For once I decided to forego Python in favour of pencil and paper, as an attempt at that “pure” solving experience. I wrote out some tables of the numbers I needed (1-19, 20-90 in tens, HUNDRED and AND), along with their two associated numbers. After that it became fairly easy to combine them when I wanted to test a number (the unique-letter parts taking longer as I couldn’t always use the crib sheet).

After solving I used Python to check all my answers satisfied the clues. I replicated my tables (mapping numbers to words; the code did all the sums) then wrote a short function to turn a given number into a phrase — not as hard as it sounds:

* If the number is at least 100, it must start with (the word for) a single digit and the word HUNDRED.

* If the number is not an exact multiple of 100, it must then have the word AND.

* Whatever has happened above, the hundreds part of the number can be discarded.

* If the (hundreds-less) number is twenty or more, count the tens and look up the -TY word in a table. Discard the tens part in this case.

* Whatever’s left is either a number less than twenty, or a number less than ten plus the -TY word we got above. Look up the word in a table.

This turns 125 into “ONEHUNDREDANDTWENTYFIVE”. The length is then easy in Python – ‘len(NUMBER_STRING)’ – and so is the awkward total. Assuming a lookup table of letters to numbers (but the ASCII subtraction trick is just as good), it’s ‘sum(LETTER_VALUES[l] for l in set(NUMBER_STRING))’ (‘set’ discards the duplicates).

At this point I just wrote out one more table of clue letters to my answers, and ran the code on it so I could visually check all the clues were satisfied. I imagine it would have been possible to build a solver this way too though — programming in more tables of clue expressions and of entry digit relationships. I’ve solved a few numerics with help from Python, usually to do the heavy lifting on an answer check (or to break something if it looks like brute force is required, usually meaning I’ve missed a more elegant trick) but haven’t yet gone as far as utilising a general constraint solver like that. One day I’ll find the time to try it out!

For fun I tried starting something in Excel. With sheets named UnderTwenty and Tens, each containing a table mapping numbers to words (with headings, so the data started at A2 in both cases), I then made a third sheet with row 2 like this:

A: (number to decompose, to be entered)

B: hundreds value: =FLOOR(A2/100, 1)

C: remainder after hundreds removed: =MOD(A2, 100)

D: tens value if at least twenty (ie not 10 itself): =IF(C2>=20,FLOOR(C2/10, 1), 0)*10

E: units-or-teens value (ie whatever is under 20): =IF(C2>=20,MOD(C2, 10),MOD(C2, 20))

F: Number of hundreds: =IF(B2>0,VLOOKUP(B2,UnderTwenty!$A$2:$B$20,2,FALSE),””)

G: HUNDRED if needed: =IF(B2>0,”hundred”,””)

H: AND if needed: =IF(AND(MOD(A2, 100)0, A2>=100),”and”,””)

I: -TY word: =IF(D20,VLOOKUP(D2,Tens!$A$2:$B$9,2,FALSE),””)

J: The rest: =IF(E20,VLOOKUP(E2,UnderTwenty!$A$2:$B$20,2,FALSE),””)

K: All together: =CONCAT(F2:J2)

Copy the row down and every number from 1-999 that you enter in column A will be described in words in column K. At this point, getting the length should be easy, but I believe getting the unique letters requires a bit of VBA (basically, defining your own function). Could be worth doing though as with that done, any number can be turned into any pair of length/unique-value-sum numbers at will. (Or you can make 253 rows, fill the first column with numbers 1-253, and just use the whole sheet as a manual lookup table.)

]]>