Location: Atlantis, Spiky Tower
Depth: 470

Solution to UKACD

by Iolanthe Chronis and Brad Stronger

Answer: FRUMPISH

This puzzle is a list of words named UKACD.txt. It is very similar to the real UKACD, but in the difference lies the solution.

The puzzle is constructed using the following algorithm.
1. Take the UKACD, and exclude all words containing F.
2. Then add back all words containing FR (words containing both F and R)
3. Then remove all words containing FRU
4. Then add back all words containing FRUM
5. Then remove all words containing FRUMP
6. Then add back all words containing FRUMPI
7. Then remove all words containing FRUMPIS
8. Then add back all words containing FRUMPISH (including frumpish, trumpet-fish, etc.)

The way to solve this is to have an evolving hypothesis as to how the list was generated. Repeatedly calculate what the puzzle would look like under that hypothesis, find the difference, and calculate a new hypothesis. An annotated shell session is below.

# puzzle.txt is the puzzle, ukacd.txt is the real UKACD
diff puzzle.txt ukacd.txt | grep "<"
# -> nothing, therefore the puzzle is a strict subset of UKACD
diff puzzle.txt ukacd.txt | grep ">"
# -> words with "f"
diff puzzle.txt ukacd.txt | grep ">" | sed 's/> \(.*\)/\1/' > 1F.txt
# store the current work in 1F.txt
grep -i "f" ukacd.txt > UKACD-F.txt

The puzzle appears to be missing a lot of "f" words from UKACD. But is it missing all of them? 1F.txt is the list of missing words, so we've generated the list of F words. Let's compare them.

diff 1F.txt UKACD-F.txt | grep "<" # nothing
diff 1F.txt UKACD-F.txt | grep ">"
# -> words with "f" and "r"
diff 1F.txt UKACD-F.txt | grep ">" | sed 's/> \(.*\)/\1/' > 2FR.txt
grep -i "r" UKACD-F.txt > UKACD-FR.txt

So we see that it was missing the F words, but was not missing the FR words. But was it "not missing" all the FR words? We can continue this process for several more letters.

diff 2FR.txt UKACD-FR.txt | grep "<" # nothing
diff 2FR.txt UKACD-FR.txt | grep ">"
# -> words with "f" and "r" and "u"
diff 2FR.txt UKACD-FR.txt | grep ">" | sed 's/> \(.*\)/\1/' > 3FRU.txt
grep -i "u" UKACD-FR.txt > UKACD-FRU.txt

diff 3FRU.txt UKACD-FRU.txt | grep "<" # nothing
diff 3FRU.txt UKACD-FRU.txt | grep ">"
# -> words with f,r,u,m
diff 3FRU.txt UKACD-FRU.txt | grep ">" | sed 's/> \(.*\)/\1/' > 4FRUM.txt
grep -i "m" UKACD-FRU.txt > UKACD-FRUM.txt

diff 4FRUM.txt UKACD-FRUM.txt | grep "<" # nothing
diff 4FRUM.txt UKACD-FRUM.txt | grep ">"
# -> words with f,r,u,m,p
diff 4FRUM.txt UKACD-FRUM.txt | grep ">" | sed 's/> \(.*\)/\1/' > 5FRUMP.txt
grep -i "p" UKACD-FRUM.txt > UKACD-FRUMP.txt

diff 5FRUMP.txt UKACD-FRUMP.txt | grep "<" # nothing
diff 5FRUMP.txt UKACD-FRUMP.txt | grep ">"
# -> words with f,r,u,m,p,i
diff 5FRUMP.txt UKACD-FRUMP.txt | grep ">" | sed 's/> \(.*\)/\1/' > 6FRUMPI.txt
grep -i "i" UKACD-FRUMP.txt > UKACD-FRUMPI.txt

diff 6FRUMPI.txt UKACD-FRUMPI.txt | grep "<" # nothing
diff 6FRUMPI.txt UKACD-FRUMPI.txt | grep ">"
# -> words with f,r,u,m,p,i,s
diff 6FRUMPI.txt UKACD-FRUMPI.txt | grep ">" | sed 's/> \(.*\)/\1/' > 7FRUMPIS.txt
grep -i "s" UKACD-FRUMPI.txt > UKACD-FRUMPIS.txt

diff 7FRUMPIS.txt UKACD-FRUMPIS.txt | grep "<" # nothing
diff 7FRUMPIS.txt UKACD-FRUMPIS.txt | grep ">"
# -> words with f,r,u,m,p,i,s,h
diff 7FRUMPIS.txt UKACD-FRUMPIS.txt | grep ">" | sed 's/> \(.*\)/\1/' > 8FRUMPISH.txt
grep -i "h" UKACD-FRUMPIS.txt > UKACD-FRUMPISH.txt

diff 8FRUMPISH.txt UKACD-FRUMPISH.txt | grep "<" # nothing
diff 8FRUMPISH.txt UKACD-FRUMPISH.txt | grep ">"
# -> nothing, thus our hypothesis is finally accurate, and FRUMPISH is the answer