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> displayCurrentBest =
                (generation, fitness, genes) =>
                    {
                        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);
                    };
            string result = new GeneticSolver().GetBest(GeneCount,
                                                        GeneSet,
                                                        getFitness,
                                                        displayCurrentBest);
            Console.WriteLine(result);
            return getFitness(result) == 0
                       ? new String(result.OrderBy(x => x).ToArray())
                       : null;
        }