Skip to content

Instantly share code, notes, and snippets.

# BWPanda/numberchains.py Last active Dec 17, 2018

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)) # 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()
to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.