Created
August 24, 2025 17:58
-
-
Save matthewdeanmartin/3e954b142d9d8671e0bcc900dddc1936 to your computer and use it in GitHub Desktop.
Algorithm for a human to generate 1000 pseudorandom numbers per hour
This file contains hidden or 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 collections | |
| import math | |
| import re | |
| def seeded_text_key_scramble(source_text, secret_key, start_word_index, num_digits, verbose=False): | |
| """ | |
| Generates a sequence of pseudo-random digits based on a source text and a secret key. | |
| Args: | |
| source_text (str): The text to use as the source of entropy. | |
| secret_key (str): A string of digits to use as the key. | |
| start_word_index (int): The index of the word to start from in the text. | |
| num_digits (int): The total number of digits to generate. | |
| verbose (bool): If True, prints the step-by-step actions for generation. | |
| Returns: | |
| str: The generated string of digits. | |
| """ | |
| # Sanitize the source text by keeping only letters and spaces, and splitting into words. | |
| words = re.sub(r'[^a-zA-Z\s]', '', source_text.lower()).split() | |
| if not words: | |
| raise ValueError("Source text contains no usable words.") | |
| generated_digits = [] | |
| word_index = start_word_index % len(words) | |
| key_index = 0 | |
| # The main loop, generating two digits per iteration. | |
| num_iterations = (num_digits + 1) // 2 | |
| for i in range(num_iterations): | |
| if len(generated_digits) >= num_digits: | |
| break | |
| if verbose: print(f"\n--- Iteration {i + 1} ---") | |
| # 1. Identify the current word and count its letters (L). | |
| current_word = words[word_index] | |
| l = len(current_word) | |
| if verbose: print(f"ACTION: Point to word '{current_word}'. Count its letters. L = {l}.") | |
| # 2. Get the current key digit (k). | |
| k = int(secret_key[key_index]) | |
| if verbose: print(f"ACTION: Recall the next secret key digit. k = {k}.") | |
| # 3. Calculate the first digit (D1). | |
| d1 = (l + k) % 10 | |
| generated_digits.append(str(d1)) | |
| if verbose: print(f"ACTION: Calculate first digit: ({l} + {k}) mod 10 = {d1}. Write down '{d1}'.") | |
| if len(generated_digits) >= num_digits: | |
| break | |
| # 4. Calculate the second digit (D2). | |
| letter_pos_in_word = (d1 - 1) % l if l > 0 else 0 | |
| letter = current_word[letter_pos_in_word] | |
| alphabet_pos = ord(letter) - ord('a') + 1 | |
| d2 = alphabet_pos % 10 | |
| generated_digits.append(str(d2)) | |
| if verbose: | |
| print(f"ACTION: Count {d1} letters into '{current_word}' to find the letter '{letter}'.") | |
| print( | |
| f"ACTION: Find alphabet position of '{letter}' ({alphabet_pos}). Calculate second digit: {alphabet_pos} mod 10 = {d2}. Write down '{d2}'.") | |
| # 5. Find the next word. | |
| words_to_advance = d2 + 1 | |
| word_index = (word_index + words_to_advance) % len(words) | |
| if verbose: | |
| print(f"ACTION: Count {words_to_advance} words forward to find the next word ('{words[word_index]}').") | |
| print(f" > Generated so far: {''.join(generated_digits)}") | |
| # 6. Advance the key index, looping if necessary. | |
| key_index = (key_index + 1) % len(secret_key) | |
| return "".join(generated_digits) | |
| def analyze_randomness(digits_str): | |
| """ | |
| Performs several statistical tests on a string of digits to check for randomness. | |
| """ | |
| print("--- Statistical Randomness Analysis ---") | |
| # 1. Frequency Analysis | |
| print("\n1. Digit Frequency Distribution:") | |
| counts = collections.Counter(digits_str) | |
| total_digits = len(digits_str) | |
| expected_count = total_digits / 10.0 | |
| print(f"Total Digits: {total_digits}") | |
| print(f"Expected count per digit: {expected_count:.1f}") | |
| print("-" * 30) | |
| for digit in sorted(counts.keys()): | |
| print(f"Digit {digit}: {counts[digit]:>4} times ({(counts[digit] / total_digits) * 100:5.2f}%)") | |
| print("-" * 30) | |
| # 2. Chi-Squared Test for Uniformity | |
| chi_squared_stat = sum([(counts.get(str(d), 0) - expected_count) ** 2 / expected_count for d in range(10)]) | |
| critical_value = 16.919 # p=0.05, df=9 | |
| print("\n2. Chi-Squared Test for Uniformity:") | |
| print(f"Chi-Squared Statistic: {chi_squared_stat:.4f}") | |
| print(f"Critical Value (p=0.05, df=9): {critical_value}") | |
| if chi_squared_stat < critical_value: | |
| print("Result: The distribution appears uniform. We DO NOT reject the null hypothesis.") | |
| else: | |
| print("Result: The distribution does NOT appear uniform. We REJECT the null hypothesis.") | |
| # 3. Runs Test (Simple version: count of adjacent identical digits) | |
| runs = 0 | |
| for i in range(total_digits - 1): | |
| if digits_str[i] == digits_str[i + 1]: | |
| runs += 1 | |
| expected_runs = (total_digits - 1) / 10.0 | |
| print("\n3. Simple Runs Test (Adjacent Repeats):") | |
| print(f"Observed number of adjacent identical digits: {runs}") | |
| print(f"Expected number of adjacent identical digits: {expected_runs:.1f}") | |
| if abs(runs - expected_runs) < 3 * math.sqrt(expected_runs): # Check within ~3 std deviations | |
| print("Result: The number of runs is within the expected range for a random sequence.") | |
| else: | |
| print("Result: The number of runs is outside the expected range.") | |
| # --- Main Execution --- | |
| if __name__ == "__main__": | |
| lorem_ipsum_text = """ | |
| Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. | |
| Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. | |
| Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. | |
| Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. | |
| Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, | |
| eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. | |
| Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores | |
| eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, | |
| consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam | |
| quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, | |
| nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse | |
| quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur? | |
| """ | |
| SECRET_KEY = "3141592653" | |
| START_WORD_INDEX = 13 | |
| NUM_DIGITS_TO_GENERATE = 1000 | |
| # --- VERBOSE DEMONSTRATION --- | |
| # Show the step-by-step process for the first 20 digits to see how a human would do it. | |
| print("=" * 50) | |
| print("--- Human Action Simulation (First 20 Digits) ---") | |
| print("=" * 50) | |
| seeded_text_key_scramble( | |
| source_text=lorem_ipsum_text, | |
| secret_key=SECRET_KEY, | |
| start_word_index=START_WORD_INDEX, | |
| num_digits=20, | |
| verbose=True | |
| ) | |
| # --- FULL GENERATION AND ANALYSIS --- | |
| print("\n\n" + "=" * 50) | |
| print(f"--- Full Run: Generating {NUM_DIGITS_TO_GENERATE} Digits for Analysis ---") | |
| print("=" * 50) | |
| random_number = seeded_text_key_scramble( | |
| source_text=lorem_ipsum_text, | |
| secret_key=SECRET_KEY, | |
| start_word_index=START_WORD_INDEX, | |
| num_digits=NUM_DIGITS_TO_GENERATE, | |
| verbose=False # Turn off verbose for the full run | |
| ) | |
| print(f"\n--- Generated {len(random_number)}-Digit Number ---") | |
| for i in range(0, len(random_number), 100): | |
| print(random_number[i:i + 100]) | |
| print("\n") | |
| analyze_randomness(random_number) |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
==================================================
--- Human Action Simulation (First 20 Digits) ---
--- Iteration 1 ---
ACTION: Point to word 'ut'. Count its letters. L = 2.
ACTION: Recall the next secret key digit. k = 3.
ACTION: Calculate first digit: (2 + 3) mod 10 = 5. Write down '5'.
ACTION: Count 5 letters into 'ut' to find the letter 'u'.
ACTION: Find alphabet position of 'u' (21). Calculate second digit: 21 mod 10 = 1. Write down '1'.
ACTION: Count 2 words forward to find the next word ('et').
--- Iteration 2 ---
ACTION: Point to word 'et'. Count its letters. L = 2.
ACTION: Recall the next secret key digit. k = 1.
ACTION: Calculate first digit: (2 + 1) mod 10 = 3. Write down '3'.
ACTION: Count 3 letters into 'et' to find the letter 'e'.
ACTION: Find alphabet position of 'e' (5). Calculate second digit: 5 mod 10 = 5. Write down '5'.
ACTION: Count 6 words forward to find the next word ('ad').
--- Iteration 3 ---
ACTION: Point to word 'ad'. Count its letters. L = 2.
ACTION: Recall the next secret key digit. k = 4.
ACTION: Calculate first digit: (2 + 4) mod 10 = 6. Write down '6'.
ACTION: Count 6 letters into 'ad' to find the letter 'd'.
ACTION: Find alphabet position of 'd' (4). Calculate second digit: 4 mod 10 = 4. Write down '4'.
ACTION: Count 5 words forward to find the next word ('exercitation').
--- Iteration 4 ---
ACTION: Point to word 'exercitation'. Count its letters. L = 12.
ACTION: Recall the next secret key digit. k = 1.
ACTION: Calculate first digit: (12 + 1) mod 10 = 3. Write down '3'.
ACTION: Count 3 letters into 'exercitation' to find the letter 'e'.
ACTION: Find alphabet position of 'e' (5). Calculate second digit: 5 mod 10 = 5. Write down '5'.
ACTION: Count 6 words forward to find the next word ('ex').
--- Iteration 5 ---
ACTION: Point to word 'ex'. Count its letters. L = 2.
ACTION: Recall the next secret key digit. k = 5.
ACTION: Calculate first digit: (2 + 5) mod 10 = 7. Write down '7'.
ACTION: Count 7 letters into 'ex' to find the letter 'e'.
ACTION: Find alphabet position of 'e' (5). Calculate second digit: 5 mod 10 = 5. Write down '5'.
ACTION: Count 6 words forward to find the next word ('irure').
--- Iteration 6 ---
ACTION: Point to word 'irure'. Count its letters. L = 5.
ACTION: Recall the next secret key digit. k = 9.
ACTION: Calculate first digit: (5 + 9) mod 10 = 4. Write down '4'.
ACTION: Count 4 letters into 'irure' to find the letter 'r'.
ACTION: Find alphabet position of 'r' (18). Calculate second digit: 18 mod 10 = 8. Write down '8'.
ACTION: Count 9 words forward to find the next word ('dolore').
--- Iteration 7 ---
ACTION: Point to word 'dolore'. Count its letters. L = 6.
ACTION: Recall the next secret key digit. k = 2.
ACTION: Calculate first digit: (6 + 2) mod 10 = 8. Write down '8'.
ACTION: Count 8 letters into 'dolore' to find the letter 'o'.
ACTION: Find alphabet position of 'o' (15). Calculate second digit: 15 mod 10 = 5. Write down '5'.
ACTION: Count 6 words forward to find the next word ('sint').
--- Iteration 8 ---
ACTION: Point to word 'sint'. Count its letters. L = 4.
ACTION: Recall the next secret key digit. k = 6.
ACTION: Calculate first digit: (4 + 6) mod 10 = 0. Write down '0'.
ACTION: Count 0 letters into 'sint' to find the letter 't'.
ACTION: Find alphabet position of 't' (20). Calculate second digit: 20 mod 10 = 0. Write down '0'.
ACTION: Count 1 words forward to find the next word ('occaecat').
--- Iteration 9 ---
ACTION: Point to word 'occaecat'. Count its letters. L = 8.
ACTION: Recall the next secret key digit. k = 5.
ACTION: Calculate first digit: (8 + 5) mod 10 = 3. Write down '3'.
ACTION: Count 3 letters into 'occaecat' to find the letter 'c'.
ACTION: Find alphabet position of 'c' (3). Calculate second digit: 3 mod 10 = 3. Write down '3'.
ACTION: Count 4 words forward to find the next word ('sunt').
--- Iteration 10 ---
ACTION: Point to word 'sunt'. Count its letters. L = 4.
ACTION: Recall the next secret key digit. k = 3.
ACTION: Calculate first digit: (4 + 3) mod 10 = 7. Write down '7'.
ACTION: Count 7 letters into 'sunt' to find the letter 'n'.
ACTION: Find alphabet position of 'n' (14). Calculate second digit: 14 mod 10 = 4. Write down '4'.
ACTION: Count 5 words forward to find the next word ('deserunt').
==================================================
--- Full Run: Generating 1000 Digits for Analysis ---
--- Generated 1000-Digit Number ---
5135643575488500337414826912268964905809604724847115400397515542755503510900859287846081754569540101
9245994875342500816469472484711540039751554275550351090085928784608175456954010192459948753425008164
6947248471154003975155427555035109008592878460817545695401019245994875342500816469472484711540039751
5542755503510900859287846081754569540101924599487534250081646947248471154003975155427555035109008592
8784608175456954010192459948753425008164694724847115400397515542755503510900859287846081754569540101
9245994875342500816469472484711540039751554275550351090085928784608175456954010192459948753425008164
6947248471154003975155427555035109008592878460817545695401019245994875342500816469472484711540039751
5542755503510900859287846081754569540101924599487534250081646947248471154003975155427555035109008592
8784608175456954010192459948753425008164694724847115400397515542755503510900859287846081754569540101
9245994875342500816469472484711540039751554275550351090085928784608175456954010192459948753425008164
--- Statistical Randomness Analysis ---
Total Digits: 1000
Expected count per digit: 100.0
Digit 0: 137 times (13.70%)
Digit 1: 99 times ( 9.90%)
Digit 2: 63 times ( 6.30%)
Digit 3: 40 times ( 4.00%)
Digit 4: 149 times (14.90%)
Digit 5: 186 times (18.60%)
Digit 6: 52 times ( 5.20%)
Digit 7: 86 times ( 8.60%)
Digit 8: 89 times ( 8.90%)
Digit 9: 99 times ( 9.90%)
Chi-Squared Test for Uniformity:
Chi-Squared Statistic: 187.5800
Critical Value (p=0.05, df=9): 16.919
Result: The distribution does NOT appear uniform. We REJECT the null hypothesis.
Simple Runs Test (Adjacent Repeats):
Observed number of adjacent identical digits: 100
Expected number of adjacent identical digits: 99.9
Result: The number of runs is within the expected range for a random sequence.
Process finished with exit code 0