Algorithm-X-DLX
view release on metacpan or search on metacpan
examples/sudoku/Sudoku.pm view on Meta::CPAN
$self->{values_} = [@$arg];
} elsif (defined $arg && !ref($arg)) {
croak "Got empty string" unless length $arg;
$string = $arg;
} else {
die "Unknown blessed parameter.\n";
}
}
if (! $self->{type_} && $string ) {
$self->{type_} = SudokuType::guess($string);
}
if (! $self->{values_} && $string ) {
$self->{values_} = SudokuFormat::get_values($string);
}
$self->{type_} ||= SudokuType->new();
$self->{values_} ||= [(0) x $self->{type_}->size()];
return bless $self, $class;
examples/sudoku/SudokuFormat.pm view on Meta::CPAN
$self->{template} = $input;
}
if (ref($type_or_format) eq 'SudokuType') {
my $type = $type_or_format;
$self->{type} = $type;
$self->{template} ||= default_template($type);
} else {
my $format = $type_or_format;
my $type = SudokuType::guess($format);
$self->{type} = $type;
$self->{template} ||= $format;
}
$self->{labels} = choose_labels($self->{template});
# Validate cells
my $cells = 0;
foreach my $c (split //, $self->{template}) {
if (is_cell($c, $self)) {
examples/sudoku/SudokuType.pm view on Meta::CPAN
croak "Sudoku must have non-zero size";
}
return $type;
}
sub from_size {
my ($size) = @_;
return new(__PACKAGE__, isqrt($size));
}
sub guess {
my ($str) = @_;
my @lines;
my $line = '';
my $cells = 0;
my $size = SudokuFormat::count_cells($str);
my $n = isqrt($size);
foreach my $c (split //, $str) {
if ($c eq "\n") {
examples/sudoku/SudokuType.pm view on Meta::CPAN
for my $y (0 .. $#lines) {
for my $x (0 .. length($lines[$y]) - 1) {
if (SudokuFormat::is_valid_cell(substr($lines[$y], $x, 1))) {
$total_size++;
$region_size{$region[$y][$x]}++;
push @final_regions, $region[$y][$x];
}
}
}
#print "\%region_size = ", Dumper(\%region_size);
#print "guess(): \$total_size = $total_size, \$size = $size\n";
croak "Total size mismatch" if $total_size != $size;
#print "guess(): \$n = $n, \@final_regions = (@final_regions)\n";
#print Dumper(\%region_size);
for my $p (values %region_size) {
return from_size($size) if $p != $n;
# croak "Region has wrong size" if $p != $n;
}
return new(__PACKAGE__, \@final_regions);
}
sub n {
examples/sudoku/sudoku.pl view on Meta::CPAN
$input .= $line;
if (!$opt_one_sudoku_per_line) {
$input .= "\n";
next unless eof(STDIN);
}
}
$input or next;
eval {
my $type = SudokuType::guess($input);
my $format;
if ($opt_format eq 'PRESERVE') {
$format = SudokuFormat->new($type, $input);
} elsif ($opt_format eq 'COMPACT') {
$format = SudokuFormat->compact($type);
} elsif ($opt_format eq 'ONELINE') {
$format = SudokuFormat->oneline($type);
} else {
$format = SudokuFormat->new($type);
examples/t/sudoku/02-sudokutype.t view on Meta::CPAN
lives_ok { SudokuType->new([0]) } 'valid type';
lives_ok { SudokuType->new([1]) } 'valid type';
lives_ok { SudokuType->new([999]) } 'valid type';
lives_ok { SudokuType->new([0, 0, 1, 1]) } 'valid type';
lives_ok { SudokuType->new([0, 1, 1, 0]) } 'valid type';
is_deeply(SudokuType->new([0, 0, 1, 1]), SudokuType->new([6, 6, 2, 2]), 'same custom type');
};
subtest 'guess type nxn regions' => sub {
plan tests => 7;
throws_ok { SudokuType::guess(join '',
"....",
"....",
"....",
"..."
) } qr/Not a square/i, 'corrupt lines';
throws_ok { SudokuType::guess(join '',
"....",
"....",
"....",
"....."
) } qr/Not a square/i, 'corrupt lines';
is_deeply(SudokuType->new(1), SudokuType::guess(join '',
"+-+\n",
"|.|\n",
"+-+\n"
), 'same custom type');
is_deeply(SudokuType->new(4), SudokuType::guess(join '',
"....",
"....",
"....",
"....",
), 'same custom type');
is_deeply(SudokuType->new(4), SudokuType::guess(join '',
". .|..\n",
". .|..\n",
" +-+--\n",
".|.|..\n",
"-+ | \n",
". .|..\n"
), 'same custom type');
is_deeply(SudokuType->new(4), SudokuType::guess(join '',
"..|..\n",
"..|..\n",
"..|..\n",
"--+--\n",
"..|..\n"
), 'same custom type');
is_deeply(SudokuType->new(4), SudokuType::guess(join '',
".1|..\n",
"..|2.\n",
"-----\n",
"z.|..\n",
".a|..\n"
), 'same custom type');
};
subtest 'guess type nxm regions' => sub {
plan tests => 6;
is_deeply(SudokuType->new(4, 1), SudokuType::guess(join '',
"....\n",
"----\n",
"....\n",
"----\n",
"....\n",
"----\n",
"....\n"
), 'same custom type');
is_deeply(SudokuType->new(1, 4), SudokuType::guess(join '',
".|.|.|.\n",
".|.|.|.\n",
".|.|.|.\n",
".|.|.|.\n"
), 'same custom type');
is_deeply(SudokuType->new(3, 2), SudokuType::guess(join '',
"|...|...|\n",
"|...|...|\n",
"|-------|\n",
"|...|...|\n",
"|...|...|\n",
"|-------|\n",
"|...|...|\n",
"|...|...|\n"
), 'same custom type');
is_deeply(SudokuType->new(3, 2), SudokuType::guess(join '',
"|...|...|\n",
"|...|...|\n",
"\n",
"|...|...|\n",
"|...|...|\n",
"\n",
"|...|...|\n",
"|...|...|\n"
), 'same custom type');
is_deeply(SudokuType->new(3, 2), SudokuType::guess(join '',
"...|......|...\n\n",
"...|......|...\n\n",
"...|......|..."
), 'same custom type');
is_deeply(SudokuType->new(3, 2), SudokuType::guess(join '',
"|. ..|...|\n",
"|. ..|...|\n",
"----------\n",
"|. ..|...|\n",
"|. ..|...|\n",
"----------\n",
"|. ..|...|\n",
"| | |\n",
"|. ..|...|\n"
), 'same custom type');
};
subtest 'guess arbitrary regions' => sub {
plan tests => 5;
is_deeply(SudokuType->new([
0, 0, 1, 1, 1, 1, 2,
0, 0, 0, 1, 1, 1, 2,
3, 0, 0, 4, 4, 2, 2,
3, 3, 4, 4, 4, 2, 2,
3, 3, 4, 4, 5, 5, 2,
3, 6, 6, 6, 5, 5, 5,
3, 6, 6, 6, 6, 5, 5,
]), SudokuType::guess(join '',
"+---+-------+-+\n",
"|. .|. . . .|.|\n",
"| +-+ | |\n",
"|. . .|. . .|.|\n",
"+-+ +---+-+ |\n",
"|.|. .|. .|. .|\n",
"| +-+-+ | |\n",
"|. .|. . .|. .|\n",
"| | +-+-+ |\n",
"|. .|. .|. .|.|\n",
examples/t/sudoku/02-sudokutype.t view on Meta::CPAN
"|.|. . .|. . .|\n",
"| | +-+ |\n",
"|.|. . . .|. .|\n",
"+-+-------+---+\n"
), 'same arbitrary type');
is_deeply(SudokuType->new([
0, 0, 0, 1,
0, 1, 1, 1,
2, 3, 3, 3,
2, 2, 2, 3,
]), SudokuType::guess(join '',
". ..|.\n",
" -- \n",
".|.. .\n",
"------\n",
".|.. .\n",
" -- \n",
". ..|.\n"
), 'same arbitrary type');
is_deeply(SudokuType->new([
0, 0, 0, 1,
0, 1, 1, 1,
2, 3, 3, 3,
2, 2, 2, 3,
]), SudokuType::guess(join '',
"...|.\n",
" / \n",
".|...\n",
"-----\n",
".|...\n",
" --- \n",
"...|.\n"
), 'same arbitrary type');
is_deeply(SudokuType->new([
0, 0, 0, 1,
0, 1, 1, 1,
2, 3, 3, 3,
2, 2, 2, 3,
]), SudokuType::guess(join '',
"...,.",
".!!...\n",
"\n",
".@#...",
"..._."
), 'same arbitrary type');
is_deeply(SudokuType->new([
0, 0, 0, 1,
0, 1, 1, 1,
2, 3, 3, 3,
2, 2, 2, 3,
]), SudokuType::guess(
"...,..=]...\n\n.:)......_."
), 'same arbitrary type');
};
done_testing();
( run in 0.578 second using v1.01-cache-2.11-cpan-702932259ff )