Re: /$sudoku/
Ilmari Karonen <[email protected]> Thu, 20 Apr 2006 19:27:35 +0300
| Newsgroups | gmane.comp.lang.perl.fun |
|---|---|
| Organization | vyznev.net |
| Message-ID | <[email protected]> |
Ilmari Karonen wrote:
> Sudoku solvers are old hat, of course, but this one is a bit different:
> it's a regexp. I suppose someone may have done this before, but if so,
> I haven't seen it. It's grossly inefficient, of course, solving the
> puzzle entirely by guesswork and backtracking, but that's not really the
> point. (It could be made quite a bit faster by hardcoding the givens in
> the regexp, but that would make the regexp non-generic.)
Incidentally, here's the hardcoded-givens version. It's indeed quite a
lot faster the generic version -- I've yet to find a puzzle that would
take more than 0.1 seconds to solve on my workstation.
#!/usr/bin/perl -w
use strict;
while (defined(my $str = <>)) {
chomp $str;
length($str) != 81 || $str =~ tr/1-9_//c
and (print("Bad input.\n"), next);
$str =~ tr/_/0/;
my $sudoku = ("^.*" .
(join ".*\n.*",
map {
my $n = $_;
("(?!" .
((join "|",
(map substr($str,$_,1) ||
($_ < $n ? "\\" . ($_+1) : ()),
(grep $_ != $n &&
(int($_ % 9) == int($n % 9) ||
int($_ / 9) == int($n / 9) ||
int($_ / 27) == int($n / 27) &&
int($_ / 3 % 3) == int($n / 3 % 3)),
0..80))) || "x") .
")(.)");
} 0..80) .
".*\$"
);
$str =~ s/(.)/$1 ? "$1\n" : "123456789\n"/eg;
print((join("", $str =~ /$sudoku/) || "No solution."), "\n");
}
__END__
--
Ilmari Karonen