Advertisement
bsddeamon

Backup

Dec 30th, 2016
161
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scheme 14.47 KB | None | 0 0
  1. (define-library (sudoku printing)
  2.   (import (scheme base)
  3.     (only (scheme write) display)
  4.     (only (srfi 1) count))
  5.   (export print display-stat print-sudoku)
  6.   (begin (define (print str) (display str) (newline))
  7.     (define (display-stat str n)
  8.       (display
  9.         (string-append str ": " (number->string n) ".\n")))
  10.     (define delim
  11.       (list->string
  12.         (cons #\newline (make-list #\_ 19))))
  13.     (define (print-sudoku grid)
  14.       (display
  15.         (string-append delim
  16.           (let f ([i 0] [str ""])
  17.             (unless (> i 80)
  18.               (f (+ i 1)
  19.                 (string-append str
  20.                   (when (= (modulo i 9) 0) "|")
  21.                   (number->string
  22.                     (vector-ref grid i))
  23.                   "|"
  24.                   (when (= (modulo i 9) 8)
  25.                     delim)))))
  26.           "\n"))
  27.       (display-stat "Number of clues"
  28.         (count (lambda (x) (> x 0))
  29.           (vector-list grid))))))
  30.  
  31. (define-library (sudoku grid)
  32.   (import (scheme base)
  33.     (only (srfi 1) break concatenate iota lset= take zip)
  34.     (only (srfi 27) default-random-source
  35.       random-source-randomize!)
  36.     (only (gauche sequence) permute shuffle shuffle!)
  37.     (only (util combinations) permutations)
  38.     (only (util list) slices)
  39.     (sudoku printing))
  40.   (export solution)
  41.  
  42.   (begin (random-source-randomize! default-random-source)
  43.     (define-syntax receive
  44.       (syntax-rules ()
  45.         [(_ formals expr body ...)
  46.          (call-with-values (lambda () expr)
  47.            (lambda formals body ...))]))
  48.  
  49.     (define (compose f . g)
  50.       (if (null? g) f
  51.           (let ([g (apply compose g)])
  52.             (lambda (x) (f (g x))))))
  53.  
  54.     (define (split3 ls) (slices ls 3))
  55.  
  56.     (define (transpose ls) (apply zip ls))
  57.  
  58.     (define (cube->rows ls)
  59.       (map concatenate (concatenate ls)))
  60.  
  61.     (define (cube->blocks ls) (map transpose (split3 ls)))
  62.  
  63.     (define (triplets f ls)
  64.       (map f (transpose (map split3 ls))))
  65.  
  66.     (define (rotations ls)
  67.       (let ([n (length ls)])
  68.         (do ([i 0 (+ i 1)]
  69.                [ls (append ls ls) (cdr ls)]
  70.                [y (list) (cons (take ls n) y)])
  71.               ((= i n) (reverse y)))))
  72.  
  73.     (define all-3*3-latin-squares
  74.       (shuffle
  75.         (cube->rows
  76.           (map (compose permutations rotations)
  77.             (list (list 0 1 2) (list 0 2 1))))))
  78.  
  79.    (define (randomize-third ls)
  80.      (let f ([ls ls] [xs (shuffle ls)] [y (list)])
  81.        (if (null? ls) (reverse y)
  82.            (receive (a b)
  83.              (break
  84.                (let ([x (car ls)])
  85.                  (lambda (y) (lset= = x y)))
  86.                xs)
  87.              (f (cdr ls) (append a (cdr b))
  88.                (cons (car b) y))))))
  89.  
  90.     (define (randomize-vertically grid)
  91.       (concatenate
  92.         (triplets transpose
  93.           (map randomize-third
  94.             (triplets concatenate (cube->blocks grid))))))
  95.  
  96.    (define (randomize-triplets grid)
  97.      (concatenate
  98.        (concatenate
  99.          (randomize-vertically
  100.            (transpose
  101.              (map concatenate
  102.                (randomize-vertically grid)))))))
  103.  
  104.     (define (swap-occurences grid)
  105.       (map (let ([indexes
  106.                   (list->vector (shuffle (iota 9 1)))])
  107.              (lambda (x) (vector-ref indexes (- x 1))))
  108.         grid))
  109.  
  110.     (define solution
  111.       (list->vector
  112.         (swap-occurences
  113.           (randomize-triplets
  114.             (permute
  115.               (cube->rows
  116.                 (cube->blocks
  117.                   (map
  118.                     (lambda (xs i)
  119.                       (split3
  120.                         (map (lambda (x) (+ x (* i 3) 1))
  121.                           xs)))
  122.                     (cdr all-3*3-latin-squares)
  123.                     (car all-3*3-latin-squares))))
  124.               (list 0 3 6 1 4 7 2 5 8))))))))
  125.  
  126. (define-library (sudoku solver)
  127.   (import (scheme base)) (export solve)
  128.   (begin (define (incr! n) (set! n (+ n 1)))
  129.  
  130.     (define (push! x stack) (set! stack (cons x stack)))
  131.  
  132.     (define (pop! y stack)
  133.       (set! y (car stack))
  134.       (set! stack (cdr stack)))
  135.  
  136.     (define (vector->possibilities v)
  137.       (let f ([i 0] [j 0] [ls (vector->list v)] [y (list)])
  138.         (cond [(> j 8) (f (+ i 1) 0 ls y)]
  139.           [(> i 8) (reverse y)]
  140.           [else
  141.            (let ([k (car ls)])
  142.              (if (> k 0)
  143.                  (f i (+ j 1) (cdr ls)
  144.                    (cons (list i j (- k 1)) y))
  145.                  (let g ([k 0] [y y])
  146.                    (if (> k 8)
  147.                        (f i (+ j 1) (cdr ls) y)
  148.                        (g (+ k 1)
  149.                          (cons (list i j k) y))))))])))
  150.  
  151.     (define-record-type <node>
  152.       (node h l u i j k r d s) #f
  153.       (h header set-header!) (l left set-left!)
  154.       (u up set-up!) (i ival) (j jval) (k kval)
  155.       (r right set-right!) (d down set-down!)
  156.       (s size set-size!))
  157.  
  158.     (define (update-size! update constraint)
  159.       (let ([constraint (header constraint)])
  160.         (set-size! constraint
  161.           (update (size constraint) 1))))
  162.  
  163.     (define (horizontal-restore! entry)
  164.       (set-right! (left entry) entry)
  165.       (set-left! (right entry) entry))
  166.  
  167.     (define (vertical-restore! entry)
  168.       (update-size! + entry)
  169.       (set-down! (up entry) entry)
  170.       (set-up! (down entry) entry))
  171.  
  172.     (define (horizontal-delete! entry)
  173.       (set-right! (left entry) (right entry))
  174.       (set-left! (right entry) (left entry)))
  175.  
  176.     (define (vertical-delete! entry)
  177.       (set-down! (up entry) (down entry))
  178.       (set-up! (down entry) (up entry))
  179.       (update-size! - entry))
  180.  
  181.     (define (make-headers)
  182.       (let ([root (node #f #f #f #f #f #f #f #f #f)])
  183.         (set-left! root root)
  184.         (set-right! root root)
  185.         (do ([i 0 (+ i 1)]) ((> i 3))
  186.           (do ([j 0 (+ j 1)]) ((> j 8))
  187.             (do ([k 0 (+ k 1)]) ((> k 8))
  188.               (let ([constraint
  189.                      (node #f (left root)
  190.                        #f i j k root #f 0)])
  191.                 (set-header! constraint constraint)
  192.                 (set-up! constraint constraint)
  193.                 (set-down! constraint constraint)
  194.                 (horizontal-restore! constraint)))))
  195.         root))
  196.  
  197.     (define (make-row! sudoku possibility)
  198.       (apply
  199.         (lambda (row column value)
  200.           (let ([rule 0] [rules (make-vector 4 #f)]
  201.                  [constraints
  202.                   (vector
  203.                     (lambda (i j)
  204.                       (and (= i row) (= j column)))
  205.                     (lambda (i j)
  206.                       (and (= i row) (= j value)))
  207.                     (lambda (i j)
  208.                       (and (= i column) (= j value)))
  209.                     (lambda (i j)
  210.                       (and (= j value)
  211.                         (= i (+ (* (floor-quotient row 3)
  212.                                    3)
  213.                                 (floor-quotient
  214.                                   column 3))))))])
  215.             (do ([constraint (right sudoku)
  216.                     (right constraint)])
  217.                   ((vector-ref rules 3)
  218.                    (vector->list rules))
  219.               (and (= (ival constraint) rule)
  220.                 ((vector-ref constraints rule)
  221.                    (jval constraint) (kval constraint))
  222.                 (vector-set! rules rule
  223.                   (let ([hint
  224.                           (node constraint #f
  225.                             (up constraint) row
  226.                             column value #f
  227.                             constraint #f)])
  228.                     (vertical-restore! hint)
  229.                     hint))
  230.                 (incr! rule)))))
  231.         possibility))
  232.  
  233.     (define (make-grid ls)
  234.       (let ([grid (make-headers)])
  235.         (for-each
  236.           (lambda (possibilities)
  237.             (apply
  238.               (lambda (row-column row-value column-value
  239.                         block-value)
  240.                 (set-left! row-column block-column)
  241.                 (set-right! row-column row-value)
  242.                 (set-left! row-value row-column)
  243.                 (set-right! row-value column-value)
  244.                 (set-left! column-value row-value)
  245.                 (set-right! column-value block-value)
  246.                 (set-left! block-value column-value)
  247.                 (set-right! block-value row-column))
  248.               (make-row! grid possibilities)))
  249.           (vector->possibilities ls))
  250.         grid))
  251.  
  252.     (define (grid-for-each direction root f)
  253.       (do ([x (direction root) (direction x)])
  254.             ((eq? x root)) (f x)))
  255.  
  256.     (define (vertical-cover! constraint)
  257.       (let ([constraint (header constraint)])
  258.         (grid-for-each down constraint
  259.           (lambda (possibility)
  260.             (grid-for-each right possibility
  261.               vertical-delete!)))
  262.         (horizontal-delete! constraint)))
  263.  
  264.     (define (vertical-uncover! constraint)
  265.       (let ([constraint (header constraint)])
  266.         (grid-for-each up constraint
  267.           (lambda (possibility)
  268.             (grid-for-each right possibility
  269.               vertical-restore!)))
  270.         (horizontal-restore! constraint)))
  271.  
  272.     (define (horizontal-cover! possibility)
  273.       (grid-for-each right possibility vertical-cover!))
  274.  
  275.     (define (horizontal-uncover! possibility)
  276.       (grid-for-each left possibility vertical-uncover!))
  277.  
  278.     (define (optimal-branch sudoku)
  279.       (let compare ([constraint sudoku] [minimum 9]
  280.                     [ls (list)])
  281.         (if (eq? constraint sudoku) (list minimum ls)
  282.             (let ([n (size constraint)])
  283.               (cond
  284.                 [(< minimum n)
  285.                  (compare (right constraint) minimum ls)]
  286.                 [(= n minimum)
  287.                  (compare (right constraint) minimum
  288.                    (cons constraint ls))]
  289.                 [else (compare (right constraint)
  290.                         n (list constraint))])))))
  291.  
  292.     (define (try! constraint clues search! cycles guesses
  293.               undo?)
  294.       (vertical-cover! constraint)
  295.       (grid-for-each down constraint
  296.         (lambda (possibility)
  297.           (push! possibility clues)
  298.           (horizontal-cover! possibility)
  299.           (when undo?
  300.             (search! cycles (+ guesses 1))
  301.             (pop! possibility clues)
  302.             (set! constraint (header possibility))
  303.             (horizontal-uncover! possibility)))
  304.       (when undo? (vertical-uncover! constraint)))
  305.  
  306.     (define (solve sudoku max-solutions)
  307.       (let ([clues (list)] [solutions 0]
  308.             [guesses 0] [cycles 0])
  309.         (call-with-current-continuation
  310.           (lambda (return)
  311.             (let search! ([c 0] [g 0])
  312.               (set! cycles c)
  313.               (set! guesses g)
  314.               (cond
  315.                 [(< max-solutions solutions)
  316.                  (return (list solutions guesses cycles))]
  317.                 [(eq? (right sudoku) sudoku)
  318.                  (incr! solutions)]
  319.                 [else
  320.                  (let ([constraint
  321.                         (optimal-branch sudoku)])
  322.                    (cond
  323.                      [(= (car constraint) 1)
  324.                       (for-each
  325.                         (lambda (hint)
  326.                           (try! hint clues search! c g #f))
  327.                         (cdr constraint))
  328.                       (search! (+ c 1) g)]
  329.                      [else (try! (car (cdr constraint))
  330.                              clues search! c g #t)]))]))
  331.             (return (list solutions guesses cycles))))))))
  332.  
  333. (define-library (sudoku generator)
  334.   (import (scheme base) (srfi 1)
  335.     (only (srfi 27) default-random-source
  336.       random-source-randomize!)
  337.     (only (gauche sequence) shuffle)
  338.     (sudoku solver) (sudoku printing) (sudoku grid))
  339.   (export get-args display-greetings rate-sudoku
  340.     initial-prune! remove-useless! add-useful!)
  341.   (begin (define sudoku)
  342.  
  343.     (random-source-randomize!default-random-source)
  344.  
  345.     (define (get-args args)
  346.       (if (< (length args) 3) (initial-prune! 23 800)
  347.           (apply initial-prune! (cdr args))))
  348.  
  349.     (define (display-greetings)
  350.       (display
  351.         (string-append
  352.           "SamDoku-Generator.ss\n\n"
  353.           "This program is 3-clause BSD-licensed!\n\n"
  354.           "Author: Samuel Duclos\n"
  355.           "\tJanuary 2017\n\n"
  356.           "No warranties, no responsibilities!\n\n")))
  357.  
  358.     (define (rate-sudoku)
  359.       (let ([rating (cdr (solve sudoku 1))])
  360.         (display-stat "Guesses" (car rating))
  361.         (display-stat "Cycles" (cadr rating))))
  362.  
  363.     (define (initial-prune! initial-clues max-solutions)
  364.       (print "Solution:")
  365.       (print-sudoku solution)
  366.       (display-stat "Maximum solutions per try"
  367.         max-solutions)
  368.       (print "Randomly pruning...")
  369.       (let ([v (make-vector 81 0)])
  370.         (for-each
  371.           (lambda (i)
  372.             (vector-set! v i (vector-ref solution i)))
  373.           (take (shuffle (iota 81)) initial-clues))
  374.         (let ([n (car (solve v max-solutions))])
  375.           (cond [(< n max-solutions)
  376.                  (print-sudoku v)
  377.                  (display-stat "Solutions" n)
  378.                  (set! sudoku v)]
  379.             [else (initial-prune initial-clues
  380.                     max-solutions)]))))
  381.  
  382.     (define (make-updater eq update)
  383.       (lambda (grid)
  384.         (filter-map
  385.           (lambda (i)
  386.             (and (eq (vector-ref grid i) 0)
  387.               (let ([g (vector-copy grid)])
  388.                 (vector-set! g i (update i))))
  389.                 g)))
  390.           (iota 81))))
  391.  
  392.     (define prunes (make-updater > (lambda (i) 0)))
  393.  
  394.     (define adds
  395.       (make-updater =
  396.         (lambda (i) (vector-ref solution i))))
  397.  
  398.     (define (unique-solutions grids)
  399.       (filter (lambda (x) (= (car (solve x 1)) 1)) grids))
  400.  
  401.     (define (not-useless grids)
  402.       (filter (lambda (x) (> (car (solve x 1)) 0)) grids))
  403.  
  404.     (define (add-useful!)
  405.       (print "Adding clues until only one solution remains…")
  406.       (let f ([grids (list sudoku)])
  407.         (let ([ls (unique-solutions grids)])
  408.           (if (null? ls) (f (concatenate (map adds grids)))
  409.               (set! sudoku ls))))
  410.       (display-stat "Possible solution(s) to optimize"
  411.         (length sudoku))
  412.       (print-sudoku (car sudoku)))
  413.  
  414.     (define (remove-useless!)
  415.       (print "Removing useless clues…")
  416.       (let f ([grids sudoku])
  417.         (let ([ls (not-useless grids)])
  418.           (if (null? ls)
  419.               (set! sudoku (car (unique-solutions grids)))
  420.               (f (concatenate (map prunes ls))))))
  421.       (print-sudoku sudoku))))
  422.  
  423. (import (scheme base) (sudoku generator))
  424. (display-greetings)
  425. (get-args (command-line))
  426. (add-useful!)
  427. (remove-useless!)
  428. (rate-sudoku)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement