Location: Coral Reef
Depth: 80

Solution to A Puzzle Consisting Entirely of Random Anagrams

by Brian Chen


The solver is confronted with a bunch of anagrams of the word "RANDOM".

The word "anagram" is used quite loosely; they're just permutations of the six letters in "RANDOM", which look pretty random. However, all of them start with "A", which suggests that whatever mechanism is being used is heavily biased towards using anagrams of "RANDOM" that come alphabetically early. So, the solver should naturally be led to determine how early, or more precisely, the index of the permutation in an alphabetical list of all 720 anagrams of "RANDOM". Note that this index is zero-indexed, which is slightly more natural to compute and also fits with the encoding that gives the indices meaning.

After this is done, the list of indices can be seen to mostly be in the 65~90 range, with a few 10s and 32s. As these numbers line up nicely with the ASCII newline, space, and uppercase letters, this should suggest converting the numbers to ASCII. If this is done, the result additionally starts with "YOU ARE ON THE RIGHT TRACK" as extra confirmation. (These confirmations should also allow any off-by-one errors in deciding whether to start the indexing at 0 or 1 to be resolved.) This is the full result:

After the confirmational message, the result of the first decryption is a bunch of other "anagrams". They are not anagrams of the word "RANDOM", but they can be decrypted to indices and then ASCII in the same way to yield another message:

(Note that duplicate letters in the word being permuted should be considered the same, so e.g. there are only 3 anagrams of "see" and "see" is the last, i.e. index 2. This is the only way the index and ASCII would be uniquely specified. It does mean that a program for solving this part will have to be more complex than a program that only has to solve the first stage.)

The next thing to do is to actually solve the anagrams themselves, producing words that form mostly unambiguous clues, one clue per line. This is not difficult with any online anagram solver, although a few of the proper nouns may slip through the solvers' word lists and need to be solved manually. (It may also be possible to brute-force the possiblities after the expected form of the result is determined.)

Putting these words through the same anagram-to-ASCII process produces a string of digits.

The digits spell out the number 2896836569686226.

The solver should now realize that this is the NUMBER referred to in the previous message, and the two should be combined by applying the indexing procedure one last time, just in reverse. In other words, the solver must find the anagram that is index 2896836569686226 of "ACCCCEGIILMMOOOORSTWY".

This produces the cluephrase "CLOWESCOMICORMAGICTOY", cluing EIGHT BALL, the answer.

Appendix. The author's Haskell program for solving this puzzle follows:

/* Generated by pandoc. */
    -- solver.hs
    import Data.Char
    import Data.List

    factorial :: Integer -> Integer
    factorial n = product [1..n]

    maybeLast :: [a] -> Maybe a
    maybeLast [] = Nothing
    maybeLast [x] = Just x
    maybeLast (_:xs) = maybeLast xs

    -- Given a list of frequencies of objects, count permutations of said objects
    groupPerms :: [Integer] -> Integer
    groupPerms fs = factorial (sum fs) `quot` product (map factorial fs)

    -- Given a word, count how many permutations it has
    lexCount :: (Ord a) => [a] -> Integer
    lexCount ss = groupPerms . map genericLength . group $ sort ss

    -- Given an index and a string, try to index into the lexicographical dictionary of the string's permutations
    lexAt :: (Ord a) => Integer -> [a] -> Maybe [a]
    lexAt 0 [] = Just []
    lexAt _ [] = Nothing
    lexAt ix ss = let cs = nub (sort ss) in do
        (ch, n) <- maybeLast . takeWhile ((<= ix) . snd) . zip cs . scanl (+) 0 $ map (lexCount . (`delete` ss)) cs
        res <- lexAt (ix - n) (ch `delete` ss)
        return $ ch : res

    -- Given a word, figure out its index in a lexicographical dictionary of its permutations
    lexIndex :: (Ord a) => [a] -> Integer
    lexIndex [] = 0
    lexIndex [_] = 0
    lexIndex (x:xs) = (sum . map (lexCount . (`delete` (x:xs))) . filter (< x) . nub $ sort xs) + lexIndex xs

    main :: IO ()
    main = interact $ (++ "\n") . map (chr . fromIntegral . lexIndex) . words

    result1 :: Maybe String
    result1 = lexAt 2896836569686226 "ACCCCEGIILMMOOOORSTWY"

The program takes as input a list of words and does one pass of indexing and converting to ASCII. So, for example, this shell command will extract the message containing the character bank for the final anagram:

    $ runhaskell solver.hs < puzzle | tail -n +3 | runhaskell solver.hs