March 1, 2019

Last week I gave a rather silly solution to the Scrabble problem. Today’s exercise is my penance for that silliness.

As I’ve mentioned previously, my day job is on a team of programmers that supports our enterprise-wide computer system. I sit in a cube farm, where there is neither audible nor visual privacy. We recently hired a new programmer to replace a retiring team member, and he has a daily calendar on his desk that provides a jumbled series of letters that you have to rearrange to form a word. Yesterday’s puzzle was L T E A D E; most of the puzzles I solve in a few seconds, but that one took several minutes. The calendar appears to have a flaw: the solutions, one day after the next, are in alphabetical order, so I know before I start that the first letter will be E.

Your task is to write a program that solves jumbles. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.


Pages: 1 2

9 Responses to “Jumble”

  1. James Curtis-Smith said

    I was really happy to get this one right…. although I came up with an archaic one as there is also a solution starting with “d”…

    my $x = lc join q(), grep { m{\S} } sort split //, join q(), @ARGV;
    open my $F,q(<),q(/usr/share/dict/british-english-insane);
    while(<$F>) {
      next unless $x eq lc join q(), sort split //;
      print "$_\n" 
    > perl jumble.pl  L T E A D E
  2. programmingpraxis said

    delate (verb)

    1. report (an offense or crime): “they may delate my slackness to my patron”
    2. inform against or denounce (someone): “they deliberated together on delating her as a witch”
  3. V said

    Quick one in Ruby.

    def jumble(word, dict)
      chars = word.downcase.chars.sort
      dict.select do |w|
        chars.size == w.size && chars == w.downcase.chars.sort
    # Dictionary words form macOS
    words = File.readlines("/usr/share/dict/words")
    puts jumble('LTEADE', words)  


  4. Globules said

    A Haskell version.

    import           Control.Monad (forM_)
    import           Data.List (sort)
    import           Data.Maybe (fromMaybe)
    import           Data.Map (Map)
    import qualified Data.Map as M
    import           Data.Text (Text)
    import qualified Data.Text as T
    import qualified Data.Text.IO as TIO
    import           System.Environment (getArgs)
    import           Text.Printf (printf)
    type Dict = Map Text [Text]
    unjumble :: Dict -> Text -> [Text]
    unjumble dict letters = fromMaybe [] $ M.lookup (canon letters) dict
    unjumblePrint :: Dict -> Text -> IO ()
    unjumblePrint dict letters = do
      let matches = unjumble dict letters
      printf "%s: %s\n" letters (T.unwords matches)
    canon :: Text -> Text
    canon = T.pack . sort . T.unpack . T.toLower
    dictionaryFrom :: FilePath -> IO Dict
    dictionaryFrom path = dictFrom . T.words <$> TIO.readFile path
      where dictFrom = M.fromListWith (++) . map letterSort
            letterSort word = (canon word, [word])
    main :: IO ()
    main = do
      dict <- dictionaryFrom "/usr/share/dict/words"
      args <- map T.pack <$> getArgs
      forM_ args $ unjumblePrint dict
    $ ./jumble lteade dbeia groegj slenet nargo
    lteade: elated delate
    dbeia: abide
    groegj: jogger
    slenet: nestle
    nargo: Ronga rogan organ orang Orang nagor groan grano goran argon angor
  5. Smith said

    Has an option to specify what the word starts with.

    def jumble(letters='lteade', startswith=''):
        from collections import Counter
        length = len(letters)
        letters = Counter(letters)
        prior = lambda w: w.startswith(startswith)
        is_length = lambda w: len(w) == length
        clean = lambda w: w.strip().lower()
        def is_valid(word):
            word = Counter(word)
            return sum(map(lambda c: c > 0, word.values())) == 0
        dictionary = open('/usr/share/dict/words')
        if len(startswith): dictionary = filter(prior, dictionary)
        return filter(is_valid, filter(is_length, map(clean, dictionary))) 
    print(list(jumble('lteade', 'e')))
    print(list(jumble('lteade', '')))
    ['delate', 'elated']
  6. Daniel said

    Here’s a solution in Python.

    from collections import Counter
    puzzle = 'LTEADE'
    with open('/usr/share/dict/words') as f:
        for line in f:
            word = line.strip()
            if Counter(word.upper()) == Counter(puzzle):


  7. faeredia said

    Solution with gawk, posix awk doesn’t have asort, BYO to make it more portable.

    #! /usr/bin/gawk -f

    jumble - solves a jumbled word puzzle

    usage: jumble [-v puzzle="XXX"] [path/to/dictionary]

    BEGIN {
    if( puzzle == "" ) puzzle = "LTEADE"
    split(puzzle, puzzle_arr, "")
    puzzle_len = asort(puzzle_arr)

    if( length($0) != puzzle_len ) next
    split($0, test_arr, "")
    for( i = 1 ; i <= puzzle_len ; i++ )
    if( test_arr[i] != puzzle_arr[i] ) next
    print FILENAME ": " $0

    In action:
    ./jumble.awk -v puzzle="LTEADE" /usr/share/dict/*
    /usr/share/dict/american-english: elated
    /usr/share/dict/british: elated
    /usr/share/dict/british-english: elated
    /usr/share/dict/catala: delate
    /usr/share/dict/catalan: delate
    /usr/share/dict/german: adelte
    /usr/share/dict/german: dealte
    /usr/share/dict/german: tadele
    /usr/share/dict/ngerman: adelte
    /usr/share/dict/ngerman: dealte
    /usr/share/dict/ngerman: tadele
    /usr/share/dict/usa: elated
    /usr/share/dict/words: elated

  8. […] exercise was posted over at ProgrammingPraxis called […]

  9. Steve said

    Klong version (#5)

    :"Shuffle letters"
    p::{[l]; l::x@<x; print(l); p2(l; 2)}
    :"If there is a larger # in sublist than the 1st # in sublist..."
    p2::{[ns]; :[0=""=ns::news((-y)#x); p2a(x; ns; y); p2b(x; y)]}
    :"Get print new list, and call p2 with it"
    p2a::{[l n]; n::(#x)-z; print(l::(n#x),y); p2(l; 2)}
    :"n++; If n<=length(list), p2(list; n)"
    p2b::{[n]; :[0=(n::y+1)>#x; p2(x;n); n::n]}
    :"Filter a list of number based upon given function"
    filter::{[func]; func::x; y@&func'y}
    :"Print word match"
    print::{:[0=.sys("grep -q ^",x,"$ /usr/share/dict/words"); .p(x); ""]} 
    :"Return new sublist or ''"
    news::{[f f2 p s]; s::x; f::*s; f2::filter({x>f}; s); :[0=f2=""; news2(s; f2@<f2); ""]}
    :"Return new sublist"        
    news2::{[f2 i p s s2]; s::x; f2::y; p::(s?f2@0)@0; i::-1; (*f2),s2@<s2::filter({x; i::i+1; 0=i=p}; s)}
        {.p(""); .p(x,":"); p(x)}'["lteade" "dbeia" "groegj" "slenet" "nargo"];.p(""); "** Done **"






    “** Done **”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: