GolfScript, 50 bytes
I wanted to see if I could beat Quincunx's 51-byte self-contained GolfScript solution. Turns out that, with enough tricks, yes, I can — by one byte.
Since one of the tricks I'm using is the use of bytes outside the printable ASCII range, the resulting program is cannot be directly pasted here. Instead, I'm providing a hex dump of it; users on Unixish systems can use xxd -r
to reconstruct the actual 50-byte GolfScript program from the hex dump:
0000000: 7e6e 270b 97eb 442f e166 9894 9f00 c63c ~n'...D/.f.....<
0000010: 8128 73a3 9b55 5065 a9fb f06a 2727 ff16 .(s..UPe...j''..
0000020: 277b 6261 7365 7d2f 2b6e 2f3d 7b39 392b '{base}/+n/={99+
0000030: 7d25 }%
The basic trick used to generate this program is simple: I compress the long string literal that makes up most of Quincunx's code by subtracting 99 (the ASCII code of the letter c
) from the character values, interpreting the resulting values as a number in base 22 (enough to encode the letters up to x
) and then re-encode the resulting number in base 255 to produce the unprintable byte string that makes up most of the first half of my program. The rest of the program then reverses this process, decoding the string back into something printable.
(Since the lowest letter actually present in the number names is e
, I could've shortened the byte string further by subtracting 101 from the ASCII codes and using base 20. However, subtracting 101 would've mapped the letter o
to a newline, which I'm using as the number delimiter because it's conveniently available as the built-in constant n
in GolfScript. Working around that would cost me more than the one byte that using a lower base would save. Using the offset 99 leaves the newline corresponding to the letter m
, which is conveniently absent from the number names.)
Here's a de-golfed version of the program:
~ # eval the input, turning it into a number
n # push a newline onto the stack; we'll need it later
# this is the byte string encoding the number names:
"\x0B\x97\xEBD/\xE1f\x98\x94\x9F\x00\xC6<\x81(s\xA3\x9BUPe\xA9\xFB\xF0j"
# convert the encoded string from base 255 to base 22
# (and, incidentally, from a string to an array):
"\xFF\x16" {base}/
+ # prepend the newline pushed earlier to the array, re-stringifying it
n/ # split the resulting string at newlines
= # pick the substring corresponding to the input number
{99+}% # add 99 to the character values in the chosen substring
one
) acceptable? \$\endgroup\$3
, you can't outputone two three four five six seven eight nine
even though you technically outputthree
. Similarly, you can't outputthree seven
, etc. \$\endgroup\$