use strict; use warnings; my $s= [ [ 9, 0, 0, 6, 3, 0, 0, 0, 4 ], [ 0, 1, 0, 2, 5, 8, 0, 0, 0 ], [ 0, 0, 0, 7, 0, 0, 0, 0, 8 ], [ 6, 4, 0, 0, 2, 0, 5, 0, 0 ], [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 8, 2, 0, 5, 0, 0, 0, 9, 0 ], [ 0, 0, 0, 0, 0, 0, 8, 7, 0 ], [ 3, 0, 0, 0, 0, 5, 0, 4, 0 ], [ 0, 0, 1, 0, 7, 6, 0, 0, 0 ], ]; sub getrow { my ($s, $row)= @_; my @a; for my $col (0..8) { push @a, $s->[$row][$col]; } return \@a; } sub getcol { my ($s, $col)= @_; my @a; for my $row (0..8) { push @a, $s->[$row][$col]; } return \@a; } sub getsub { my ($s, $sub)= @_; my $subcol= int($sub/3); my $subrow= $sub%3; my @a; for my $row (0..2) { for my $col (0..2) { push @a, $s->[$subrow+$row][$subcol+$col]; } } return \@a; } sub findunused { my ($a)= @_; my %x; $x{$_}++ for (@$a); my @a; for my $digit (1..9) { if (!exists $x{$digit}) { push @a, $digit; } } return \@a; } sub intersect { my %x; for my $a (@_) { $x{$_}++ for (@{$a}); } return [ grep { $x{$_} == @_ } keys %x ]; } sub print_sudoku { my ($s)= @_; for my $row (0..8) { for my $col (0..8) { print $s->[$row][$col]; } print "\n"; } print "\n"; } while (1) { my $ur; my $uc; my $us; for my $row (0..8) { $ur->[$row]= findunused( getrow($s, $row)); } for my $col (0..8) { $uc->[$col]= findunused( getcol($s, $col)); } for my $sub (0..8) { $us->[$sub]= findunused( getsub($s, $sub)); } for my $row (0..8) { for my $col (0..8) { my $sub= int($row/3)*3+int($col/3); if ($s->[$row][$col]==0) { my $ii= intersect($ur->[$row], $uc->[$col], $us->[$sub]); if (@{$ii} == 1) { $s->[$row][$col]= $ii->[0]; } } } } print_sudoku($s); }