Skip to content

Instantly share code, notes, and snippets.

@MitchellSlavik
Created September 10, 2018 03:40
Show Gist options
  • Save MitchellSlavik/a373fc8327959eddecaa7244d5c37887 to your computer and use it in GitHub Desktop.
Save MitchellSlavik/a373fc8327959eddecaa7244d5c37887 to your computer and use it in GitHub Desktop.
Frequency analysis of a cipher text with a replacement mapping prompt
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