optimisticninja / liberprimus-tool

Python tool/libraray for evolving solutions toward the Liber Primus from Cicada 3301
1 stars 1 forks source link

Finish implementing crossover #36

Closed optimisticninja closed 1 month ago

optimisticninja commented 2 months ago

At this time, we are simply printing that a crossover should occur - this got lost in the process of getting mutation working.

d4v1-sudo commented 2 months ago
import copy
import random

class GeneticAlgorithm:
    def __init__(self, crossover_rate, **entries):
        self.crossover_rate = crossover_rate
        self.__dict__.update(entries)

    def crossover(self, **entries):
        offspring = copy.deepcopy(self)
        crypto_dict = self.__dict__
        for attr, v in entries.items():
            if attr == "scheme" and random.random() < self.crossover_rate:
                offspring_scheme = random.choice([self.scheme, v])
                offspring.scheme = offspring_scheme

            elif attr == "shift" and random.random() < self.crossover_rate:
                offspring_shift = random.choice([self.shift, v])
                offspring.shift = offspring_shift

            elif attr == "lookup" and random.random() < self.crossover_rate:
                offspring_lookup = random.choice([self.lookup, v])
                offspring.lookup = offspring_lookup

            elif attr == "key" and random.random() < self.crossover_rate:
                offspring_key = random.choice([self.key, v])
                offspring.key = offspring_key

            elif attr == "skips" and random.random() < self.crossover_rate:
                offspring_skips = self.merge_dicts(self.skips, v)
                offspring.skips = offspring_skips

            elif attr == "excludes" and random.random() < self.crossover_rate:
                offspring_excludes = self.merge_dicts(self.excludes, v)
                offspring.excludes = offspring_excludes

        return offspring

    def merge_dicts(self, dict1, dict2):
        merged_dict = dict1.copy()
        for key, value in dict2.items():
            if key in merged_dict:
                merged_dict[key].extend(value)
            else:
                merged_dict[key] = value
        return merged_dict

# one example
ga = GeneticAlgorithm(0.5, scheme="vigenere", shift=3, lookup="ATBASH", key="KEY", skips={'a': [1, 2]}, excludes={'b': [3, 4]})
offspring = ga.crossover(scheme="rot", shift=5, lookup="RUNE_LOOKUP", key="NEW_KEY", skips={'c': [5, 6]}, excludes={'d': [7, 8]})
print(offspring.__dict__)