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\$
  • 4
    \$\begingroup\$ Can use a decimal point after the first number even if it isn't required? \$\endgroup\$ – Dennis Jun 19 '15 at 17:49
  • 1
    \$\begingroup\$ Do we have to type 0.7734 for hello or would .7734 be acceptable? \$\endgroup\$ – Dennis Jun 19 '15 at 17:54
  • 3
    \$\begingroup\$ What is the correct behaviour if the dictionary contains words with upper case, punctuation, etc? \$\endgroup\$ – Peter Taylor Jun 19 '15 at 18:00
  • 1
    \$\begingroup\$ @Dennis 0.7734 is required \$\endgroup\$ – Beta Decay Jun 19 '15 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 '15 at 20:25

13 Answers 13

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\$
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\$
  • \$\begingroup\$ "Belie" and "Belies" are words? The more you know... \$\endgroup\$ – Qwerp-Derp Mar 16 '16 at 6:17
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\$
  • \$\begingroup\$ I don't know a lot of Python, but wouldn't something like "oizehsglb".index(b) be shorter? \$\endgroup\$ – Dennis Jun 19 '15 at 18:20
  • 3
    \$\begingroup\$ d[b] == "oizehsglb".index(b). Possibly lacking a cast to string/character. \$\endgroup\$ – Dennis Jun 19 '15 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 '15 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 '15 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 '15 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\$
  • \$\begingroup\$ What happens with t('Impossible')? \$\endgroup\$ – Arturo Torres Sánchez Jun 21 '15 at 0:31
  • \$\begingroup\$ @ArturoTorresSánchez You're right, I've fixed that \$\endgroup\$ – Downgoat Jun 21 '15 at 15:24
  • \$\begingroup\$ is join`` ES2015 or is it pre-ES2015? \$\endgroup\$ – WallyWest Jul 14 '15 at 1:41
  • \$\begingroup\$ @WallyWest That's an ES6 feature. It's supported in most major browsers \$\endgroup\$ – Downgoat Jul 24 '15 at 22:48
  • \$\begingroup\$ What is ES7 specific in this? \$\endgroup\$ – Arjun May 29 '16 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\$
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\$
2
\$\begingroup\$

TI-BASIC, 75 88 bytes

edit 2: never mind, this is still technically invalid, as it only accepts one word at a time (not a dictionary). I'll try to fix it to allow more than one word as input...

edit: oops; I originally made it show a .0 at the end if the last number was 0, not the other way around. Fixed, although this is a kinda bad workaround (displays "0." alongside the number if it starts with 0, otherwise displays two spaces in the same place). On the bright side, it correctly handles words like "Otto" (displays both 0s) since it's not actually displaying a decimal number!


I can't think of a better language to do this in. Can definitely be golfed more, but I'm too tired right now. The tilde is the negation symbol [the ( - ) button].

Input is taken from the calculator's answer variable, meaning whatever was last evaluated (like _ in the interactive python shell) so you have to type a string on the homescreen (quote mark is on ALPHA+), press ENTER, then run the program. Alternatively, you can use a colon to separate commands, so if you name the program, say, "CALCTEXT" and you want to run it on the string "HELLO", you can type "HELLO":prgmCALCTEXT instead of doing them separately.

seq(inString("OIZEHSGLB",sub(Ans,X,1))-1,X,length(Ans),1,~1
Text(0,0,sub("0.  ",1+2(0 or Ans(1)),2),sum(seq(Ans(X)10^(dim(Ans)-X),X,1,dim(Ans
\$\endgroup\$
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\$
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\$
  • \$\begingroup\$ In this case =="" can be replaced with <?A. And no need for gsub() as sub() is enough. \$\endgroup\$ – manatwork Jun 20 '15 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\$
  • 1
    \$\begingroup\$ Won't *s|32 work as lowercase conversion in this context? \$\endgroup\$ – Hagen von Eitzen Jun 21 '15 at 13:50
  • \$\begingroup\$ Great idea! Thanks! \$\endgroup\$ – some user Jun 21 '15 at 23:34
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\$
0
\$\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\$
  • \$\begingroup\$ You can save 7 bytes by changing ;String l= to ,l= and =o+ to +=. \$\endgroup\$ – LegionMammal978 Jun 20 '15 at 18:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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