# Code Golf: Word Unscrambler

Write a program that either accepts input via stdin or from the command line. It will then unscramble the words, printing out the unscrambled version of each word.You get a text file containing every word (most of them) in the English dictionary to use. (Here is the file: Word List, and you can either use it from the web or save it as a text file and use it from there.)

## Inputs to measure the score:

bbuleb lwrfoe kaec rtawe cokr kmli pcaee

## Correct Outputs:

bubble flower cake water rock milk peace

bubble fowler cake water cork milk peace

## Scoring:

Score = (Amount of correct outputs) x (100 / (Code Length))

The code with the highest score wins!

Edit: This is my first post, please be kind!

• Scoring is suboptimal. say 'bubble flower cake water rock milk peace' scores hard-to-beat 213 and yet isn't very interesting. – J B Mar 13 '12 at 10:17
• Many scrambles have multiple correct unscrambles...I mean "opst" could easily be "stop" or "pots" or "post" or "tops". – dmckee --- ex-moderator kitten Mar 13 '12 at 14:01
• I notice that all answers so far have loaded the wordlist from the web. Is there any requirement that the file cannot be local? – Steven Rumbalski Mar 13 '12 at 19:36
• @StevenRumbalski No, you can either use it from the web or locally. – 3aw5TZetdf Mar 13 '12 at 20:29
• @StevenRumbalski fowler and cork is considered correct output and the inputs can be the same case as the word life. (Will edit the post about the correct outputs) – 3aw5TZetdf Mar 14 '12 at 1:17

## GolfScript, 27 chars, 7 correct outputs ⇒ score ≈ 25.926

