Instantly share code, notes, and snippets.

Embed
What would you like to do?
A Python number counting script. See: https://panda.id.au/node/53
"""
Get number chains using letter counting functions.
In English, the word for the number 8 ('eight') has 5 letters. The word for the
number 5 ('five') has 4 letters. The word for the number 4 ('four') also has 4
letters. Therefore, the number chain for 8 is: 8 > 5 > (4) (with the 4 looping
back on itself).
It is interesting to note the number chains of different numbers, and in
different languages. Hence this script.
Inspiration came from Matt Parker's "Four has Four Letters" video:
https://www.youtube.com/watch?v=LYKn0yUTIU4
Read details about the creation of this script and what it found:
https://panda.id.au/node/53
"""
# Requires num2words: https://github.com/savoirfairelinux/num2words
import num2words
### Variables
# Get chains/words for all numbers between 0 and this number (inclusive).
max_number = 1000
# The language to get number words for. Supported languages can be found here:
# https://github.com/savoirfairelinux/num2words#user-content-usage
language = 'en'
# What to display for the numbers between 0 and max_number. Options are:
# 'chains': Outputs number chains (e.g. '3 > 5 > (4)').
# 'words': Outputs number words (e.g. 'fifty-six').
# 'stats': Outputs statistics for this range of numbers in this language.
display_type = 'stats'
# Get number chains, words or statistics.
def chains():
chains = []
for i in range(max_number + 1):
if display_type == 'words':
word = get_word(i, False)
print(word)
else:
chain = []
chain = links(i, chain)
if display_type == 'stats':
chains.append(chain)
else:
print(display(chain))
if display_type == 'stats':
stats(chains)
# Convert a number to its word.
def get_word(number, clean = True):
word = num2words.num2words(number, lang=language)
# Remove certain characters to make counting the length more accurate.
if clean:
characters = [' ', '-']
for char in characters:
word = word.replace(char, '')
return word
# Recursively get all the links of a number chain.
def links(number, chain):
# Add this number to the chain.
chain.append(number)
# Get the length of this number's word.
word = get_word(number)
length = len(word)
if length == number:
# The chain terminates with a single number loop.
index = chain.index(number)
chain.insert(index, '#')
return chain
elif length in chain:
# The chain terminates with a multi-number loop.
index = chain.index(length)
chain.insert(index, '#')
return chain
else:
# Get the next number in the chain.
return links(length, chain)
# Display a nicely formatted chain.
def display(chain):
output = ''
length = len(chain)
for i in chain:
if i == '#':
# This is the start of the termination loop.
output += '('
elif i == chain[length - 1]:
# This is the end of the chain/termination loop.
output += str(i) + ')'
else:
output += str(i) + ' > '
return output
# Calculate and display statistics for number chains.
def stats(chains):
# Initial values.
longest_chain_length = 1
longest_chain_example = 0
longest_chain_number = 0
longest_loop = 1
loops = []
for chain in chains:
length = len(chain) - 1 # Don't count the terminator.
if length > longest_chain_length:
longest_chain_length = length
longest_chain_example = chain
longest_chain_number = 1
elif length == longest_chain_length:
longest_chain_number += 1
loops = get_loop(chain, loops)
for loop in loops:
length = len(loop)
if length > longest_loop:
longest_loop = length
# Output statistics.
print('Numbers: 0 - ' + str(max_number))
print('Language: ' + language)
print()
print('Length of longest chain: ' + str(longest_chain_length))
print('Number of chains of that length: ' + str(longest_chain_number))
print('Example: ' + str(display(longest_chain_example)))
print()
if len(loops) > 1:
print('Longest loop: ' + str(longest_loop))
print('Number of loops: ' + str(len(loops)))
print('All loops:')
for loop in loops:
print(' (' + display(loop))
else:
print('All chains terminate at loop: (' + display(loops[0]))
# Get the termination loop from a chain and add it to a list, if it doesn't
# already exist.
def get_loop(chain, loops):
# Get termination loop from chain.
start = chain.index('#') + 1
end = len(chain)
chain_loop = chain[start:end]
# Make a copy to sort.
chain_loop_sorted = chain_loop.copy()
chain_loop_sorted.sort()
loop_exists = False
for loop in loops:
# Make a copy to sort.
loop_sorted = loop.copy()
loop_sorted.sort()
if chain_loop_sorted == loop_sorted:
loop_exists = True
break
# Loop is unique, add it to list.
if not loop_exists:
loops.append(chain_loop)
return loops
# Run the script.
chains()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment