32
\$\begingroup\$

In schools across the world, children type a number into their LCD calculator, turn it upside down and erupt into laughter after creating the word 'Boobies'. Of course, this is the most popular word, but there are many other words which can be produced.

All words must be less than 10 letters long, however (the dictionary does contain words long than this however, so you must perform a filter in your program). In this dictionary, there are some uppercase words, so convert the all words the lowercase.

Using, an English language dictionary, create a list of numbers which can be typed into an LCD calculator and makes a word. As with all code golf questions, the shortest program to complete this task wins.

For my tests, I used the UNIX wordlist, gathered by typing:

ln -s /usr/dict/words w.txt

Or alternatively, get it here.

For example, the image above was created by typing the number 35007 into the calculator and turning it upside down.

The letters and their respective numbers:

  • b: 8
  • g: 6
  • l: 7
  • i: 1
  • o: 0
  • s: 5
  • z: 2
  • h: 4
  • e: 3

Note that if the number starts with a zero, a decimal point is required after that zero. The number must not start with a decimal point.

I think this is MartinBüttner's code, just wanted to credit you for it :)

/* Configuration */

var QUESTION_ID = 51871; // Obtain this from the url
// It will be like http://XYZ.stackexchange.com/questions/QUESTION_ID/... on any question page
var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";

/* App */

var answers = [], page = 1;

function answersUrl(index) {
  return "http://api.stackexchange.com/2.2/questions/" +  QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER;
}

function getAnswers() {
  jQuery.ajax({
    url: answersUrl(page++),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      answers.push.apply(answers, data.items);
      if (data.has_more) getAnswers();
      else process();
    }
  });
}

getAnswers();

var SIZE_REG = /\d+(?=[^\d&]*(?:<(?:s>[^&]*<\/s>|[^&]+>)[^\d&]*)*$)/;
var NUMBER_REG = /\d+/;
var LANGUAGE_REG = /^#*\s*([^,]+)/;

function shouldHaveHeading(a) {
  var pass = false;
  var lines = a.body_markdown.split("\n");
  try {
    pass |= /^#/.test(a.body_markdown);
    pass |= ["-", "="]
              .indexOf(lines[1][0]) > -1;
    pass &= LANGUAGE_REG.test(a.body_markdown);
  } catch (ex) {}
  return pass;
}

function shouldHaveScore(a) {
  var pass = false;
  try {
    pass |= SIZE_REG.test(a.body_markdown.split("\n")[0]);
  } catch (ex) {}
  return pass;
}

function getAuthorName(a) {
  return a.owner.display_name;
}

function process() {
  answers = answers.filter(shouldHaveScore)
                   .filter(shouldHaveHeading);
  answers.sort(function (a, b) {
    var aB = +(a.body_markdown.split("\n")[0].match(SIZE_REG) || [Infinity])[0],
        bB = +(b.body_markdown.split("\n")[0].match(SIZE_REG) || [Infinity])[0];
    return aB - bB
  });

  var languages = {};
  var place = 1;
  var lastSize = null;
  var lastPlace = 1;
  answers.forEach(function (a) {
    var headline = a.body_markdown.split("\n")[0];
    //console.log(a);
    var answer = jQuery("#answer-template").html();
    var num = headline.match(NUMBER_REG)[0];
    var size = (headline.match(SIZE_REG)||[0])[0];
    var language = headline.match(LANGUAGE_REG)[1];
    var user = getAuthorName(a);
    if (size != lastSize)
      lastPlace = place;
    lastSize = size;
    ++place;
    answer = answer.replace("{{PLACE}}", lastPlace + ".")
                   .replace("{{NAME}}", user)
                   .replace("{{LANGUAGE}}", language)
                   .replace("{{SIZE}}", size)
                   .replace("{{LINK}}", a.share_link);
    answer = jQuery(answer)
    jQuery("#answers").append(answer);

    languages[language] = languages[language] || {lang: language, user: user, size: size, link: a.share_link};
  });

  var langs = [];
  for (var lang in languages)
    if (languages.hasOwnProperty(lang))
      langs.push(languages[lang]);

  langs.sort(function (a, b) {
    if (a.lang > b.lang) return 1;
    if (a.lang < b.lang) return -1;
    return 0;
  });

  for (var i = 0; i < langs.length; ++i)
  {
    var language = jQuery("#language-template").html();
    var lang = langs[i];
    language = language.replace("{{LANGUAGE}}", lang.lang)
                       .replace("{{NAME}}", lang.user)
                       .replace("{{SIZE}}", lang.size)
                       .replace("{{LINK}}", lang.link);
    language = jQuery(language);
    jQuery("#languages").append(language);
  }

}
body { text-align: left !important}

