#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <stdbool.h>
#define SIZE 9 // rozmiar planszy
#define BLOCK 3 // rozmiar bloku 3x3
// parametry GA
#define POP_SIZE 200 // liczebnosc populacji
#define MAX_GEN 5000 // maksymalna liczba generacji
#define TOURN_SIZE 3 // liczba w turnieju
#define CROSS_RATE 0.05 // prawdopodobienstwo krzyzowania
#define MUT_RATE 0.05 // prawdopodobienstwo mutacji
#define REPORT_GEN 50 // raport co
// dane sudoku, 0 = puste pole
int puzzle[ SIZE] [ SIZE] = {
{ 5 , 3 , 0 , 0 , 7 , 0 , 0 , 0 , 0 } ,
{ 6 , 0 , 0 , 1 , 9 , 5 , 0 , 0 , 0 } ,
{ 0 , 9 , 8 , 0 , 0 , 0 , 0 , 6 , 0 } ,
{ 8 , 0 , 0 , 0 , 6 , 0 , 0 , 0 , 3 } ,
{ 4 , 0 , 0 , 8 , 0 , 3 , 0 , 0 , 1 } ,
{ 7 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 6 } ,
{ 0 , 6 , 0 , 0 , 0 , 0 , 2 , 8 , 0 } ,
{ 0 , 0 , 0 , 4 , 1 , 9 , 0 , 0 , 5 } ,
{ 0 , 0 , 0 , 0 , 8 , 0 , 0 , 7 , 9 }
} ;
// struktura jednego osobnika
typedef struct {
int grid[ SIZE] [ SIZE] ; // wartosci w komorkach
int fitness; // ocena dopasowania
} Individual;
// deklaracje funkcji
void entry_individual( Individual * ind) ;
int evaluate_fitness( const Individual * ind) ;
Individual* tournament_selection( Individual pop[ ] ) ;
void crossover( const Individual * p1, const Individual * p2,
Individual * c1, Individual * c2, int generation) ;
void mutate( Individual * ind, int generation) ;
void do_sudoku_ga( void ) ;
void print_individual( const Individual * ind) ;
void print_iteration( int gen, const Individual * best) ;
// losowa liczba z przedzialu [a,b]
static int rand_range( int a, int b) {
return a
+ rand ( ) % ( b
- a
+ 1 ) ; }
// inicjalizacja osobnika: uzupelnienie pustych pol w blokach 3x3
void entry_individual( Individual * ind) {
bool fixed[ SIZE] [ SIZE] = { false } ;
// skopiuj stale wart
for ( int i = 0 ; i < SIZE; i++ ) {
for ( int j = 0 ; j < SIZE; j++ ) {
ind-> grid[ i] [ j] = puzzle[ i] [ j] ;
fixed[ i] [ j] = ( puzzle[ i] [ j] != 0 ) ;
}
}
// wypełnij kazdy blok
for ( int br = 0 ; br < BLOCK; br++ ) {
for ( int bc = 0 ; bc < BLOCK; bc++ ) {
bool present[ SIZE+ 1 ] = { false } ;
// zaznacz juz obecne wartosci
for ( int di = 0 ; di < BLOCK; di++ )
for ( int dj = 0 ; dj < BLOCK; dj++ ) {
int v = ind-> grid[ br* BLOCK+ di] [ bc* BLOCK+ dj] ;
if ( v) present[ v] = true ;
}
int missing[ SIZE] , m = 0 ;
// zbierz brakujace
for ( int v = 1 ; v <= SIZE; v++ )
if ( ! present[ v] ) missing[ m++ ] = v;
// losowo przemieszaj brakujace
for ( int x = m- 1 ; x > 0 ; x-- ) {
int tmp = missing[ x] ; missing[ x] = missing[ y] ; missing[ y] = tmp;
}
// wstaw w puste miejsca
int idx = 0 ;
for ( int di = 0 ; di < BLOCK; di++ )
for ( int dj = 0 ; dj < BLOCK; dj++ ) {
int r = br* BLOCK+ di, c = bc* BLOCK+ dj;
if ( ! fixed[ r] [ c] ) ind-> grid[ r] [ c] = missing[ idx++ ] ;
}
}
}
// oblicz fitness poczatkowy
ind-> fitness = evaluate_fitness( ind) ;
}
// ocena ile roznych liczb w kazdym wierszu i kolumnie
int evaluate_fitness( const Individual * ind) {
int score = 0 ;
int row_cnt[ SIZE+ 1 ] , col_cnt[ SIZE+ 1 ] ;
for ( int i = 0 ; i < SIZE; i++ ) {
memset ( row_cnt
, 0 , sizeof row_cnt
) ; memset ( col_cnt
, 0 , sizeof col_cnt
) ; for ( int j = 0 ; j < SIZE; j++ ) {
row_cnt[ ind-> grid[ i] [ j] ] ++;
col_cnt[ ind-> grid[ j] [ i] ] ++;
}
for ( int v = 1 ; v <= SIZE; v++ ) {
if ( row_cnt[ v] > 0 ) score++;
if ( col_cnt[ v] > 0 ) score++;
}
}
return score;
}
// selekcja turniejowa, najlepsze z TOURN_SIZE osobnikow
Individual* tournament_selection( Individual pop[ ] ) {
Individual * best = NULL;
for ( int i = 0 ; i < TOURN_SIZE; i++ ) {
Individual
* cand
= & pop
[ rand ( ) % POP_SIZE
] ; if ( ! best || cand-> fitness > best-> fitness) best = cand;
}
return best;
}
// krzyzowanie swapuj losowo bloki 3x3 z CROSS_RATE %
void crossover( const Individual * p1, const Individual * p2,
Individual * c1, Individual * c2, int generation) {
// skopiuj rodzicow
memcpy ( c1
-> grid
, p1
-> grid
, sizeof p1
-> grid
) ; memcpy ( c2
-> grid
, p2
-> grid
, sizeof p2
-> grid
) ; if ( ( double ) rand ( ) / RAND_MAX
< CROSS_RATE
) { for ( int br = 0 ; br < BLOCK; br++ ) {
for ( int bc = 0 ; bc < BLOCK; bc++ ) {
// zamien blok
for ( int di = 0 ; di < BLOCK; di++ )
for ( int dj = 0 ; dj < BLOCK; dj++ ) {
int r = br* BLOCK+ di, c = bc* BLOCK+ dj;
int tmp = c1-> grid[ r] [ c] ;
c1-> grid[ r] [ c] = c2-> grid[ r] [ c] ;
c2-> grid[ r] [ c] = tmp;
}
}
}
}
}
c1-> fitness = evaluate_fitness( c1) ;
c2-> fitness = evaluate_fitness( c2) ;
}
// mutacja = w jednym bloku zamienia dwie losowe puste komorki
void mutate( Individual * ind, int generation) {
if ( ( double ) rand ( ) / RAND_MAX
>= MUT_RATE
) return ; int br = rand_range( 0 , BLOCK- 1 ) , bc = rand_range( 0 , BLOCK- 1 ) ;
int idxs[ SIZE] , m = 0 ;
for ( int di = 0 ; di < BLOCK; di++ )
for ( int dj = 0 ; dj < BLOCK; dj++ ) {
int r = br* BLOCK+ di, c = bc* BLOCK+ dj;
if ( puzzle[ r] [ c] == 0 ) idxs[ m++ ] = r* SIZE + c;
}
if ( m < 2 ) return ;
int a
= idxs
[ rand ( ) % m
] , b
= idxs
[ rand ( ) % m
] ; if ( a != b) {
int r1 = a/ SIZE, c1 = a% SIZE;
int r2 = b/ SIZE, c2 = b% SIZE;
int tmp = ind-> grid[ r1] [ c1] ;
ind-> grid[ r1] [ c1] = ind-> grid[ r2] [ c2] ;
ind-> grid[ r2] [ c2] = tmp;
ind-> fitness = evaluate_fitness( ind) ;
}
}
// glowna petla
void do_sudoku_ga( void ) {
Individual pop[ POP_SIZE] , newpop[ POP_SIZE] ;
// inicjalizacja populacji
for ( int i = 0 ; i < POP_SIZE; i++ ) entry_individual( & pop[ i] ) ;
Individual best = pop[ 0 ] ;
for ( int gen = 1 ; gen <= MAX_GEN; gen++ ) {
// aktualizacja najlepszego
for ( int i = 0 ; i < POP_SIZE; i++ )
if ( pop[ i] .fitness > best.fitness ) best = pop[ i] ;
// raport co mniej jesli wystarczy
if ( gen % REPORT_GEN == 0 ) print_iteration( gen, & best) ;
// tworzenie nastepnej populacji
for ( int i = 0 ; i < POP_SIZE; i += 2 ) {
Individual * p1 = tournament_selection( pop) ;
Individual * p2 = tournament_selection( pop) ;
crossover( p1, p2, & newpop[ i] , & newpop[ i+ 1 ] , gen) ;
mutate( & newpop[ i] , gen) ;
mutate( & newpop[ i+ 1 ] , gen) ;
}
memcpy ( pop
, newpop
, sizeof pop
) ; // znaleziono idealne rozwiazanie
if ( best.fitness == 2 * SIZE * SIZE) break ;
}
// wynik
printf ( "\n Final best fitness %d/%d\n " , best.
fitness , 2 * SIZE
* SIZE
) ; print_individual( & best) ;
}
// wyswietlenie
void print_individual( const Individual * ind) {
for ( int i = 0 ; i < SIZE; i++ ) {
for ( int j = 0 ; j < SIZE; j++ )
printf ( "%d " , ind
-> grid
[ i
] [ j
] ) ; }
}
// raport
void print_iteration( int gen, const Individual * best) {
printf ( "Gen %4d, best fitness=%3d\n " , gen
, best
-> fitness
) ; }
int main( void ) {
do_sudoku_ga( ) ;
return 0 ;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8dGltZS5oPgojaW5jbHVkZSA8bWF0aC5oPgojaW5jbHVkZSA8c3RkYm9vbC5oPgoKI2RlZmluZSBTSVpFICAgICAgICA5ICAgICAgLy8gcm96bWlhciBwbGFuc3p5CiNkZWZpbmUgQkxPQ0sgICAgICAgMyAgICAgIC8vIHJvem1pYXIgYmxva3UgM3gzCgovLyBwYXJhbWV0cnkgR0EKI2RlZmluZSBQT1BfU0laRSAgICAyMDAgICAgLy8gbGljemVibm9zYyBwb3B1bGFjamkKI2RlZmluZSBNQVhfR0VOICAgICA1MDAwICAgLy8gbWFrc3ltYWxuYSBsaWN6YmEgZ2VuZXJhY2ppCiNkZWZpbmUgVE9VUk5fU0laRSAgMyAgICAgIC8vIGxpY3piYSB3IHR1cm5pZWp1CiNkZWZpbmUgQ1JPU1NfUkFURSAgMC4wNSAgICAvLyBwcmF3ZG9wb2RvYmllbnN0d28ga3J6eXpvd2FuaWEKI2RlZmluZSBNVVRfUkFURSAgICAwLjA1ICAgIC8vIHByYXdkb3BvZG9iaWVuc3R3byBtdXRhY2ppCgojZGVmaW5lIFJFUE9SVF9HRU4gNTAgICAgICAvLyByYXBvcnQgY28KCi8vIGRhbmUgc3Vkb2t1LCAwID0gcHVzdGUgcG9sZQppbnQgcHV6emxlW1NJWkVdW1NJWkVdID0gewogICAgezUsMywwLCAwLDcsMCwgMCwwLDB9LAogICAgezYsMCwwLCAxLDksNSwgMCwwLDB9LAogICAgezAsOSw4LCAwLDAsMCwgMCw2LDB9LAoKICAgIHs4LDAsMCwgMCw2LDAsIDAsMCwzfSwKICAgIHs0LDAsMCwgOCwwLDMsIDAsMCwxfSwKICAgIHs3LDAsMCwgMCwyLDAsIDAsMCw2fSwKCiAgICB7MCw2LDAsIDAsMCwwLCAyLDgsMH0sCiAgICB7MCwwLDAsIDQsMSw5LCAwLDAsNX0sCiAgICB7MCwwLDAsIDAsOCwwLCAwLDcsOX0KfTsKCi8vIHN0cnVrdHVyYSBqZWRuZWdvIG9zb2JuaWthCnR5cGVkZWYgc3RydWN0IHsKICAgIGludCBncmlkW1NJWkVdW1NJWkVdOyAvLyB3YXJ0b3NjaSB3IGtvbW9ya2FjaAogICAgaW50IGZpdG5lc3M7ICAgICAgICAgIC8vIG9jZW5hIGRvcGFzb3dhbmlhCn0gSW5kaXZpZHVhbDsKCi8vIGRla2xhcmFjamUgZnVua2NqaQp2b2lkIGVudHJ5X2luZGl2aWR1YWwoSW5kaXZpZHVhbCAqaW5kKTsKaW50ICBldmFsdWF0ZV9maXRuZXNzKGNvbnN0IEluZGl2aWR1YWwgKmluZCk7CkluZGl2aWR1YWwqIHRvdXJuYW1lbnRfc2VsZWN0aW9uKEluZGl2aWR1YWwgcG9wW10pOwp2b2lkIGNyb3Nzb3Zlcihjb25zdCBJbmRpdmlkdWFsICpwMSwgY29uc3QgSW5kaXZpZHVhbCAqcDIsCiAgICAgICAgICAgICAgIEluZGl2aWR1YWwgKmMxLCBJbmRpdmlkdWFsICpjMiwgaW50IGdlbmVyYXRpb24pOwp2b2lkIG11dGF0ZShJbmRpdmlkdWFsICppbmQsIGludCBnZW5lcmF0aW9uKTsKdm9pZCBkb19zdWRva3VfZ2Eodm9pZCk7CnZvaWQgcHJpbnRfaW5kaXZpZHVhbChjb25zdCBJbmRpdmlkdWFsICppbmQpOwp2b2lkIHByaW50X2l0ZXJhdGlvbihpbnQgZ2VuLCBjb25zdCBJbmRpdmlkdWFsICpiZXN0KTsKCi8vIGxvc293YSBsaWN6YmEgeiBwcnplZHppYWx1IFthLGJdCnN0YXRpYyBpbnQgcmFuZF9yYW5nZShpbnQgYSwgaW50IGIpIHsKICAgIHJldHVybiBhICsgcmFuZCgpICUgKGIgLSBhICsgMSk7Cn0KCi8vIGluaWNqYWxpemFjamEgb3NvYm5pa2E6IHV6dXBlbG5pZW5pZSBwdXN0eWNoIHBvbCB3IGJsb2thY2ggM3gzCnZvaWQgZW50cnlfaW5kaXZpZHVhbChJbmRpdmlkdWFsICppbmQpIHsKICAgIGJvb2wgZml4ZWRbU0laRV1bU0laRV0gPSB7ZmFsc2V9OwogICAgLy8gc2tvcGl1aiBzdGFsZSB3YXJ0CiAgICBmb3IgKGludCBpID0gMDsgaSA8IFNJWkU7IGkrKykgewogICAgICAgIGZvciAoaW50IGogPSAwOyBqIDwgU0laRTsgaisrKSB7CiAgICAgICAgICAgIGluZC0+Z3JpZFtpXVtqXSA9IHB1enpsZVtpXVtqXTsKICAgICAgICAgICAgZml4ZWRbaV1bal0gPSAocHV6emxlW2ldW2pdICE9IDApOwogICAgICAgIH0KICAgIH0KICAgIC8vIHd5cGXFgm5paiBrYXpkeSBibG9rCiAgICBmb3IgKGludCBiciA9IDA7IGJyIDwgQkxPQ0s7IGJyKyspIHsKICAgICAgICBmb3IgKGludCBiYyA9IDA7IGJjIDwgQkxPQ0s7IGJjKyspIHsKICAgICAgICAgICAgYm9vbCBwcmVzZW50W1NJWkUrMV0gPSB7ZmFsc2V9OwogICAgICAgICAgICAvLyB6YXpuYWN6IGp1eiBvYmVjbmUgd2FydG9zY2kKICAgICAgICAgICAgZm9yIChpbnQgZGkgPSAwOyBkaSA8IEJMT0NLOyBkaSsrKQogICAgICAgICAgICBmb3IgKGludCBkaiA9IDA7IGRqIDwgQkxPQ0s7IGRqKyspIHsKICAgICAgICAgICAgICAgIGludCB2ID0gaW5kLT5ncmlkW2JyKkJMT0NLK2RpXVtiYypCTE9DSytkal07CiAgICAgICAgICAgICAgICBpZiAodikgcHJlc2VudFt2XSA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaW50IG1pc3NpbmdbU0laRV0sIG0gPSAwOwogICAgICAgICAgICAvLyB6YmllcnogYnJha3VqYWNlCiAgICAgICAgICAgIGZvciAoaW50IHYgPSAxOyB2IDw9IFNJWkU7IHYrKykKICAgICAgICAgICAgICAgIGlmICghcHJlc2VudFt2XSkgbWlzc2luZ1ttKytdID0gdjsKICAgICAgICAgICAgLy8gbG9zb3dvIHByemVtaWVzemFqIGJyYWt1amFjZQogICAgICAgICAgICBmb3IgKGludCB4ID0gbS0xOyB4ID4gMDsgeC0tKSB7CiAgICAgICAgICAgICAgICBpbnQgeSA9IHJhbmQoKSAlICh4KzEpOwogICAgICAgICAgICAgICAgaW50IHRtcCA9IG1pc3NpbmdbeF07IG1pc3NpbmdbeF0gPSBtaXNzaW5nW3ldOyBtaXNzaW5nW3ldID0gdG1wOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIHdzdGF3IHcgcHVzdGUgbWllanNjYQogICAgICAgICAgICBpbnQgaWR4ID0gMDsKICAgICAgICAgICAgZm9yIChpbnQgZGkgPSAwOyBkaSA8IEJMT0NLOyBkaSsrKQogICAgICAgICAgICBmb3IgKGludCBkaiA9IDA7IGRqIDwgQkxPQ0s7IGRqKyspIHsKICAgICAgICAgICAgICAgIGludCByID0gYnIqQkxPQ0srZGksIGMgPSBiYypCTE9DSytkajsKICAgICAgICAgICAgICAgIGlmICghZml4ZWRbcl1bY10pIGluZC0+Z3JpZFtyXVtjXSA9IG1pc3NpbmdbaWR4KytdOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogICAgLy8gb2JsaWN6IGZpdG5lc3MgcG9jemF0a293eQogICAgaW5kLT5maXRuZXNzID0gZXZhbHVhdGVfZml0bmVzcyhpbmQpOwp9CgovLyBvY2VuYSBpbGUgcm96bnljaCBsaWN6YiB3IGthemR5bSB3aWVyc3p1IGkga29sdW1uaWUKaW50IGV2YWx1YXRlX2ZpdG5lc3MoY29uc3QgSW5kaXZpZHVhbCAqaW5kKSB7CiAgICBpbnQgc2NvcmUgPSAwOwogICAgaW50IHJvd19jbnRbU0laRSsxXSwgY29sX2NudFtTSVpFKzFdOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBTSVpFOyBpKyspIHsKICAgICAgICBtZW1zZXQocm93X2NudCwgMCwgc2l6ZW9mIHJvd19jbnQpOwogICAgICAgIG1lbXNldChjb2xfY250LCAwLCBzaXplb2YgY29sX2NudCk7CiAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogPCBTSVpFOyBqKyspIHsKICAgICAgICAgICAgcm93X2NudFtpbmQtPmdyaWRbaV1bal1dKys7CiAgICAgICAgICAgIGNvbF9jbnRbaW5kLT5ncmlkW2pdW2ldXSsrOwogICAgICAgIH0KICAgICAgICBmb3IgKGludCB2ID0gMTsgdiA8PSBTSVpFOyB2KyspIHsKICAgICAgICAgICAgaWYgKHJvd19jbnRbdl0gPiAwKSBzY29yZSsrOwogICAgICAgICAgICBpZiAoY29sX2NudFt2XSA+IDApIHNjb3JlKys7CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuIHNjb3JlOwp9CgovLyBzZWxla2NqYSB0dXJuaWVqb3dhLCBuYWpsZXBzemUgeiBUT1VSTl9TSVpFIG9zb2JuaWtvdwpJbmRpdmlkdWFsKiB0b3VybmFtZW50X3NlbGVjdGlvbihJbmRpdmlkdWFsIHBvcFtdKSB7CiAgICBJbmRpdmlkdWFsICpiZXN0ID0gTlVMTDsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgVE9VUk5fU0laRTsgaSsrKSB7CiAgICAgICAgSW5kaXZpZHVhbCAqY2FuZCA9ICZwb3BbcmFuZCgpICUgUE9QX1NJWkVdOwogICAgICAgIGlmICghYmVzdCB8fCBjYW5kLT5maXRuZXNzID4gYmVzdC0+Zml0bmVzcykgYmVzdCA9IGNhbmQ7CiAgICB9CiAgICByZXR1cm4gYmVzdDsKfQoKLy8ga3J6eXpvd2FuaWUgc3dhcHVqIGxvc293byBibG9raSAzeDMgeiBDUk9TU19SQVRFICUKdm9pZCBjcm9zc292ZXIoY29uc3QgSW5kaXZpZHVhbCAqcDEsIGNvbnN0IEluZGl2aWR1YWwgKnAyLAogICAgICAgICAgICAgICBJbmRpdmlkdWFsICpjMSwgSW5kaXZpZHVhbCAqYzIsIGludCBnZW5lcmF0aW9uKSB7CiAgICAvLyBza29waXVqIHJvZHppY293CiAgICBtZW1jcHkoYzEtPmdyaWQsIHAxLT5ncmlkLCBzaXplb2YgcDEtPmdyaWQpOwogICAgbWVtY3B5KGMyLT5ncmlkLCBwMi0+Z3JpZCwgc2l6ZW9mIHAyLT5ncmlkKTsKICAgIGlmICgoZG91YmxlKXJhbmQoKS9SQU5EX01BWCA8IENST1NTX1JBVEUpIHsKICAgICAgICBmb3IgKGludCBiciA9IDA7IGJyIDwgQkxPQ0s7IGJyKyspIHsKICAgICAgICAgICAgZm9yIChpbnQgYmMgPSAwOyBiYyA8IEJMT0NLOyBiYysrKSB7CiAgICAgICAgICAgICAgICBpZiAocmFuZCgpJTIpIHsKICAgICAgICAgICAgICAgICAgICAvLyB6YW1pZW4gYmxvawogICAgICAgICAgICAgICAgICAgIGZvciAoaW50IGRpID0gMDsgZGkgPCBCTE9DSzsgZGkrKykKICAgICAgICAgICAgICAgICAgICBmb3IgKGludCBkaiA9IDA7IGRqIDwgQkxPQ0s7IGRqKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgaW50IHIgPSBicipCTE9DSytkaSwgYyA9IGJjKkJMT0NLK2RqOwogICAgICAgICAgICAgICAgICAgICAgICBpbnQgdG1wID0gYzEtPmdyaWRbcl1bY107CiAgICAgICAgICAgICAgICAgICAgICAgIGMxLT5ncmlkW3JdW2NdID0gYzItPmdyaWRbcl1bY107CiAgICAgICAgICAgICAgICAgICAgICAgIGMyLT5ncmlkW3JdW2NdID0gdG1wOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgIGMxLT5maXRuZXNzID0gZXZhbHVhdGVfZml0bmVzcyhjMSk7CiAgICBjMi0+Zml0bmVzcyA9IGV2YWx1YXRlX2ZpdG5lc3MoYzIpOwp9CgovLyBtdXRhY2phID0gdyBqZWRueW0gYmxva3UgemFtaWVuaWEgZHdpZSBsb3Nvd2UgcHVzdGUga29tb3JraQp2b2lkIG11dGF0ZShJbmRpdmlkdWFsICppbmQsIGludCBnZW5lcmF0aW9uKSB7CiAgICBpZiAoKGRvdWJsZSlyYW5kKCkvUkFORF9NQVggPj0gTVVUX1JBVEUpIHJldHVybjsKICAgIGludCBiciA9IHJhbmRfcmFuZ2UoMCwgQkxPQ0stMSksIGJjID0gcmFuZF9yYW5nZSgwLCBCTE9DSy0xKTsKICAgIGludCBpZHhzW1NJWkVdLCBtID0gMDsKICAgIGZvciAoaW50IGRpID0gMDsgZGkgPCBCTE9DSzsgZGkrKykKICAgIGZvciAoaW50IGRqID0gMDsgZGogPCBCTE9DSzsgZGorKykgewogICAgICAgIGludCByID0gYnIqQkxPQ0srZGksIGMgPSBiYypCTE9DSytkajsKICAgICAgICBpZiAocHV6emxlW3JdW2NdID09IDApIGlkeHNbbSsrXSA9IHIqU0laRSArIGM7CiAgICB9CiAgICBpZiAobSA8IDIpIHJldHVybjsKICAgIGludCBhID0gaWR4c1tyYW5kKCklbV0sIGIgPSBpZHhzW3JhbmQoKSVtXTsKICAgIGlmIChhICE9IGIpIHsKICAgICAgICBpbnQgcjEgPSBhL1NJWkUsIGMxID0gYSVTSVpFOwogICAgICAgIGludCByMiA9IGIvU0laRSwgYzIgPSBiJVNJWkU7CiAgICAgICAgaW50IHRtcCA9IGluZC0+Z3JpZFtyMV1bYzFdOwogICAgICAgIGluZC0+Z3JpZFtyMV1bYzFdID0gaW5kLT5ncmlkW3IyXVtjMl07CiAgICAgICAgaW5kLT5ncmlkW3IyXVtjMl0gPSB0bXA7CiAgICAgICAgaW5kLT5maXRuZXNzID0gZXZhbHVhdGVfZml0bmVzcyhpbmQpOwogICAgfQp9CgovLyBnbG93bmEgcGV0bGEKdm9pZCBkb19zdWRva3VfZ2Eodm9pZCkgewogICAgc3JhbmQoKHVuc2lnbmVkKXRpbWUoTlVMTCkpOwogICAgSW5kaXZpZHVhbCBwb3BbUE9QX1NJWkVdLCBuZXdwb3BbUE9QX1NJWkVdOwogICAgLy8gaW5pY2phbGl6YWNqYSBwb3B1bGFjamkKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgUE9QX1NJWkU7IGkrKykgZW50cnlfaW5kaXZpZHVhbCgmcG9wW2ldKTsKICAgIEluZGl2aWR1YWwgYmVzdCA9IHBvcFswXTsKCiAgICBmb3IgKGludCBnZW4gPSAxOyBnZW4gPD0gTUFYX0dFTjsgZ2VuKyspIHsKICAgICAgICAvLyBha3R1YWxpemFjamEgbmFqbGVwc3plZ28KICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IFBPUF9TSVpFOyBpKyspCiAgICAgICAgICAgIGlmIChwb3BbaV0uZml0bmVzcyA+IGJlc3QuZml0bmVzcykgYmVzdCA9IHBvcFtpXTsKICAgICAgICAvLyByYXBvcnQgY28gbW5pZWogamVzbGkgd3lzdGFyY3p5CiAgICAgICAgaWYgKGdlbiAlIFJFUE9SVF9HRU4gPT0gMCkgcHJpbnRfaXRlcmF0aW9uKGdlbiwgJmJlc3QpOwogICAgICAgIC8vIHR3b3J6ZW5pZSBuYXN0ZXBuZWogcG9wdWxhY2ppCiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBQT1BfU0laRTsgaSArPSAyKSB7CiAgICAgICAgICAgIEluZGl2aWR1YWwgKnAxID0gdG91cm5hbWVudF9zZWxlY3Rpb24ocG9wKTsKICAgICAgICAgICAgSW5kaXZpZHVhbCAqcDIgPSB0b3VybmFtZW50X3NlbGVjdGlvbihwb3ApOwogICAgICAgICAgICBjcm9zc292ZXIocDEsIHAyLCAmbmV3cG9wW2ldLCAmbmV3cG9wW2krMV0sIGdlbik7CiAgICAgICAgICAgIG11dGF0ZSgmbmV3cG9wW2ldLCAgIGdlbik7CiAgICAgICAgICAgIG11dGF0ZSgmbmV3cG9wW2krMV0sIGdlbik7CiAgICAgICAgfQogICAgICAgIG1lbWNweShwb3AsIG5ld3BvcCwgc2l6ZW9mIHBvcCk7CiAgICAgICAgLy8gem5hbGV6aW9ubyBpZGVhbG5lIHJvendpYXphbmllCiAgICAgICAgaWYgKGJlc3QuZml0bmVzcyA9PSAyICogU0laRSAqIFNJWkUpIGJyZWFrOwogICAgfQogICAgLy8gd3luaWsKICAgIHByaW50ZigiXG5GaW5hbCBiZXN0IGZpdG5lc3MgJWQvJWRcbiIsIGJlc3QuZml0bmVzcywgMipTSVpFKlNJWkUpOwogICAgcHJpbnRfaW5kaXZpZHVhbCgmYmVzdCk7Cn0KCi8vIHd5c3dpZXRsZW5pZQp2b2lkIHByaW50X2luZGl2aWR1YWwoY29uc3QgSW5kaXZpZHVhbCAqaW5kKSB7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IFNJWkU7IGkrKykgewogICAgICAgIGZvciAoaW50IGogPSAwOyBqIDwgU0laRTsgaisrKQogICAgICAgICAgICBwcmludGYoIiVkICIsIGluZC0+Z3JpZFtpXVtqXSk7CiAgICAgICAgcHJpbnRmKCJcbiIpOwogICAgfQp9CgovLyByYXBvcnQKdm9pZCBwcmludF9pdGVyYXRpb24oaW50IGdlbiwgY29uc3QgSW5kaXZpZHVhbCAqYmVzdCkgewogICAgcHJpbnRmKCJHZW4gJTRkLCBiZXN0IGZpdG5lc3M9JTNkXG4iLCBnZW4sIGJlc3QtPmZpdG5lc3MpOwp9CgppbnQgbWFpbih2b2lkKSB7CiAgICBwcmludGYoIkdBIFN1ZG9rdSBzb2x2ZXJcbiIpOwogICAgZG9fc3Vkb2t1X2dhKCk7CiAgICByZXR1cm4gMDsKfQ==
stdout
GA Sudoku solver
Gen 50, best fitness=147
Gen 100, best fitness=150
Gen 150, best fitness=151
Gen 200, best fitness=151
Gen 250, best fitness=151
Gen 300, best fitness=151
Gen 350, best fitness=153
Gen 400, best fitness=154
Gen 450, best fitness=156
Gen 500, best fitness=156
Gen 550, best fitness=156
Gen 600, best fitness=156
Gen 650, best fitness=156
Gen 700, best fitness=156
Gen 750, best fitness=156
Gen 800, best fitness=156
Gen 850, best fitness=156
Gen 900, best fitness=156
Gen 950, best fitness=156
Gen 1000, best fitness=156
Gen 1050, best fitness=156
Gen 1100, best fitness=156
Gen 1150, best fitness=156
Gen 1200, best fitness=156
Gen 1250, best fitness=156
Gen 1300, best fitness=156
Gen 1350, best fitness=156
Gen 1400, best fitness=156
Gen 1450, best fitness=156
Gen 1500, best fitness=156
Gen 1550, best fitness=156
Gen 1600, best fitness=156
Gen 1650, best fitness=156
Gen 1700, best fitness=156
Gen 1750, best fitness=156
Gen 1800, best fitness=156
Gen 1850, best fitness=156
Gen 1900, best fitness=158
Gen 1950, best fitness=158
Gen 2000, best fitness=158
Gen 2050, best fitness=160
Gen 2100, best fitness=160
Gen 2150, best fitness=160
Gen 2200, best fitness=160
Gen 2250, best fitness=160
Gen 2300, best fitness=160
Gen 2350, best fitness=160
Gen 2400, best fitness=160
Gen 2450, best fitness=160
Gen 2500, best fitness=160
Gen 2550, best fitness=160
Gen 2600, best fitness=160
Gen 2650, best fitness=160
Gen 2700, best fitness=160
Gen 2750, best fitness=160
Gen 2800, best fitness=160
Gen 2850, best fitness=160
Gen 2900, best fitness=160
Gen 2950, best fitness=160
Gen 3000, best fitness=160
Gen 3050, best fitness=160
Gen 3100, best fitness=160
Gen 3150, best fitness=160
Gen 3200, best fitness=160
Gen 3250, best fitness=160
Gen 3300, best fitness=160
Gen 3350, best fitness=160
Gen 3400, best fitness=160
Gen 3450, best fitness=160
Gen 3500, best fitness=160
Gen 3550, best fitness=160
Gen 3600, best fitness=160
Gen 3650, best fitness=160
Gen 3700, best fitness=160
Gen 3750, best fitness=160
Gen 3800, best fitness=160
Gen 3850, best fitness=160
Gen 3900, best fitness=160
Gen 3950, best fitness=160
Gen 4000, best fitness=160
Gen 4050, best fitness=160
Gen 4100, best fitness=160
Gen 4150, best fitness=160
Gen 4200, best fitness=160
Gen 4250, best fitness=160
Gen 4300, best fitness=160
Gen 4350, best fitness=160
Gen 4400, best fitness=160
Gen 4450, best fitness=160
Gen 4500, best fitness=160
Gen 4550, best fitness=160
Gen 4600, best fitness=160
Gen 4650, best fitness=160
Gen 4700, best fitness=160
Gen 4750, best fitness=160
Gen 4800, best fitness=160
Gen 4850, best fitness=160
Gen 4900, best fitness=160
Gen 4950, best fitness=160
Final best fitness 162/162
5 3 4 6 7 8 9 1 2
6 7 2 1 9 5 3 4 8
1 9 8 3 4 2 5 6 7
8 5 9 7 6 1 4 2 3
4 2 6 8 5 3 7 9 1
7 1 3 9 2 4 8 5 6
9 6 1 5 3 7 2 8 4
2 8 7 4 1 9 6 3 5
3 4 5 2 8 6 1 7 9