n%(\:w;' '%{$:c;w{$c=}?}%n*


GolfScript doesn't have a file I/O operator, so I had to get a bit clever with the input. Specifically,

• the scrambled words should be given on the first input line, separated by spaces, and
• the wordlist should be given on the subsequent input lines, one word per line.

The scrambled words and the wordlist need to have the same letter case.

Here's an example invocation from a Unix shell command line, assuming that the code above has been saved as unscramble.gs, the GolfScript interpreter as golfscript.rb and the wordlist as wordlist.txt:

(echo BBULEB LWRFOE KAEC RTAWE COKR KMLI PCAEE; cat wordlist.txt) \
| ruby golfscript.rb unscramble.gs


This will produce the following output:

BUBBLE
FLOWER
CAKE
WATER
CORK
MILK
PEACE


The way it works is simply by sorting the letters in each input word and selecting the first word in the wordlist that produces the same string when its letters are sorted. Nearly half of the code is actually just for input parsing (and output formatting): all the real work is done in the {$:c;w{$c=}?}% loop.

Here's a de-golfed version with comments showing how it works:

n %                 # split the input on newlines
( \ :w ;            # pop the first line off the list of lines and assign the rest to w
' ' %               # split the first line on spaces

# apply the following map to each scrambled word:
{
$:c ; # sort the letters in the word and assign the sorted word to c w {$ c = } ?   # find the first word in w that, sorted, equals c
} %

n *                 # join the results with newlines for output

• Wow, this answer is amazing! – 3aw5TZetdf Mar 28 '12 at 7:01

## Python 3 / 84 chars / 7 correct outputs / score 8.3333

edit As per clarifications, removed .upper() and considering all 7 ouputs correct.

a=sorted
for b in input().split():print([c for c in open('x')if a(b)==a(c[:-1])][0])


Output:

BUBBLE
FLOWER
CAKE
WATER
CORK
MILK
PEACE


## Python, 189171 156 chars / 6 7 correct outputs / "spirit of the law"

from urllib import*
z=sorted
x=dict((z(m),m)for m in urlopen("http://bit.ly/wZYCmE").read().split())
for n in raw_input().split():print x[z(n.upper())]


(It gets "fowler" instead of "flower", both are on the input list and have the same letters.)

Edit: Steven Rumbalski's suggestions

## Python, 144 chars / 7 correct outputs / "letter of the law"

for x in raw_input().split():print{620:'bubble',655:'flower',404:'cake',547:'water',431:'rock',429:'milk',510:'peace'}[sum(map(ord,x.lower()))]

• x=dict((z(m),m)for m in urlopen("http://bit.lywZYCmE").read().split()) – Steven Rumbalski Mar 13 '12 at 19:43
• z=lambda p:tuple(sorted(p)) – Steven Rumbalski Mar 13 '12 at 19:47
• Since you are using Python 2, you can save by taking advantage of backticks. Have z=sorted, then instead of z(m) use z(m) – Steven Rumbalski Mar 13 '12 at 22:31

### bash, grep, sed, sort: 144 chars, 144/7=20.57 (all correct)

s(){
echo $1|sed 's/./\n&/g'|sort } for w in$*
do
for m in $(egrep "^["$w"]{"${#w}"}$" d)
do
[[ s $w = s$m ]] &&(echo $m;break) done done  d is the filename of the dict; for testing on Linux replace it with $d as d=/usr/share/dict/words and subtract 1 from the filesize, to avoid a local copy.

usage:

./unscramble.sh bbuleb lwrfoe kaec rtawe cokr kmli pcaee
bubble
flower
cake
water
cork
rock
milk
peace


works well with dict/words, so I didn't download anything, lazy me! :)

## Perl, 173 characters / 6 correct outputs

use LWP::Simple;
sub e{my$m;$m.=$_ for sort split//,uc$_[0];$m}$_=get"http://bit.ly/wZYCmE";
@x=split/\n/;$_=<>;for(split){$l=$_;for(@x){print"$_ ",$l=''if(e$_)eq e$l}}  ## JavaScript, 357 330 chars [node.js] / 7 correct outputs function g(w,s){return s===+s?g[a=w.toUpperCase().split("").sort().join("")]=g[a]||w:w.split("\n").map(g)&&s.split(" ").map(g).join(" ")}require('http').get({host:'web.mit.edu',path:'/kilroi/Public/bot/wordlist'},function(r){b=[];function f(c){c?b.push(c):console.log(g(b.join(""),process.argv[2]))}r.on('data',f),r.on('end',f)})  Eugh... slightly prettier version below. Doesn't read from stdin (string to check is first command-line argument), but it does fetch the dictionary from the net. The g function receives a string with the dictionary content (w) and a string to check (s); this is the most interesting part I suppose. (It should theoretically work on any input string, as long as there's a permutation of each word in the dictionary. Oh, and the output is currently upper-case [as it is in the dictionary]) function g(w,s) { return s===+s ? g[a=w.toUpperCase().split("").sort().join("")] = g[a] || w : w.split("\n").map(g) && s.split(" ").map(g).join(" ") } require('http').get({host:'web.mit.edu',path:'/kilroi/Public/bot/wordlist'}, function(r) { b=[] function f(c) { c ? b.push(c) : console.log(g(b.join(""), process.argv[2])) } r.on('data',f) r.on('end',f) })  # Q,38 chars, 7 correct, 18.42105 points {1#d(&)1=asc[x]~/:(asc')d:(_)read0:d}  d is the dictionary file, stored locally in the same working directory. usage: {1#d(&)1=asc[x]~/:(asc')d:(_)read0:d} each ("bbuleb";"lwrfoe";"kaec";"rtawe";"cokr";"kmli";"pcaee") "bubble" "flower" "cake" "water" "cork" "milk" "peace"  ## PHP 270bytes Source. SCORE- ? I'm not sure if if this type of output is accepted, please inform if its wrong. <?$s=explode(PHP_EOL,file_get_contents('http://bit.ly/wZYCmE'));$n=explode(' ',$argv[1]);for($i=0;$i<count($n);$i++){$f=0;for($j=0;$j<count($s);$j++){$t1=str_split(trim($n[$i]));sort($t1);$t2=str_split($s[$j]);sort($t2);if($t1==$t2){$f++?echo'/':0;echo$s[$j];}}echo' ';}


Run:

php unscramble.php "BBULEB LWRFOE KAEC RTAWE COKR KMLI PCAEE"


Output:

BUBBLE FLOWER/FOWLER CAKE WATER CORK/KROC/ROCK MILK PEACE

• It has the right output! – 3aw5TZetdf Apr 26 '12 at 21:52

# Jelly, 14 bytes, 7 correct outputs ⇒ score = 50 (Feedback appreciated!)

ɠḲ©µ³ḲŒ!f®ḢƊ€K


Try it online! (Long URL)

Feed space-separated dictionary on stdin and space-separated scrambled words as the first argument, e.g. curl http://web.mit.edu/kilroi/Public/bot/wordlist | tr '\n' ' ' | jelly fun unscrambler.j "BBULEB LWRFOE KAEC RTAWE COKR KMLI PCAEE"

ɠḲ©µ³ḲŒ!f®ḢƊ€K
ɠḲ©µ               read the dictionary from stdin splitting on spaces, and save it to the register
³Ḳ             split the scrambled word list argument on spaces
Ɗ      define a function of the previous three links taking an input W:
Œ!f®        get all permutations of W, and filter it with the dictionary
(aka, remove all words in the dictionary that are not permutations of W)
Ḣ       take the head, so we return just one unscrambled word per scrambled word
€K    run that Ɗ function on each of the unscrambled words, and split the results with spaces

• In Jelly, taking input from whatever source is most convenient, and in whatever form is most convenient, can matter a lot. STDIN is pretty clunky. If you put the dictionary in ⁴ you can get rid of the register (11 bytes); if you take input as lists you get 8 bytes – Lynn May 9 '18 at 10:37

# Zsh, 129 chars / 7 correct outputs ⇒ score ≈ 5.426

for i in $@ do while read w do [[${#w} == ${#i} ]]&&[[${${(Lo)${(s::)w}}} == ${${(Lo)${(s::)i}}} ]]&&echo$w&&break
done<d
done


Usage:

Save the word list as d in the same directory as the script, and from that directory run

% zsh ./unscramble.zsh bbuleb lwrfoe kaec rtawe cokr kmli pcaee
BUBBLE
FLOWER
CAKE
WATER
CORK
MILK
PEACE


How it works:

(s::) splits into single-character words

(L) lowercases

(o) sorts ascending

Was inspired to try after reading this blog post. Not golf, but a fun survey. (Disclaimer: the article's from one of the other teams at my workplace.)