#answer-list {
  padding: 10px;
  width: 50%;
  float: left;
}

#language-list {
  padding: 10px;
  width: 50%px;
  float: left;
}

table thead {
  font-weight: bold;
}

table td {
  padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b">
<div id="answer-list">
  <h2>Leaderboard</h2>
  <table class="answer-list">
    <thead>
      <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr>
    </thead>
    <tbody id="answers">

    </tbody>
  </table>
</div>
<div id="language-list">
  <h2>Winners by Language</h2>
  <table class="language-list">
    <thead>
      <tr><td>Language</td><td>User</td><td>Score</td></tr>
    </thead>
    <tbody id="languages">

    </tbody>
  </table>
</div>
<table style="display: none">
  <tbody id="answer-template">
    <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
  </tbody>
</table>
<table style="display: none">
  <tbody id="language-template">
    <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
  </tbody>
</table>

\$\endgroup\$
13
  • 4
    \$\begingroup\$ Can use a decimal point after the first number even if it isn't required? \$\endgroup\$
    – Dennis
    Jun 19, 2015 at 17:49
  • 1
    \$\begingroup\$ Do we have to type 0.7734 for hello or would .7734 be acceptable? \$\endgroup\$
    – Dennis
    Jun 19, 2015 at 17:54
  • 3
    \$\begingroup\$ What is the correct behaviour if the dictionary contains words with upper case, punctuation, etc? \$\endgroup\$ Jun 19, 2015 at 18:00
  • 1
    \$\begingroup\$ @Dennis 0.7734 is required \$\endgroup\$
    – Beta Decay
    Jun 19, 2015 at 18:15
  • 4
    \$\begingroup\$ What about words that require a trailing zero after the decimal? For example, oligo requires a trailing zero after the decimal: 0.6170 \$\endgroup\$
    – Mr. Llama
    Jun 19, 2015 at 20:25

12 Answers 12

9
\$\begingroup\$

Bash + coreutils, 54

Again, thanks to @TobySpeight for the golfing help.

rev|tr oizehsglb 0-8|sed '/.\{11\}\|[^0-9]/d;s/^0/&./'

Input wordlist is taken from STDIN:

$ ./5318008.sh < /usr/share/dict/words | head
8
38
338
5338
638
5638
36138
31738
531738
7738
$ 
\$\endgroup\$
1
  • \$\begingroup\$ "Belie" and "Belies" are words? The more you know... \$\endgroup\$
    – clismique
    Mar 16, 2016 at 6:17
7
\$\begingroup\$

CJam, 44 42 bytes

r{el"oizehsglb"f#W%"0."a.e|N+_,B<*_W&!*r}h

Try it online in the CJam interpreter.

To run the program from the command line, download the Java interpreter and execute:

java -jar cjam-0.6.5.jar 5318008.cjam < /usr/share/dict/words

How it works

r            e# Read a whitespace-separated token from STDIN.
{            e# While loop:
 el          e#   Convert to lowercase.
 "oizehsglb" e#   Push that string.
 f#          e#   Get the index of each character from the input in that string.
             e#   This pushes -1 for "not found".
 W%          e#   Reverse the resulting array.
 "0."a       e#   Push ["0."].
 .e|         e#   Vectorized logical NOT. This replaces an initial 0 with "0.".
 N+          e#   Append a linefeed.
 _,B<*       e#   Repeat the array (array.length < 11) times.
 _W&!*       e#   Repeat the array !(array.intersection(-1)) times.
 r           e#   Read a whitespace-separated token from STDIN.
}h           e# If the token is not empty, repeat the loop.
\$\endgroup\$
6
\$\begingroup\$

Python 2, 271 216 211 205 Bytes

This is the only idea I've had so far.. I will update this once I think of something else! I assumed we needed to read from a file, but if not let me know so I can update :)

Big thanks to Dennis for saving me 55 bytes :)

Also thanks to Sp3000 for saving 6 bytes :)

d,f,g='oizehsglb',[x.lower()for x in open('w.txt').read().split('\n')if len(x)<10],[]
for x in f:
 c=x[::-1]
 for b in d:c=c.replace(b,`d.find(b)`)
 g=[g,g+[['0.'+c[1:],c][c[0]!='0']]][c.isdigit()]
