Skip to content

Instantly share code, notes, and snippets.

@henryefranks
Created September 9, 2018 22:56
Show Gist options
  • Save henryefranks/08452366ac07451f759bc74cb0a1b895 to your computer and use it in GitHub Desktop.
Save henryefranks/08452366ac07451f759bc74cb0a1b895 to your computer and use it in GitHub Desktop.
Caesar cipher decoder using chi-squared values
###################################################
## DECODE CAESAR CIPHER USING CHI-SQUARED VALUES ##
## COPYRIGHT (C) 2018 HENRY FRANKS ##
###################################################
phrase = "AOLJHLZHYJPWOLYPZVULZMAOLLHYSPLZARUVDUHUKZPTWSLZAJPWOLYZPAPZHAFWLVMZBIZAPABAPVUJPWOLYPUDOPJOLHJOSLAALYPUAOLWSHPUALEAPZZOPMALKHJLYAHPUUBTILYVMWSHJLZKVDUAOLHSWOHILA" # Phrase to decode
expected = [13.2345, 2.4138, 4.5036, 6.885, 19.602, 3.6126, 3.2724, 9.8658, 11.2914, 0.243, 1.2474, 6.5286, 3.9042, 10.935, 12.1662, 3.1226, 0.162, 9.7038, 10.2546, 14.6772, 4.4712, 1.5876, 3.8232, 0.243, 3.1914, 0.1134] # Expected frequencies for 162 letters
observed = [18, 3, 0, 3, 1, 1, 0, 12, 3, 8, 3, 22, 4, 0, 12, 17, 0, 1, 6, 2, 11, 7, 8, 0, 8, 12] # Observed letter frequencies
chi_values = {} # Dictionary will store shift as key and X^2 as value
for shift in range(26):
shifted = observed[-shift:] + observed[:-shift] # Shift list by shift
chi_squared = sum([(o-e)**2 / e for (e, o) in zip(expected, shifted)]) # Calculate X^2 for shifted list
print('Shift: %02d | X^2: %d' % (shift, chi_squared))
chi_values[shift] = chi_squared # Add shift and X^2 to dictionary
best_shift = min(chi_values, key=chi_values.get) # Get the shift for the lowest X^2
# Apply shift to string
values = [ord(c) + best_shift for c in phrase.upper()] # Convert character to number
decoded = ''.join([chr(n) if n < 91 else chr(n-26) for n in values]) # Shift number and convert back to character
print('\nBest shift: %d | Decoded: %s' % (best_shift, decoded))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment