public string Duplicate(string toMatch)
        {
            var solver = new GeneticSolver
                {
                    MaxSecondsWithoutImprovement = 1
                };
            int geneCount = toMatch.Length;
            Func<string, int> getFitness = child =>
            {
                int matches = Enumerable.Range(0, geneCount)
                    .Count(x => child[x] != toMatch[x]);
                return matches;
            };
            string geneSet = new String(toMatch.Distinct().ToArray());
            var stopwatch = new Stopwatch();
            stopwatch.Start();
            Action<int, int, string, string> displayCurrentBest =
                (generation, fitness, genes, strategy) =>
                    Console.WriteLine("generation\t{0} fitness\t{1} {2}\telapsed: {3}",
                                  generation.ToString().PadLeft(5, ' '),
                                  fitness.ToString().PadLeft(TotalWidth(toMatch), ' '),
                                  genes,
                                  stopwatch.Elapsed);

            string result = solver.GetBest(toMatch.Length,
                                           geneSet,
                                           getFitness,
                                           displayCurrentBest);
            Console.WriteLine(result);
            return result;
        }
        public string Solve()
        {
            Func<string, int> getFitness = child =>
            {
                var queenLocations = new HashSet<Point>(child.Select(x => x.ToPoint(GeneSet, BoardWidth)));
                int fitness = queenLocations.Sum(x => CountQueensAttacked(GetAttackablePoints(x), queenLocations));
                fitness += 10000 * (GeneCount - queenLocations.Count);
                return fitness;
            };

            var stopwatch = new Stopwatch();
            stopwatch.Start();
            Action<int, int, string, string> displayCurrentBest =
                (generation, fitness, genes, strategy) =>
                {
                    var board = new char?[BoardHeight, BoardWidth];

                    foreach (var queenLocation in genes.Select(x => x.ToPoint(GeneSet, BoardWidth)))
                    {
                        board[queenLocation.X, queenLocation.Y] = 'Q';
                    }

                    for (int i = 0; i < BoardHeight; i++)
                    {
                        for (int j = 0; j < BoardWidth; j++)
                        {
                            Console.Write(board[i, j] ?? '.');
                            Console.Write(' ');
                        }
                        Console.WriteLine();
                    }
                    Console.WriteLine("generation\t{0} fitness\t{1} elapsed: {2}",
                                      generation.ToString().PadLeft(5, ' '),
                                      fitness.ToString().PadLeft(2, ' '),
                                      stopwatch.Elapsed);
                };
            var geneticSolver = new GeneticSolver
            {
                GetCanonicalGenes = GetCanonicalGenes,
                MaxSecondsWithoutImprovement = 5
            };
            string result = geneticSolver.GetBest(GeneCount,
                                                  GeneSet,
                                                  getFitness,
                                                  displayCurrentBest);
            Console.WriteLine(result);
            return getFitness(result) == 0
                       ? GetCanonicalGenes(result)
                       : null;
        }
        public string Solve(IRouteSource routeSource, int maxSecondsWithoutImprovement)
        {
            if (routeSource.OptimalRoute != null)
            {
                Console.WriteLine("Expect optimal route " + routeSource.OptimalRoute
                                  + " to have fitness " + CalculateRouteLength(routeSource.OptimalRoute, routeSource));
            }

            var stopwatch = new Stopwatch();
            stopwatch.Start();

            var geneticSolver = new GeneticSolver
            {
                GetCanonicalGenes = GetCanonicalGenes,
                MaxSecondsWithoutImprovement = maxSecondsWithoutImprovement,
                NumberOfParentLines = 4
            };
            string result = geneticSolver.GetBest(
                routeSource.GeneSet.Length,
                routeSource.GeneSet,
                child => CalculateRouteLength(child, routeSource),
                (generation, fitness, genes, strategy) => Display(generation, fitness, genes, strategy, stopwatch));
            Console.WriteLine(GetCanonicalGenes(result));

            return GetCanonicalGenes(result);
        }