print g
\$\endgroup\$
8
  • \$\begingroup\$ I don't know a lot of Python, but wouldn't something like "oizehsglb".index(b) be shorter? \$\endgroup\$
    – Dennis
    Jun 19, 2015 at 18:20
  • 3
    \$\begingroup\$ d[b] == "oizehsglb".index(b). Possibly lacking a cast to string/character. \$\endgroup\$
    – Dennis
    Jun 19, 2015 at 18:29
  • 1
    \$\begingroup\$ Oh, wow, it never occurred to me that the numbers we were able to replace had numerical values in order.. Yes, that will definitely work! Thanks! \$\endgroup\$
    – Kade
    Jun 19, 2015 at 18:35
  • 1
    \$\begingroup\$ Haven't tested but: 1) .find is shorter than .index, 2) Depending on which version you have, at least in 2.7.10 open without a mode argument defaults to r, 3) Doesn't just for x in open(...) work? (may need to remove a trailing newline) If it doesn't, then .split('\n') is shorter than .splitlines() \$\endgroup\$
    – Sp3000
    Jun 20, 2015 at 1:05
  • 1
    \$\begingroup\$ Also g+=[['0.'+c[1:],c][c[0]!='0']]*c.isdigit(), and you can save a few more by reversing in f then doing for c in f instead of having c=x[::-1]. Also you only use f once, so you don't need to save it as a variable \$\endgroup\$
    – Sp3000
    Jun 20, 2015 at 3:33
6
\$\begingroup\$

JavaScript (ES7), 73 bytes

This can be done in ES7 a mere 73 bytes:

s=>[for(w of s)'oizehsglb'.search(w)].reverse().join``.replace(/^0/,'0.')

Ungolfed:

var b = function b(s) {
    return s.length < 10 && /^[bglioszhe]*$/.test(s) ? s.replace(/./g, function (w) {
        return 'oizehsglb'.search(w);
    }).reverse().join('').replace(/^0/, '0.') : '';
};

Usage:

t('hello'); // 0.7734
t('loose'); // 35007
t('impossible'); //

Function:

t=s=>                       // Create a function 't' with an argument named 's' 
   [                        // Return this array  comprehension
     for(i of s)            // Loops through each letter in the string
     'oizehsglb'.search(w)  // Converts it to it's corresponding number
   ]
  .reverse().join``         // Reverse the array and make it a string
  .replace(/^0/,'0.')       // If the first character is a 0, add a decimal after it

I ran this on the UNIX wordlist and have put the results in a paste bin:

Results

The code used to obtain the results on Firefox:

document.querySelector('pre').innerHTML.split('\n').map(i => t(i.toLowerCase())).join('\n').replace(/^\s*[\r\n]/gm, '');
\$\endgroup\$
6
  • \$\begingroup\$ What happens with t('Impossible')? \$\endgroup\$ Jun 21, 2015 at 0:31
  • \$\begingroup\$ @ArturoTorresSánchez You're right, I've fixed that \$\endgroup\$
    – Downgoat
    Jun 21, 2015 at 15:24
  • \$\begingroup\$ is join`` ES2015 or is it pre-ES2015? \$\endgroup\$ Jul 14, 2015 at 1:41
  • \$\begingroup\$ @WallyWest That's an ES6 feature. It's supported in most major browsers \$\endgroup\$
    – Downgoat
    Jul 24, 2015 at 22:48
  • \$\begingroup\$ What is ES7 specific in this? \$\endgroup\$
    – Arjun
    May 29, 2016 at 0:58
5
\$\begingroup\$

Python 2, 121 bytes

for s in open("w.txt"):
 L=map("oizehsglb".find,s[-2::-1].lower())
 if-min(L)<1>len(L)-9:print`L[0]`+"."[L[0]:]+`L`[4::3]

Assumes that the dictionary file w.txt ends with a trailing newline, and has no empty lines.

\$\endgroup\$
0
3
\$\begingroup\$

GNU sed, 82

(including 1 for -r)

Thanks to @TobySpeight for the golfing help.

s/$/:/
:
s/(.)(:.*)/\2\1/
t
s/://
y/oizehsglb/012345678/
/.{11}|[^0-9]/d;s/^0/&./

Input wordlist is taken from STDIN:

$ sed -rf 5318008.sed /usr/share/dict/words | tail
3705
53705
1705
0.705
50705
5705
505
2
0.02
5002
$ 
\$\endgroup\$
0
2
\$\begingroup\$

