[Haskell-cafe] Code Review: Sudoku solver

Daniel Fischer daniel.is.fischer at web.de
Sat Apr 8 19:21:42 EDT 2006


Am Samstag, 8. April 2006 02:20 schrieb Daniel Fischer:
> Am Freitag, 7. April 2006 17:33 schrieben Sie:
> > > Just out of curiosity, speed was not the objective when I wrote my
> > > solver, I wanted to avoid guesswork (as much as possible), but in
> > > comparison with Cale Gibbard's and Alson Kemp's solvers (which are much
> > > more beautifully coded), it turned out that mine is blazingly fast, so
> > > are there faster solvers around (in Haskell, in other languages)?
> >
> > if I modify your solver to produce similar output to mine (input/first
> > propagation, solved puzzle, number and list of guesses made), your's
> > takes about a third of the time of mine (solving 36628 17hint puzzles
> > in 6m vs 17m, 2GHz Pentium M), and I wasn't exactly unhappy with
> > my solver before I did this comparison!-)
>
> Mine's even faster now (at least on my computer, would you care to test it
> on your's? If you don't want to get EnumSet, just change DiffArray to
> Array, worked wonders for me), I'll dig into yours tomorrow to see what I
> can get out of it to improve my algorithm.

Unforunately, no new inference rules :-(
Two things I don't like about your code:
1. no type declarations
2. too much name shadowing, that makes following the code difficult

apart from that: clever
>
> > like you, I've been trying to remove guesses, and the speed came as a
> > welcome bonus (I'm still using lists all over the place, with lots of not
> > nice adhoc code still remaining; not all propagators are iterated fully
>
> lists and adhoc code tend to be performance killers, I doubled the speed of
> mine by de-adhoccing the code (and that although I introduced the
> speed-killer DiffArray)

I believe if you change the representation of puzzles from [(pos,range)]
to an Array, you'll get a significant speedup
>
> > yet because I only recently removed a logic bug that slowed down the
> > search instead of speading it up; ..). so the more interesting bit is
> > that our solvers disagree on which are the most difficult puzzles
> > (requiring the largest number of guesses):
> >
> > df
> > puzzles involving guesses: 5319
>
> If that's not a typo, I'm baffled. My original needed to guess in 5309

Rot! Typo in _my_ previous message, 5319 is correct.

> puzzles, and I can't imagine what inference I could have dropped when
> cleaning up the code.
>
> > largest number of guesses:
> >     10 (#36084), 11 (#22495)
> >
> > cr
> > puzzles involving guesses: 8165
> > largest number of guesses:
> >     10 (#9175), 10 (#17200), 10 (#29823), 10 (#30811)
> >
> > df's solver needs 0/0/3/0 for cr's trouble spots, while cr's solver needs
> > 5/9 guesses for df's. lots of potential for interesting investigations,

We use different guessing strategies (plus, I also have group-inference).
But the given number of guesses is the number of guesses in the successful 
branch, and I think a better measure for the nefariousness of a puzzle is the 
accumulated number of guesses in all branches or the number of branches 
(still better is the time needed to solve the puzzle).

This is the list of the 30 puzzles with the most branches:
puzzle  #branches
  3992   213
  7475   120
 12235   117
  5341    69
 11815    60
  9402    60
 11544    59
  9184    54
 10403    50
 31110    48
  8575    48
  1489    45
  2732    40
 11523    39
  6730    39
 10929    38
   960    35
 19474    32
  6412    31
  1599    30
 36084    29
 21832    29
 22495    28
  4657    28
 34747    27
 10404    27
 29931    26
   942    25
   563    24

the top 30 in CPUTime (in milliseconds, cpuTimePrecision = 10^10)
  3992  6480
  9184  1520
 31110  1470
 10403  1310
 12235  1260
  7475  1130
  2732  1080
   960  1050
  5341   990
 11544   960
 11815   930
  1395   730
 10929   710
  1863   710
  1330   700
 20807   630
  4181   610
 10634   570
 34401   550
   959   550
 34747   520
  1599   520
 14912   510
 29282   500
  7983   500
 29273   480
 23958   470
  2245   460
  2232   440
 36425   430

so puzzle 3992 is outstandingly bad in both respects (I fed it into my old 
step by step solver and boy, failure is detected _very_ late in practically 
all branches) and from a couple of tests I have the vague impression that the 
correlation between the number of guesses in the successful branch and time 
is not very strong (3992 has 6, 9184 and 2732 only 3, 31110 has 5, 10403 8, 
12235 9, 7475 6 and 960 7), but I don't think I'll do a statistical analysis, 
I'll stick to time as the measure.

Here's the meanest puzzle:

0 0 0 0 4 0 0 5 9
3 0 0 2 0 0 0 0 0
1 0 0 0 0 0 0 0 0
0 0 0 1 0 0 7 0 0
0 4 6 0 0 0 0 0 0
9 5 0 0 0 0 0 0 0
0 0 0 0 5 6 0 4 0
0 0 0 8 0 0 3 0 0
0 0 0 0 0 0 0 0 0

and that's so mean that David Place's incrsud beats my solver on this by a 
factor of 5.5!

> > though mostly for me!-)
>
> ^^^^^^^^^^^^^^^^^^^^^^^^^^
> I'm not sure about that :-)
>
> > cheers,
> > claus
>
Cheers again,
Daniel

-- 

"In My Egotistical Opinion, most people's C programs should be
indented six feet downward and covered with dirt."
	-- Blair P. Houghton



More information about the Haskell-Cafe mailing list