/gist:9f617b6698b24878beb7 Secret
Created
February 18, 2012 16:16
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import itertools | |
# Number stringification from | |
# http://code.activestate.com/recipes/413172-numbers-and-plural-words-as-spoken-english/ | |
_known = { | |
0: 'zero', | |
1: 'one', | |
2: 'two', | |
3: 'three', | |
4: 'four', | |
5: 'five', | |
6: 'six', | |
7: 'seven', | |
8: 'eight', | |
9: 'nine', | |
10: 'ten', | |
11: 'eleven', | |
12: 'twelve', | |
13: 'thirteen', | |
14: 'fourteen', | |
15: 'fifteen', | |
16: 'sixteen', | |
17: 'seventeen', | |
18: 'eighteen', | |
19: 'nineteen', | |
20: 'twenty', | |
30: 'thirty', | |
40: 'forty', | |
50: 'fifty', | |
60: 'sixty', | |
70: 'seventy', | |
80: 'eighty', | |
90: 'ninety' | |
} | |
def _positive_spoken_number(n): | |
"""Assume n is a positive integer. | |
>>> _positive_spoken_number(900) | |
'nine hundred' | |
>>> _positive_spoken_number(100) | |
'one hundred' | |
>>> _positive_spoken_number(100000000000) | |
'one hundred billion' | |
>>> _positive_spoken_number(1000000000000) | |
'one trillion' | |
>>> _positive_spoken_number(33000000000000) | |
'thirty-three trillion' | |
>>> _positive_spoken_number(34954523539) | |
'thirty-four billion, nine hundred fifty-four million, five hundred twenty-three thousand, five hundred thirty-nine' | |
""" | |
#import sys; print >>sys.stderr, n | |
if n in _known: | |
return _known[n] | |
bestguess = str(n) | |
remainder = 0 | |
if n<=20: | |
print >>sys.stderr, n, "How did this happen?" | |
assert 0 | |
elif n < 100: | |
bestguess= _positive_spoken_number((n//10)*10) + '-' + \ | |
_positive_spoken_number(n%10) | |
return bestguess | |
elif n < 1000: | |
bestguess= _positive_spoken_number(n//100) + ' ' + 'hundred' | |
remainder = n%100 | |
elif n < 1000000: | |
bestguess= _positive_spoken_number(n//1000) + ' ' + 'thousand' | |
remainder = n%1000 | |
elif n < 1000000000: | |
bestguess= _positive_spoken_number(n//1000000) + ' ' + 'million' | |
remainder = n%1000000 | |
elif n < 1000000000000: | |
bestguess= _positive_spoken_number(n//1000000000) + ' ' + 'billion' | |
remainder = n%1000000000 | |
else: | |
bestguess= _positive_spoken_number(n//1000000000000)+' '+'trillion' | |
remainder = n%1000000000000 | |
if remainder: | |
if remainder >= 100: comma = ',' | |
else: comma = ' and' | |
return bestguess + comma + ' ' + _positive_spoken_number(remainder) | |
else: | |
return bestguess | |
def spoken_number(n): | |
"""Return the number as it would be spoken, or just str(n) if unknown. | |
>>> spoken_number(0) | |
'zero' | |
>>> spoken_number(1) | |
'one' | |
>>> spoken_number(2) | |
'two' | |
>>> spoken_number(-2) | |
'minus two' | |
>>> spoken_number(42) | |
'forty-two' | |
>>> spoken_number(-1011) | |
'minus one thousand and eleven' | |
>>> spoken_number(1111) | |
'one thousand, one hundred and eleven' | |
""" | |
if not isinstance(n, int) and not isinstance(n, long): | |
return n | |
if n < 0: | |
if n in _known: return _known[n] | |
else: return 'minus ' + _positive_spoken_number(-n) | |
return _positive_spoken_number(n) | |
# End of re-used code! | |
def is_anagram(x, y): | |
# Test the len first as a minor optimisation | |
return len(x) == len(y) and sorted(x) == sorted(y) | |
def number_bonds(sum, minimum=1): | |
high = (sum + 1) // 2 | |
for a in xrange(minimum, high): | |
yield (a, sum - a) | |
def tyson_pairs(max): | |
symbolic_pair = lambda a, b: '{0} + {1}'.format(a, b) | |
spoken_pair = lambda a, b: '{0} plus {1}'.format(spoken_number(a), | |
spoken_number(b)) | |
for (ia, ib) in number_bonds(max): | |
for (ja, jb) in number_bonds(max, ia + 1): | |
if (is_anagram(symbolic_pair(ia, ib), | |
symbolic_pair(ja, jb)) and | |
is_anagram(spoken_pair(ia, ib), | |
spoken_pair(ja, jb))): | |
yield (ia, ib, ja, jb) | |
for pairs in itertools.chain(*(tyson_pairs(i) for i in xrange(1000))): | |
print "{0} + {1} = {2} + {3}".format(*pairs) | |
print "\t{0} plus {1} = {2} plus {3}".format(*map(spoken_number, pairs)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment