Created
September 10, 2018 03:40
-
-
Save MitchellSlavik/a373fc8327959eddecaa7244d5c37887 to your computer and use it in GitHub Desktop.
Frequency analysis of a cipher text with a replacement mapping prompt
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
from math import ceil | |
def getBool(prompt): | |
while True: | |
try: | |
return {"yes":True,"no":False,"y":True,"n":False}[input(prompt).lower()] | |
except KeyError: | |
print("Invalid input please enter Yes or No!") | |
inputText = input("Input cipher text: ") | |
spacesPartOfText = getBool("Are spaces apart of the text? ") | |
if spacesPartOfText: | |
ignoreSpaces = False | |
else: | |
ignoreSpaces = getBool("Ignore spaces in digraph/trigraph analysis? ") | |
def getKey(item): | |
return item[1] | |
def analyze(text): | |
text = text.upper() | |
counts = [[chr(x), 0] for x in range(65, 91)] | |
if spacesPartOfText: | |
counts.append([' ', 0]) | |
count = 0 | |
for c in text: | |
if not ord(c) in range(65, 91) and (): | |
continue | |
count += 1 | |
for t in counts: | |
if c == t[0]: | |
t[1] += 1 | |
counts.sort(key=getKey, reverse=True) | |
cols = 5 | |
rows = ceil(len(counts)/cols) | |
print('\nFrequency analysis:') | |
for r in range(rows): | |
text1 = '' | |
for c in range(cols): | |
pos = c * rows + r | |
if pos < len(counts): | |
text1 += '{}: '.format(counts[pos][0]) | |
text1 += '{0:9.5f} % '.format((counts[pos][1]/count) * 100) | |
print(text1) | |
print() | |
digraphs = [] | |
numDigraphs = 0 | |
textList = [i for i in text if not ignoreSpaces or i != ' '] | |
for i in range(len(textList) - 3): | |
char1 = textList[i] | |
char2 = textList[i+1] | |
num = 1 | |
numDigraphs += 1 | |
if len([b for b in digraphs if (char1+char2) == b[0]]) == 0: | |
for a in range(i + 2, len(textList) - 1): | |
char3 = textList[a] | |
char4 = textList[a+1] | |
if char1 == char3 and char2 == char4: | |
num += 1 | |
if num > 1: | |
digraphs.append((char1+char2, num)) | |
print("Digraph analysis:") | |
cols = 3 | |
rows = ceil(len(digraphs)/cols) | |
digraphs.sort(key=getKey, reverse=True) | |
if numDigraphs > 0: | |
for r in range(rows): | |
text1 = '' | |
for c in range(cols): | |
pos = c * rows + r | |
if pos < len(digraphs): | |
text1 += '{}: '.format(digraphs[pos][0]) | |
text1 += '{0:9.5f} % '.format((digraphs[pos][1]/numDigraphs) * 100) | |
print(text1) | |
print() | |
else: | |
print("No digraphs") | |
trigraphs = [] | |
numTrigraphs = 0 | |
for i in range(len(textList) - 5): | |
char1 = textList[i] | |
char2 = textList[i+1] | |
char3 = textList[i+2] | |
num = 1 | |
numTrigraphs += 1 | |
if len([b for b in digraphs if (char1+char2+char3) == b[0]]) == 0: | |
for a in range(i + 3, len(textList) - 2): | |
char4 = textList[a] | |
char5 = textList[a+1] | |
char6 = textList[a+2] | |
if char1 == char4 and char2 == char5 and char3 == char6: | |
num += 1 | |
if num > 1: | |
trigraphs.append((char1+char2+char3, num)) | |
print("Trigraph analysis:") | |
cols = 2 | |
rows = ceil(len(trigraphs)/cols) | |
trigraphs.sort(key=getKey, reverse=True) | |
if numTrigraphs > 0: | |
for r in range(rows): | |
text1 = '' | |
for c in range(cols): | |
pos = c * rows + r | |
if pos < len(trigraphs): | |
text1 += '{}: '.format(trigraphs[pos][0]) | |
text1 += '{0:9.5f} % '.format((trigraphs[pos][1]/numTrigraphs) * 100) | |
print(text1) | |
print() | |
else: | |
print('No trigraphs') | |
analyze(inputText) | |
def withMappings(text, mappings): | |
text = text.upper() | |
newText = '' | |
for c in text: | |
if c == ' ' and not spacesPartOfText: | |
newText += ' ' | |
continue | |
map1 = '' | |
for mapping in mappings: | |
if mapping[0] == c: | |
map1 = mapping[1] | |
if map1 == '': | |
newText += "_" | |
else: | |
newText += map1 | |
return newText | |
mappings = [] | |
print("Please input mappings as 'A B' to map A to B. _ = space") | |
newText = withMappings(inputText, mappings) | |
print('\n' + inputText) | |
print(newText + '\n') | |
while(True): | |
mapping = input("Mapping to try: ") | |
map1 = mapping.upper().split(" ") | |
if len(map1) == 2 and len(map1[0]) == 1 and len(map1[1]) == 1: | |
if map1[0] == '_': | |
map1[0] = ' ' | |
if map1[1] == '_': | |
map1[1] = ' ' | |
mappings = [i for i in mappings if i[0] != map1[0] and i[1] != map1[1]] | |
mappings.append((map1[0], map1[1])) | |
newText = withMappings(inputText, mappings) | |
print('\n' + inputText) | |
print(newText + '\n') | |
else: | |
print("Invalid mapping input") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment