def run_dee10():
    import random

    print("--------SYMDS2024015--------")
    print("--------Laukik Nibre--------\n")

    # Population size
    POPULATION_SIZE = 100

    # Valid genes
    GENES = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890"

    # Target string
    TARGET = "Laukik Nibre"


    class Individual(object):

        def __init__(self, chromosome):
            self.chromosome = chromosome
            self.fitness = self.cal_fitness()

        @classmethod
        def mutated_genes(cls):
            return random.choice(GENES)

        @classmethod
        def create_genome(cls):
            return [cls.mutated_genes() for _ in range(len(TARGET))]

        def mate(self, par2):
            child_chromosome = []

            for gp1, gp2 in zip(self.chromosome, par2.chromosome):

                prob = random.random()

                if prob < 0.45:
                    child_chromosome.append(gp1)

                elif prob < 0.90:
                    child_chromosome.append(gp2)

                else:
                    child_chromosome.append(self.mutated_genes())

            return Individual(child_chromosome)

        def cal_fitness(self):
            fitness = 0
            for gs, gt in zip(self.chromosome, TARGET):
                if gs != gt:
                    fitness += 1
            return fitness


    def main():

        generation = 1
        found = False
        population = []

        # Create initial population
        for _ in range(POPULATION_SIZE):
            genome = Individual.create_genome()
            population.append(Individual(genome))

        while not found:

            population = sorted(population, key=lambda x: x.fitness)

            if population[0].fitness == 0:
                found = True
                break

            new_generation = []

            # Top 10% survive
            s = int((10 * POPULATION_SIZE) / 100)
            new_generation.extend(population[:s])

            # Remaining 90% produced by mating
            s = int((90 * POPULATION_SIZE) / 100)
            for _ in range(s):
                parent1 = random.choice(population[:50])
                parent2 = random.choice(population[:50])
                child = parent1.mate(parent2)
                new_generation.append(child)

            population = new_generation

            print("Generation:", generation,
                "String:", "".join(population[0].chromosome),
                "Fitness:", population[0].fitness)

            generation += 1

        print("\nFinal Solution:")
        print("Generation:", generation,
            "String:", "".join(population[0].chromosome),
            "Fitness:", population[0].fitness)


    if __name__ == "__main__":
        main()