N queens, none of them angry.
Place N queens on an N×N board so that no two attack each other. This does it with a genetic algorithm — a population of random boards, scored by how many pairs are attacking, bred by crossover and nudged by mutation until something scores zero. Two encodings are offered: the one I wrote in 2021, and the one I would write now.
Best fitness per generation. Zero is a solved board.
The population right now
Each chip is one candidate board, written as one row index per column. The green one is the current best.
Two encodings, and why it matters
2021 is the original: a board is N row indices, one per column. That already makes column collisions impossible by construction — the part I got right without quite knowing why — so the search only has to eliminate rows and diagonals. Selection dedupes and keeps the best 100, crossover swaps tails at one cut point, mutation moves a queen to a random row. Population 50, exactly as written.
Permutation applies the same insight once more. If the board must be a permutation of 0…N−1 then every row is used exactly once, so row collisions become impossible too and only diagonals are left. Crossover has to preserve that (ordered crossover) and mutation swaps two positions instead of overwriting one.
The difference is not subtle. Set the board to 12 or 16 and run each. The 2021 encoding grinds and usually stalls a few pairs short; the permutation version solves sixteen queens in tens of generations, and twenty about as easily. Same algorithm, same fitness function — the representation was doing the work all along.