[Haskell-cafe] Code Review: Sudoku solver

Daniel Fischer daniel.is.fischer at web.de
Sat Apr 8 22:06:18 EDT 2006


Am Samstag, 8. April 2006 20:28 schrieb Chris Kuklewicz:
> I have finished my cleanup of the dancing links based solver for Sudoku.
>
> I don't have time to compare performance with the other programs that have
> been posted recently, or to do more profiling of my code.

Your dancing links:

ckSud +RTS -sstderr -H32M -A8M < sudoku17 > Solutions.txt
ckSud +RTS -sstderr -H32M -A8M
62,941,602,892 bytes allocated in the heap
330,404,632 bytes copied during GC
    465,944 bytes maximum residency (41 sample(s))

       2023 collections in generation 0 ( 15.60s)
         41 collections in generation 1 (  0.30s)

         32 Mb total memory in use

  INIT  time    0.00s  (  0.00s elapsed)
  MUT   time  734.59s  (781.93s elapsed)
  GC    time   15.90s  ( 16.73s elapsed)
  EXIT  time    0.00s  (  0.00s elapsed)
  Total time  750.49s  (798.66s elapsed)

  %GC time       2.1%  (2.1% elapsed)

  Alloc rate    85,682,629 bytes per MUT second

  Productivity  97.9% of total user, 92.0% of total elapsed

Without -HxM, -AxM:

  INIT  time    0.00s  (  0.00s elapsed)
  MUT   time  597.47s  (915.94s elapsed)
  GC    time  912.65s  (1363.63s elapsed)
  EXIT  time    0.00s  (  0.00s elapsed)
  Total time  1510.12s  (2279.57s elapsed)

My version using EnumSet (with the faster 'size'):

sudokus +RTS -sstderr > Solutions
sudokus +RTS -sstderr
82,190,535,600 bytes allocated in the heap
771,054,072 bytes copied during GC
    153,512 bytes maximum residency (394 sample(s))

     286104 collections in generation 0 ( 33.98s)
        394 collections in generation 1 (  0.35s)

          2 Mb total memory in use

  INIT  time    0.00s  (  0.00s elapsed)
  MUT   time  482.51s  (1105.12s elapsed)
  GC    time   34.33s  ( 79.90s elapsed)
  EXIT  time    0.00s  (  0.00s elapsed)
  Total time  516.84s  (1185.02s elapsed)

  %GC time       6.6%  (6.7% elapsed)

  Alloc rate    170,339,548 bytes per MUT second

  Productivity  93.4% of total user, 40.7% of total elapsed

Nice that original Haskell code can beat a translation from C.

However:
setSud ../puzzle3992 +RTS -sstderr
628|743|159
395|261|478
174|589|632
---+---+---
832|195|764
746|328|591
951|674|283
---+---+---
213|956|847
469|817|325
587|432|916
===========
888,672,920 bytes allocated in the heap
  3,352,784 bytes copied during GC
     45,648 bytes maximum residency (1 sample(s))

       3287 collections in generation 0 (  0.21s)
          1 collections in generation 1 (  0.00s)

          2 Mb total memory in use

  INIT  time    0.00s  (  0.00s elapsed)
  MUT   time    4.77s  (  4.77s elapsed)
  GC    time    0.21s  (  0.22s elapsed)
  EXIT  time    0.00s  (  0.00s elapsed)
  Total time    4.98s  (  4.99s elapsed)

  %GC time       4.2%  (4.4% elapsed)

  Alloc rate    186,304,595 bytes per MUT second

  Productivity  95.8% of total user, 95.6% of total elapsed

But
ckSud +RTS -sstderr < oneBad
ckSud +RTS -sstderr
(1,"673941852148256379295378461534167928826594713917832546351729684762483195489615237")
(2,"683941752179258463245376918534167829826594371917832546351729684762483195498615237")
(3,"829143657361785492547629381678954213934271568215836974152468739486397125793512846")
(4,"713642958825917436649835127594781362378264519261593784136478295482359671957126843")
(5,"763942158425817936189635427594781362378264519216593784631478295842359671957126843")
(6,"269743158371865924458921637945137286836492571712658349597386412683214795124579863")
(7,"269743158371865924485921637943157286856492371712638549597386412638214795124579863")
(8,"628743159395261478174589632832195764746328591951674283213956847469817325587432916")
(9,"983541762761328945524679813679483251835162497142957638457816329296735184318294576")
(10,"578942361923165748614837925867491532235786194149253876796514283452378619381629457")
(11,"938145762127396854654872931873629145546713289291584673415967328369258417782431596")
(12,"792548361531672894846931572657384129483129657219756438965817243174263985328495716")
(13,"738249561296517483154386927673192854981654372425873619547928136319765248862431795")
(14,"957842361386719452124653879598364127673281945412975638845137296231596784769428513")
(15,"598241367673958124421736985254873691317692548986415732742169853165384279839527416")
 25,708,036 bytes allocated in the heap
  9,097,220 bytes copied during GC
    329,648 bytes maximum residency (5 sample(s))

         97 collections in generation 0 (  0.42s)
          5 collections in generation 1 (  0.04s)

          2 Mb total memory in use

  INIT  time    0.00s  (  0.00s elapsed)
  MUT   time    0.23s  (  0.23s elapsed)
  GC    time    0.46s  (  0.46s elapsed)
  EXIT  time    0.00s  (  0.00s elapsed)
  Total time    0.69s  (  0.69s elapsed)

  %GC time      66.7%  (66.7% elapsed)

  Alloc rate    111,774,069 bytes per MUT second

  Productivity  33.3% of total user, 33.3% of total elapsed

The infamous puzzle 3992 is the eighth in oneBad, so the links dance rings 
around me for that.
I wonder where the dancing links run into difficulties.
I'll see whether I can grok (that does mean understand, doesn't it?) your 
programme one of these days.

>
> For those who will say "It is ugly, imperative, and ugly!" please remember
> this is a conversion of Knuth's c-code, which depended on five non-trivial
> goto jumps because he did not have tail recursion.  And the whole point of
> the algorithm are the imperative unlink & relink routines acting on a
> sparse binary matrix.
>
> This does not use any clever logic, but it does pick the tightest
> constraint at every step.  This means if there is only one obvious
> possibility for a position/row/column/block then it will immediately act on
> it.
>
> The literate source file is attached.
>
> [ My clever logic solver may eventually be cleaned up as well. ]

I really would like to see that.

Cheers, 
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