Hi okay one time I ran into a number problem that went something like this: “How many (natural) numbers less than or equal to one million are there whose digits add up to forty-two?”
Okay let’s solve this using Racket. Racket is a maybe a LISP. In LISP, pretty much the only thing that matters is you have to use parentheses.
Parentheses essentially are the basis of computation.
―Robert Constable, 8 minutes or so into this OPLSS 2015 lecture
Anyway we can stare at this problem for a while and then notice three things.
So. We only need to care about numbers that have six digits, and if every digit is seven they add up to forty-two. More, if the digits in a number are “balanced around seven” they also add up to forty-two. (A six can be made up for by an eight, a three by two nines, and so on.)
Okay so that’s extremely good to know. We pretty much just wanna balance stuff. And parentheses are like incredibly good things to balance.
Racket comes with a read-procedure. read reads an expression from something, and it makes sure parentheses are balanced. Problem solved, then, more or less...
We need some halp. read-string
will read
a string until its end. If any parentheses are out of balance, read will throw and the with-handlers-bit
will catch and make it so that we return the number zero. Otherwise one.
Woop woop. We can use read-string
to kind of check if a string has balanced parentheses. If we can turn numbers into strings, so that a string only has balanced parentheses in it if the digits in the number add up to forty-two, then stuff.
number->chars
will turn a number into a list of characters, maybe padded with some zeroes:
Now we can have one character for every digit in a number. We make a char->string
-function that will turn a character like that into a string. The string will have parentheses that are just as much balanced as the digit was balanced around seven:
So, in order to turn a number into a good string, we use number->chars
, then char->string
each digit-character. And then adjust as necessary: We will sort the characters in the string so that any left parentheses come before any right parentheses. number->string
does:
Now all that remains is to pick the numbers we care about, then feed to read-string
the strings we get by applying number->string
. read-string
should return one if things are balanced and zero if not, so if we add together all those zeroes and ones we’re good.
You can get the full program at blah. Put it into your DrRacket, press F5 or so, and voi—some 20 seconds wait—là, you will have an answer.