A lagniappe of working remotely the past year has been a daily opportunity to ponder randomness for just a moment as I enter the transitory passcode generated on my phone from an authentication app in order to complete a VPN connection to my network, a required measure of security implemented by my workplace. Over the course of the past few years of using the app, my intuition was that close to every 6-digit passcode generated by it included at least 1 repeated digit. Daily use only intensified my suspicion. It seemed that every time I thought to consider the number being generated for me, at least one pair, and frequently 2 were involved. Something about this didn't sit right with me. Were randomly generated 6 digit numbers almost guaranteed to repeat a digit? Or was this app simply not generating random numbers?
This wasn't just an idle concern. Years ago, when I first developed some programming skills that were shallow in comparison to others but deep enough to make me dangerous, I spent some of my spare time trying to conceive of ways to devise a random number generator, usually in the service of primitive game design. I discovered that writing an algorithm to try to produce actual randomness was a great deal more complex than it seemed at first blush to my fertile imagination. Most self-contained algorithms that I tried lacked something in the production of verifiably random-like sequences of numbers. I had the most success incorporating some unplanned element of the run-time environment into my calculation, e.g., the evenness or oddness of the thousandth of a second that the program was invoked or of the ascii value of the third letter of the verbal representation of the product of both the tenths and hundredths of a second of the timestamp.
Fast forward through years of American decline to the point of our present situation of isolation. Facing the mystery each weekday morning, I daily started to daydream about ways to explore the question of how random my authentication app's random number generator was. My first thought was that the question was something I could tackle through logic alone, perhaps with the help of Excel formulas. Of course, the purpose of the app being to connect me to work, it never failed that my ambition to solve the problem would be supplanted by my desire to remain gainfully employed, by doing actual work instead. Consequently, my barely started efforts would sit in cobwebs for months before the cycle would repeat, the struggle between ambition and reality playing itself out each time with the same predictable results.
Today for some reason, with the end of the month approaching and a whole weekend lying before me, it occurred to me that my ability to reason could use some help. A lightbulb went off and I realized that all I needed to do was to count every possible 6 digit number between 000000 and 999999 that contained at least one pair and then compare it to the incidence of pairs in the passcodes proffered by the authentication app. Having limited time, I needed a shortcut with the counting, so I dusted off some Python knowledge and built a program to assist with the task.
Since it had been a while since I'd used Python, to warm myself up I wrote a function to pad an integer n with up to 5 leading 0s, (e.g., render 1 as '000001', 223 as '000223' and so forth) put the digits into a list and then sort the list numerically*:
a = f"{n:06}"
l = [int(x) for x in str(a)]
l.sort()
return l
The sorting turned out not to be necessary but served mostly as acknowledgement of my realization that using this brute force method and thinking of each number as one of a million possible "hands" that could be "dealt" by the authenticator, I could abandon the complexities of factoring in the location in the string of each member of the pair that played havoc with my ADD when I was attempting to use logic alone.
My next challenge was to count the instances of pairs, and while I was at it of triples, quadruples, quintuples and sextuples in a given 6-digit number n:
l=AnalNum(n)
Ze,Si,Pr,Tr,Qr,Qt,Sx=0,0,0,0,0,0,0
item=0
while item<10:
Ct=l.count(item)
if Ct==1:
Si+=1
elif Ct==2:
Pr+=1
elif Ct==3:
Tr+=1
elif Ct==4:
Qr+=1
elif Ct==5:
Qt+=1
elif Ct==6:
Sx+=1
else:
Ze+=1
item+=1
L=[Si,Pr,Tr,Qr,Qt,Sx]
return L
- One and only one pair: e.g., 113456
- One pair and a triple: 121216
- One pair and a quadruple:121211
- Two pairs: 121256
- Three pairs: 121233
- One and only one triple: 123226
- Two triples: 121212
- One quadruple: 123222
- One quintuple: 122222
- One sextuple: 222222
- Six unique digits: 123456
Counts of instances of specific repetitions of digits in 6-digit numbers between 000000 and 999999 compared with those of 100 passcodes generated by a VPN authentication app |
~~~~~~~~~~
* Note: It will be best to think of the python contained in this post as not so much exemplary of programming virtue as confessional of programming sin.
† Do not try at home. As I discovered Monday morning, the consequence of treating an authentication app as a random number generator for a sample of significant size is being locked out of the network for too many attempts.
No comments:
Post a Comment