#!/usr/bin/python from __future__ import division from collections import Counter import sys, operator, random encoded = str(sys.argv[1]) letter_num = len(encoded.replace(" ","")) GENES = "abcdefghijklmnopqrstuvwxyz" ETAOIN = "etaoinshrdlcumwfgypbvkjxqz" MONOGRAMFREQ = { "a": 0.08167, "b": 0.01492, "c": 0.02782, "d": 0.04253, "e": 0.12702, "f": 0.02228, "g": 0.02015, "h": 0.06094, "i": 0.06966, "j": 0.00153, "k": 0.00772, "l": 0.04025, "m": 0.02406, "n": 0.06749, "o": 0.07507, "p": 0.01929, "q": 0.00095, "r": 0.05987, "s": 0.06327, "t": 0.09056, "u": 0.02758, "v": 0.00978, "w": 0.02360, "x": 0.00150, "y": 0.01974, "z": 0.00074 } TOPBIGRAM = [ "th", "he", "in", "en", "nt", "re", "er", "an", "ll", "ee", "tt", "ss"] TOPWORDS = ["the","that", "have", "for", "and", "not", "from", "with", "at", "do", "they","ever", "you"] POPSIZE = 150 MUTSELECT = 0.02 RANDSELECT = 0.05 #findnth and replacenth are helper function used in the repair of a crossover def findnth(source, target, n): num = 0 start = -1 while num < n: start = source.find(target, start+1) if start == -1: return -1 num += 1 return start def replacenth(source, old, new, n): p = findnth(source, old, n) if n == -1: return source return source[:p] + new + source[p+len(old):] # returns the encrypted string after substitution def build_individual(substitute_string): temp = "" for i,val in enumerate(encoded): if encoded[i] in GENES: temp += substitute_string[ord(encoded[i])-97] else: temp += encoded[i] return temp; # splice genes of parents together at random point in gene material def crossover(male, female): rand = random.randint(2,24) child = male[:rand] + female[rand:] child_two = male[rand:] + female[:rand] repair_one = repair(child) repair_two = repair(child_two) return [repair_one, repair_two]; #repairs the child string to conform to gene standards(every gene is unique) # cretain as much of the parent strings as possible def repair(child): repaired_child = child temp = [] rand = random.randint(1,2) omitted = [] double = [] for value in GENES: count = child.count(value) if count == 0: omitted.append(value) elif count == 2: double.append(value) for value in double: if value > 1: repaired_child = replacenth(repaired_child, value, omitted.pop(), rand) return repaired_child; #swaps 2 characters in the gene string randomly def mutate(gene): i = random.randint(2,24) j = random.randint(2,24) lst = list(gene); lst[i], lst[j] = lst[j], lst[i] return ''.join(lst) #calculated the Fitness value for a specific individual def fitness( individual ): # # calculate Monogram fitness # counted_mostcommon = Counter(individual).most_common() freq_order = [] for charcount in counted_mostcommon[1:]: freq_order.append(charcount[0]) for letter in ETAOIN: if letter not in freq_order: freq_order.append(letter) freq_order = ''.join(freq_order) monogramfitness = 0 for commonLetter in ETAOIN[:6]: if commonLetter in freq_order[:6]: monogramfitness += 1 for uncommonLetter in ETAOIN[-6:]: if uncommonLetter in freq_order[-6:]: monogramfitness += 1 # # calculate digram fitness # diagramfitness = 0; for i,val in enumerate(individual[:-1]): bigram = individual[i] + individual[i+1] if bigram in TOPBIGRAM: diagramfitness += 1 # # calculate word fitness # wordfitness = 0 exploded = individual.split(); for word in exploded: if word in TOPWORDS: wordfitness += 2 return monogramfitness + diagramfitness + wordfitness; # select the healthiest individuals and some of not so healthy ones, breed them, then mutate def evolve(population): #grade population graded = [ (fitness(build_individual(x)), x) for x in population] graded_gene = [ x[1] for x in sorted(graded, reverse=True)] retain_length = int(len(graded_gene)*0.2) parents = graded_gene[:retain_length] #select some unhealthy parents for diversity for gene in graded_gene[retain_length:]: if RANDSELECT > random.random(): parents.append(gene) #mutate all next generation parents for gene in parents: if MUTSELECT > random.random(): parents.append(mutate(gene)) parents_length = len(parents) desired_length = POPSIZE children = [] #breeding while len(children) < desired_length: male = random.randint(0, parents_length-1) female = random.randint(0, parents_length-1) if male != female: male = parents[male] female = parents[female] child_one_two = crossover(male,female) children = children + child_one_two parents.extend(children) return {"pop": list(set(parents)), "best": graded[:5]} # main function, that runs the evolution def runEvolution(targetfitness, maxGeneration): highest_fitness = 0 current_generation = 0 stagnation = 0 individuals = POPSIZE best_results = [] #generate random starting population population = {"pop": ["".join(random.sample(GENES, len(GENES))) for x in xrange(100)], "best": []} # # Evolve till targets are reached # while( highest_fitness < targetfitness and current_generation < maxGeneration and stagnation < 8000 ): population = evolve(population["pop"]) current_generation += 1 individuals= len(population["pop"]) new_highscore = population["best"][0][0] if new_highscore >= highest_fitness: best_results.append(population["best"][0]) if new_highscore > highest_fitness: stagnation = 0 highest_fitness = new_highscore else: stagnation += 1 if current_generation % 100 == 0: print "Current Generation: " + str(current_generation) + " | populationsize: " + str(individuals) + " | highest fitness: " + str(population["best"][0][0]) #for x in population["best"]: # print "gene: " + str(x[1]) + "\nsolution: " + str(build_individual(x[1])) + "\n fitness: " + str(x[0])+ "\n" print "\nEvolution break detected" print "stagnated for: " + str(stagnation) + " generations" print "Total number of generations: " + str(current_generation) print "highest fitness value reached: " + str(highest_fitness) print "best guesses: " for x in best_results[-5:]: print str(x[0]) print str(x[1]) print str(build_individual(x[1])) + "\n" return; runEvolution(10000,10000) # print fitness("iq ifcc vqqr fb rdq vfllcq na rdq cfjwhwz hr bnnb hcc hwwhbsqvqbre hwq vhlq") # print fitness("we will meet in the middle of the library at noon all arrangements are made")
Run
Reset
Share
Import
Link
Embed
Language▼
English
中文
Python Fiddle
Python Cloud IDE
Follow @python_fiddle
Browser Version Not Supported
Due to Python Fiddle's reliance on advanced JavaScript techniques, older browsers might have problems running it correctly. Please download the latest version of your favourite browser.
Chrome 10+
Firefox 4+
Safari 5+
IE 10+
Let me try anyway!
url:
Go
Python Snippet
Stackoverflow Question