Previously I wrote a random password generator in Python. This worked well, but had a couple of problems. The first, identified at the time, was that there was a slight bias in the algorithm which would return certain characters more often than others. A second problem, identified after some pondering, was the inclusion of some redundant code. That version of the function had three lists and a dictionary - could this be consolidated down to just the dictionary? As it happens... YES!
The typical usage of dictionaries is to pass in a key to obtain a value. However, it's perfectly possible to obtain a key, value or both by supplying an index using a dictionary's .keys(), .values() or .items() methods and supplying the index such as:
phoneticDictionary.items()[15]
This means, of course, that it would be possible to get a randomly generated index from the dictionary, like so:
phoneticDictionary.items()[random.randint(0, 61)]
Knowing this meant I was able to alter my code to get rid of the three lists and use just the dictionary itself. It also got rid of the bias noted earlier.
Here's the complete listing:
import random def getRandomPassword(length): phoneticDictionary = {"A" : "ALPHA", "B" : "BRAVO", "C" : "CHARLIE", "D" : "DELTA", "E" : "ECHO", "F" : "FOXTROT", "G" : "GOLF", "H" : "HOTEL", "I" : "INDIA", "J" : "JULIET", "K" : "KILO", "L" : "LIMA", "M" : "MIKE", "N" : "NOVEMBER", "O" : "OSCAR", "P" : "PAPA", "Q" : "QUEBEC", "R" : "ROMEO", "S" : "SIERRA", "T" : "TANGO", "U" : "UNIFORM", "V" : "VICTOR", "W" : "WHISKEY", "X" : "XRAY", "Y" : "YANKEE", "Z" : "ZULU", "a" : "alpha", "b" : "bravo", "c" : "charlie", "d" : "delta", "e" : "echo", "f" : "foxtrot", "g" : "golf", "h" : "hotel", "i" : "india", "j" : "juliet", "k" : "kilo", "l" : "lima", "m" : "mike", "n" : "november", "o" : "oscar", "p" : "papa", "q" : "quebec", "r" : "romeo", "s" : "sierra", "t" : "tango", "u" : "uniform", "v" : "victor", "w" : "whiskey", "x" : "xray", "y" : "yankee", "z" : "zulu", "0" : "Zero", "1" : "One", "2" : "Two", "3" : "Three", "4" : "Four", "5" : "Five", "6" : "Six", "7" : "Seven", "8" : "Eight", "9" : "Nine"} password = [] phoneticPassword = [] for i in range(length): c, pc = phoneticDictionary.items()[random.randint(0, 61)] password.append(c) phoneticPassword.append(pc) return "".join(password), "-".join(phoneticPassword)
And here's the function's output run 10 times specifying a length of 8:
pnReI0lg papa-november-ROMEO-echo-INDIA-Zero-lima-golf 7g7SnNKl Seven-golf-Seven-SIERRA-november-NOVEMBER-KILO-lima 7Q3Zy4Ya Seven-QUEBEC-Three-ZULU-yankee-Four-YANKEE-alpha 697vxMRX Six-Nine-Seven-victor-xray-MIKE-ROMEO-XRAY R214zUMk ROMEO-Two-One-Four-zulu-UNIFORM-MIKE-kilo f0db3LbG foxtrot-Zero-delta-bravo-Three-LIMA-bravo-GOLF IC9046VT INDIA-CHARLIE-Nine-Zero-Four-Six-VICTOR-TANGO 8mg5Vufa Eight-mike-golf-Five-VICTOR-uniform-foxtrot-alpha C2Puu9dc CHARLIE-Two-PAPA-uniform-uniform-Nine-delta-charlie tcK6OCsG tango-charlie-KILO-Six-OSCAR-CHARLIE-sierra-GOLF