Python 2, 147 158 156 bytes

I was missing this '0.' requirement. Hope now it works allright.

edit: Removed ".readlines()" and it still works ;p

edit2: Removed some spaces and move print to the 3rd line

edit3: Saved 2 bytes thanks to Sp3000 (removed space after print and changed 'index' to 'find')

for x in open("w.txt"):
 a="oizehsglb";g=[`a.find(b)`for b in x[::-1].lower()if b in a]
 if len(g)==len(x)-1<10:
  if g[0]=="0":g[0]="0."
  print"".join(g)
\$\endgroup\$
0
1
\$\begingroup\$

Python 2, 184 174 bytes

for s in open('w.txt'):
 try:a=''.join(map(lambda c:dict(zip('bglioszhe','867105243'))[c],s[:-1][::-1]));a=[a,'0.'+a[1:]][a[0]=='0'];print['',''.join(a)][len(s)<11]
 except:0
\$\endgroup\$
1
\$\begingroup\$

Ruby 2, 88 86 bytes

x="oizehsglb"
puts$_.tr(x,"0-8").reverse.sub /^0/,"0." if$_.size<11&&$_.delete(x)<?A

Byte count includes 2 for the ln options on the command line:

$ ruby -ln 5318008.rb wordlist.txt
\$\endgroup\$
1
  • \$\begingroup\$ In this case =="" can be replaced with <?A. And no need for gsub() as sub() is enough. \$\endgroup\$
    – manatwork
    Jun 20, 2015 at 14:00
1
\$\begingroup\$

C, 182 172 169/181 172 bytes

char*l="oizehsglb",S[99],*s,*t;main(x){for(;t=S+98,gets(S);){for(s=S;*s;s++)if(x=strchr(l,*s|32))*--t=48+x-(int)l;else break;*t==48?*t--=46,*t=48:0;*s||s-S>10?0:puts(t);}}

Expanded

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *l="oizehsglb",S[99],*s,*t;

main(int x, char **argv)
{
    for (;t=S+98,gets(S);){
        for (s=S;*s;s++)
            if (x=strchr(l,*s|32))
                *--t=48+x-(int)l;
            else
                break;
        if (*t==48) {       // '0'
            *t--=46;        // '.'
            *t=48;  // '0'
        }

        if (!*s && s-S <= 10)
            puts(t);
    }
}

using the linked words.txt, with lower case conversion:

$ ./a.out  < words.txt  | tail
2212
0.2
0.802
0.602
7702
37702
0.02
321607002
515002
0.02002

$ ./a.out < words.txt   | wc -l
 550
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Won't *s|32 work as lowercase conversion in this context? \$\endgroup\$ Jun 21, 2015 at 13:50
  • \$\begingroup\$ Great idea! Thanks! \$\endgroup\$
    – some user
    Jun 21, 2015 at 23:34
1
\$\begingroup\$

Java, 208 200 176 bytes

String f(char[] w){String o="",l="oizehsglb";for(int i=w.length;i>0;i--)o+=l.indexOf(w[i-1]|32);if(o.contains("-")||o.length()>8)o="  ";return o.charAt(0)+"."+o.substring(1);}

Expanded

String f(char[] w)
{
    String o = "", l = "oizehsglb";
    for(int i = w.length; i > 0; i--)
        o+=l.indexOf(w[i-1]|32);
    if(o.contains("-")||o.length() > 8)
        o = "  ";
    return o.charAt(0) + "." + o.substring(1);
}

It always adds the decimal, and when invalid returns " . ". But otherwise works like it should. :P

Thanks @LegionMammal978!

\$\endgroup\$
1
  • \$\begingroup\$ You can save 7 bytes by changing ;String l= to ,l= and =o+ to +=. \$\endgroup\$ Jun 20, 2015 at 18:30
1
\$\begingroup\$

Haskell, 175 bytes without imports (229 bytes with imports)

Relevant code (say in File Calc.hs):

import Data.Char(toLower)
import Data.Maybe(mapMaybe)
s="oizehsglb\n"
g('0':r)="0."++r
g x=x
main=mapM_(putStrLn.g.reverse.mapMaybe(`lookup`zip s['0'..'8'])).filter(\l->length l<10&&all(`elem`s)l).lines.map toLower=<<getContents

$ cat /usr/share/dict/words | runghc Calc.hs
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.