ナンプレを解く(改

ナンプレを解くプログラムがバグっていて解けない問題があったので直しました。
このプログラムは人間的な解法で問題を解きます。総当りな方法は使いません。

(use util.list)
(define nil '())

;;; 汎用手続き

(define (list->number lis)
  (fold (lambda (a b) (+ a (* b 10))) 0 lis))

(define (digit->integer c)
  (- (char->integer c) (char->integer #\0)))

(define (number->list num)
  (map digit->integer (string->list (number->string num))))

(define (enumerate-interval low high)
  (if (> low high)
      nil
      (cons low (enumerate-interval (+ low 1) high))))

(define (filter pred items)
  (cond ((null? items) nil)
        ((pred (car items))
         (cons (car items)
               (filter pred (cdr items))))
        (else
         (filter pred (cdr items)))))

(define (remove item seq)
  (filter (lambda (x) (not (equal? x item))) seq))

(define (element-of-set? x set)
  (cond ((null? set) #f)
        ((equal? x (car set)) #t)
        (else (element-of-set? x (cdr set)))))

(define (uniq set)
  (define (iter x s)
    (if (null? x)
        s
        (iter (cdr x)
              (if (element-of-set? (car x) s)
                  s
                  (cons (car x) s)))))
  (iter set nil))

(define (subsets s)
  (if (null? s)
      (list '())
      (let ((rest (subsets (cdr s))))
        (append rest (map (lambda (x) (cons (car s) x)) rest)))))

;;; デバッグ出力の手続き

(define *debugging* #f)

(define (debug-on)
  (print "Debug mode is on.")
  (set! *debugging* #t))

(define (debug-off)
  (print "Debug mode is off.")
  (set! *debugging* #f))

(define (debug-print msg1 . msg2)
  (define (iter msg)
    (if (null? msg)
        (newline)
        (begin
          (display (car msg))
          (iter (cdr msg)))))
  (and *debugging* (display msg1) (iter msg2)))

;;; グリッドの作成(読み込み) & グリッド-ハッシュテーブル変換をする手続き

(define (make-grids filename)
  (define ip (open-input-file filename))
  (define (read-line ip)
    (define (iter lis)
      (let ((c (read-char ip)))
        (cond ((eof-object? c) lis)
              ((eq? c #\cr) (read-char ip) lis)
              (else
               (iter (append lis (list (digit->integer c))))))))
    (iter nil))
  (define (read-grids)
    (define (iter lis c)
      (if (= c 0)
          (list lis)
          (let ((line (read-line ip)))
            (if (null? line)
                (begin
                  (close-input-port ip)
                  nil)
                (iter (append lis (list line)) (- c 1))))))
    (read-line ip)
    (iter nil 9))
  (define (iter lis)
    (if (port-closed? ip)
        lis
        (iter (append lis (read-grids)))))
  (iter nil))

(define (grid->hash grid)
  (define ht (make-hash-table 'equal?))
  (define (list->hash lis y)
    (define (iter l x)
      (if (null? l)
          'done
          (begin
            (if (> (car l) 0)
                (confirm ht (list x y) (car l))
                (hash-table-put! ht (list x y) (car l)))
            (iter (cdr l) (+ x 1)))))
    (iter lis 1))
  (define (init-hash lis y)
    (if (null? lis)
        ht
        (begin
          (list->hash (car lis) y)
          (init-hash (cdr lis) (+ y 1)))))
  (init-hash grid 1))

(define (hash->grid ht)
  (let ((nums (enumerate-interval 1 9)))
    (map (lambda (y)
           (map (lambda (x) (hash-table-get ht `(,x ,y)))
                nums))
         nums)))

(define (print-grid grids)
  (begin
    (map print grids)
    'done))

(define (grid->excel grids)
  (define (lst->csv lst)
    (and (not (null? lst))
         (display ",")
         (display (car lst))
         (lst->csv (cdr lst))))
  
  (define (output-proc lst)
    (if (null? lst)
        (newline)
        (begin
          (if (pair? (car lst))
              (begin
                (display (caar lst))
                (lst->csv (cdar lst)))
              (display (car lst)))
          (display "\t")
          (output-proc (cdr lst)))))
  
  (begin
    (map output-proc grids)
    'done))

;;; ナンバープレイス

;; グリッドの初期化。
;; グリッドの値が 0 の箇所は init-val を設定する。
(define (init-grid ht)
  (define init-val '(1 2 3 4 5 6 7 8 9))
  (define (init-proc key val)
    (if (= val 0)
        (hash-table-put! ht key init-val)
        val))

  (hash-table-map ht init-proc)
  ht)

;; key が属するミニグリッド(9x9 マス)のキーリストを生成する
(define (gen-keys-grd key)
  (define (get-keys n)
    (cond ((< n 4) '(1 2 3))
          ((< n 7) '(4 5 6))
          (else '(7 8 9))))
  (let ((xs (get-keys (car key)))
        (ys (get-keys (cadr key))))
    (define (iter x lis)
      (if (null? x)
          lis
          (iter (cdr x) (append lis (map (lambda (y) (list (car x) y)) ys)))))
    (iter xs nil)))

;; key が属する同じ行のキーリストを生成する
(define (gen-keys-row key)
  (define keys (enumerate-interval 1 9))
  (filter (lambda (k) (not (equal? k key)))
          (map (lambda (x) (list x (cadr key))) keys)))

;; key が属する同じ列のキーリストを生成する
(define (gen-keys-col key)
  (define keys (enumerate-interval 1 9))
  (filter (lambda (k) (not (equal? k key)))
          (map (lambda (y) (list (car key) y)) keys)))

;; key が属する同じ行と列のキーリストを生成する
(define (gen-keys-row-and-col key)
  (define keys (enumerate-interval 1 9))
  (append (map (lambda (x) (list x (cadr key))) keys)
          (map (lambda (y) (list (car key) y)) keys)))

;; append-keys1 と append-keys2 を append したキーリストから remove-keys を取り除く。
(define (append-and-remove-keys append-keys1 append-keys2 remove-keys)
  (define (iter keys rm-keys)
    (if (null? rm-keys)
        keys
        (iter (filter (lambda (k) (not (equal? k (car rm-keys)))) keys)
              (cdr rm-keys))))
  (iter (append append-keys1 append-keys2) remove-keys))

;; ハッシュテーブル ht の keys を val で更新する。
(define (update-vals ht keys val)
  (define (iter k)
    (if (null? k)
        'done
        (let ((v (hash-table-get ht (car k))))
          (if (pair? v)
              (let ((new-v (filter (lambda (x) (not (= x val))) v)))
                (if (null? new-v) (hash->grid ht))
                (if (null? (cdr new-v))
                    (begin
                      (confirm ht (car k) (car new-v))
                      (update-vals ht
                                   (append-and-remove-keys (gen-keys-grd (car k)) (gen-keys-row-and-col (car k)) (list (car k)))
                                   (car new-v)))
                    (set-tentative ht (car k) new-v))))
          (iter (cdr k)))))
  (iter keys))

;; 更新フラグ
(define *update-flag* #f)

(define (clear-update-flag)
  (set! *update-flag* #f))

(define (set-update-flag)
  (set! *update-flag* #t))

(define (update?)
  *update-flag*)

;; val の値によって確定もしくは暫定設定を呼ぶ
(define (update-val ht key val)
  (if (pair? val)
      (set-tentative ht key val)
      (confirm ht key val)))

;; 確定手続き
(define (confirm ht key val)
  (debug-print ";;確定 key=" key " val=" val)
  (set-update-flag)
  (hash-table-put! ht key val))

;; 暫定設定手続き
(define (set-tentative ht key val)
  (let ((prev-val (hash-table-get ht key val)))
    (if (not (equal? prev-val val))
        (begin
          (debug-print ";;暫定設定 key=" key " val=" val)
          (set-update-flag)
          (hash-table-put! ht key val)))))

(define (bins->num bin-lis)
  (define (iter lis k num)
    (if (null? lis)
        num
        (iter (cdr lis) (* k 2) (+ num (* k (car lis))))))
  (iter (reverse bin-lis) 1 0))

(define (num->bins num k)
  (define (iter n)
    (if (= n 0)
      nil
      (append (iter (quotient n 2)) (list (remainder n 2)))))
  (let ((bins (iter num)))
    (append (make-list (- k (length bins)) 0) bins)))

(define (overlap-num lis)
  (if (null? (cdr lis))
      #f
      (if (= (car lis) (cadr lis))
          (car lis)
          (overlap-num (cdr lis)))))

(define (find-val num lis)
  (define (iter l i vals)
    (if (null? l)
        vals
        (iter (cdr l) (+ i 1) (if (= (car l) num) (append vals `(,i)) vals))))
  (iter lis 1 nil))

(define (find-vals lis lists)
  (define (iter l i vals)
    (if (null? l)
        vals
        (iter (cdr l) (+ i 1)
              (if (and (memq (car lis) (car l))
                       (memq (cadr lis) (car l)))
                  (append vals `(,i))
                  vals))))
  (iter lists 1 nil))

(define (find-lis lis lists)
  (define (iter l i vals)
    (if (null? l)
        vals
        (iter (cdr l)
              (+ i 1)
              (if (equal? (car l) lis)
                  (append vals `(,i))
                  vals))))
  (iter lists 1 nil))

(define (transpose grid)
  (define (iter lis new-lis)
    (if (null? (car lis))
        new-lis
        (iter (map cdr lis) (append new-lis (list (map car lis))))))
  (iter grid nil))

(define (check-grid grid)
  (map (lambda (l) (equal? l '(1 2 3 4 5 6 7 8 9))) (map sort grid)))

;;; ナンバープレイスを解く手続き群

;; 解法レベル1
;; 確定マスのある行列マスおよびミニグリッド(9x9マス)には、
;; 確定マスと同じ値にはならないため候補値から取り除く。
(define (solve-level-1 ht)
  (define (proc key val)
    (if (not (pair? val))
        (update-vals ht
                     (append-and-remove-keys (gen-keys-grd key) (gen-keys-row-and-col key) (list key))
                     val)
        val))
  
  (clear-update-flag)
  (debug-print "=== level 1 ===")  
  (hash-table-map ht proc)
  (update?))

;; 解法レベル2
;; 行、列、ミニグリッドで候補値に 1 つしか表われない値を確定する。
;; (行、列、ミニグリッドで別々に 3 回処理する)
(define (solve-level-2 ht)
  (define (uniq-val target-vals vals)
    (if (null? vals)
        target-vals
        (uniq-val (remove (car vals) target-vals) (cdr vals))))

  (define (proc key val)
    (if (pair? val)
        (let* ((row-vals (uniq (fold append nil (map (lambda (k) (let ((v (hash-table-get ht k))) (if (pair? v) v `(,v))))
                                                     (append-and-remove-keys (gen-keys-row key) nil (list key))))))
               (col-vals (uniq (fold append nil (map (lambda (k) (let ((v (hash-table-get ht k))) (if (pair? v) v `(,v))))
                                                     (append-and-remove-keys (gen-keys-col key) nil (list key))))))
               (grd-vals (uniq (fold append nil (map (lambda (k) (let ((v (hash-table-get ht k))) (if (pair? v) v `(,v))))
                                                     (append-and-remove-keys (gen-keys-grd key) nil (list key))))))
               (draft-val-1 (uniq-val val row-vals))
               (draft-val-2 (uniq-val val col-vals))
               (draft-val-3 (uniq-val val grd-vals)))
          (cond ((= (length draft-val-1) 1) (confirm ht key (car draft-val-1)))
                ((= (length draft-val-2) 1) (confirm ht key (car draft-val-2)))
                ((= (length draft-val-3) 1) (confirm ht key (car draft-val-3)))
                (else 'nop)))))

  (clear-update-flag)
  (debug-print "=== level 2 ===")  
  (hash-table-map ht proc)
  (update?))

;; 解法レベル3
;; 行、列、ミニグリッドで候補値に 1 つしか表われない値を確定する。
;; (行、列、ミニグリッドをまとめて 1 回処理する)
#;(define (solve-level-3 ht)
  (define (uniq-val target-vals vals)
    (if (null? vals)
        target-vals
        (uniq-val (remove (car vals) target-vals) (cdr vals))))

  (define (proc key val)
    (if (pair? val)
        (let* ((vals (uniq (fold append nil (map (lambda (k) (let ((v (hash-table-get ht k))) (if (pair? v) v `(,v))))
                                                 (append-and-remove-keys (gen-keys-grd key) (gen-keys-row-and-col key) (list key))))))
               (draft-val (uniq-val val vals)))
          (if (= (length draft-val) 1)
              (confirm ht key (car draft-val))))))

  (clear-update-flag)
  (debug-print "=== level 3 ===")
  (hash-table-map ht proc)
  (update?))

;; 解法レベル4 シンプルチェーン
(define (solve-level-4 ht)
  (define (find-sc ht grid-keys)
    (define (sc keys)
      (define (one? lis) (null? (cdr lis)))
      (let ((x (uniq (map car keys)))
            (y (uniq (map cadr keys))))
        (cond ((null? keys) '(0 0))
              ((one? x) (list (car x) 0))
              ((one? y) (list 0 (car y)))
              (else '(0 0)))))
  
    (define (key-iter num keys results)
      (if (null? keys)
          results
          (let ((val (hash-table-get ht (car keys))))
            (if (pair? val)
                (let ((v (filter (lambda (v) (= v num)) val)))
                  (key-iter num
                            (cdr keys)
                            (if (null? v)
                                results
                                (cons (car keys) results))))
                (key-iter num (cdr keys) results)))))

    (define (num-iter nums)
      (if (null? nums)
          'done
          (let ((key (sc (key-iter (car nums) grid-keys nil))))
            (if (not (null? key))
                (let ((val (car nums)))
                  (and (not (= 0 (cadr key))) (update-vals ht (append-and-remove-keys (gen-keys-row key) nil grid-keys) val))
                  (and (not (= 0 (car key))) (update-vals ht (append-and-remove-keys (gen-keys-col key) nil grid-keys) val))
                  (num-iter (cdr nums)))))))
    
    (num-iter (enumerate-interval 1 9)))

  (define (iter keys)
    (if (null? keys)
        ht
        (begin
          (find-sc ht (gen-keys-grd (car keys)))
          (iter (cdr keys)))))

  (clear-update-flag)
  (debug-print "=== level 4 ===")  
  (iter '((1 1) (4 1) (7 1) (1 4) (4 4) (7 4) (1 7) (4 7) (7 7)))
  (update?))

;; 解法レベル5 2国同盟。4国同盟以上は未対応。
;; 行、列、ミニグリッド内に同盟がある場合、同盟以外から候補値を削る。
;; 例)
;; (1 2) (1 2) ... (2 5 9) (1 3 4 5) (1 2 7 8 9)
;; (1 2) と (1 2) は 2 国同盟が成立。
;; 行、列およびミニグリッドにある、(1 2) 以外のマスに 1 および 2 が入る事は無い。
;; したがって
;; (1 2) (1 2) ... (5 9) (3 4 5) (7 8 9)
;; のように除外できる。
(define (solve-level-5 ht)
  ;; val2 は val1 のサブセットか?
  ;; ただし val2 の要素数が 2 以上のものだけがチェック対象
  (define (subsets? val1 val2)
    (let ((subsets-val1 (filter (lambda (v) (>= (length v) 2)) (subsets val1))))
      (not (null? (filter (lambda (v) (equal? v val2)) subsets-val1)))))

  ;; val2 と val1 は互いにサブセットか
  (define (each-other-subsets? val1 val2)
    (and
     (= (length val1) (length val2))
     (subsets? (sort (uniq (append val1 val2))) val2)))
  
  ;; items から remove-items を削除する
  (define (removes remove-items items)
    (if (null? remove-items)
        items
        (removes (cdr remove-items) (remove (car remove-items) items))))
  
  ;; 同盟がある場合は、行、列もしくはグリッドから同盟の値を省く。
  (define (remove-keys keys val)
    (define (iter k)
      (if (null? k)
          'done
          (let ((v (hash-table-get ht (car k))))
            (if (pair? v)
                (let ((nv (removes val v)))
                  (update-val ht (car k) nv)))
            (iter (cdr k)))))
    (iter keys))

  (define (append-vals ht keys)
    (if (null? keys)
        nil
        (append (hash-table-get ht (car keys))
                (append-vals ht (cdr keys)))))
  
  ;; 同盟を探す。
  ;; 例)
  ;; ・2国同盟
  ;; (1 2) と同じ (1 2) が 1 つ(合計 2 つ) を見つけた場合。
  ;; サブセットの処理はしない。
  ;; ・3国同盟
  ;; (1 2 3) (1 2) (1 3) (2 3) はいずれも (1 2 3) のサブセットである。
  ;; サブセットのいずれか 2 つ(合計 3 つ)を見つけた場合は、3 国同盟と判断する。
  ;; また、サブセット同士で以下のように3国同盟になる場合もある。
  ;; (1 2) (1 3) (2 3)
  (define (find-alliance-2 ht key val)
    ;; フィルタ手続き
    (define (filter-proc k)
      (equal? val (hash-table-get ht k)))

    (let ((row-keys (filter filter-proc (append-and-remove-keys (gen-keys-row key) nil (list key))))
          (col-keys (filter filter-proc (append-and-remove-keys (gen-keys-col key) nil (list key))))
          (grd-keys (filter filter-proc (append-and-remove-keys (gen-keys-grd key) nil (list key)))))
      (and (not (null? row-keys)) (remove-keys (append-and-remove-keys (gen-keys-row key) nil (append (list key) row-keys)) val))
      (and (not (null? col-keys)) (remove-keys (append-and-remove-keys (gen-keys-col key) nil (append (list key) col-keys)) val))
      (and (not (null? grd-keys)) (remove-keys (append-and-remove-keys (gen-keys-grd key) nil (append (list key) grd-keys)) val))
      ))
  
  (define (find-alliance-3 ht key val)
    ;; フィルタ手続き
    (define (filter-proc k)
      (let ((k-val (hash-table-get ht k)))
        (and (pair? k-val)
             (or
              (subsets? val k-val)
              (each-other-subsets? val k-val)))))

    (let ((row-keys (filter filter-proc (append-and-remove-keys (gen-keys-row key) nil (list key))))
          (col-keys (filter filter-proc (append-and-remove-keys (gen-keys-col key) nil (list key))))
          (grd-keys (filter filter-proc (append-and-remove-keys (gen-keys-grd key) nil (list key)))))
      ;; 3国同盟の場合、
      ;; ・同盟として見付けた数が 2 箇所(key と合せて 3 箇所)
      ;; ・みつけた 3 箇所で使われている候補数が 3 つ
      ;; の場合に処理する。
      (and (not (null? row-keys))
           (= (length row-keys) 2)
           (= (length (uniq (append-vals ht (append row-keys (list key))))) 3)
           (remove-keys (append-and-remove-keys (gen-keys-row key) nil (append (list key) row-keys)) val))
      (and (not (null? col-keys))
           (= (length col-keys) 2)
           (= (length (uniq (append-vals ht (append col-keys (list key))))) 3)
           (remove-keys (append-and-remove-keys (gen-keys-col key) nil (append (list key) col-keys)) val))
      (and (not (null? grd-keys))
           (= (length grd-keys) 2)
           (= (length (uniq (append-vals ht (append grd-keys (list key))))) 3)
           (remove-keys (append-and-remove-keys (gen-keys-grd key) nil (append (list key) grd-keys)) val))
      ))

  (define (proc key val)
    (and (pair? val)
         (or
          ;; 3国同盟を先に処理する。
          (and (<= (length val) 3) (find-alliance-3 ht key val))
          (and (= (length val) 2) (find-alliance-2 ht key val)))))
        
  (clear-update-flag)
  (debug-print "=== level 5 ===")
  (hash-table-map ht proc)  
  (update?))

;; 解法レベル6 XYウイング
(define (solve-level-6 ht)
  (define (xy-wing lis)
    (let ((w (filter (lambda (l) (= 2 (apply + l))) lis)))
      (cond ((null? w) #f)
            ((null? (cdr w)) #f)
            (else
             (let ((bins (map bins->num w)))
               (let ((sb (sort bins)))
                 (let ((usb (sort (uniq sb))))
                   (if (= (abs (- (length sb) (length usb))) 1)
                       (num->bins (overlap-num sb) 9)
                       #f
                       ))))))))
  (define (xy-wing-upd-vals ht n r c)
    (let ((k1 (list (car c) (car r)))
          (k2 (list (cadr c) (cadr r))))
      (let ((rk (list k1 k2 (list (car k2) (cadr k1)) (list (car k1) (cadr k2)))))
        ;;(print "n=" n " r=" r " c=" c " k1=" k1 " k2=" k2 " rk=" rk)
        (update-vals ht (append-and-remove-keys (gen-keys-row k1) (gen-keys-col k1) rk) n)
        (update-vals ht (append-and-remove-keys (gen-keys-row k2) (gen-keys-col k2) rk) n)
        )))
  (define (find-xy-wing ht num keys)
    (define (iter vals results)
      (if (null? vals)
          results
          (if (pair? (car vals))
              (if (null? (filter (lambda (n) (= n num)) (car vals)))
                  (iter (cdr vals) (append results '(0)))
                  (iter (cdr vals) (append results '(1))))
              (iter (cdr vals) (append results '(0))))))
    (let ((vals (map (lambda (k) (hash-table-get ht k)) keys)))
      ;;(print "num=" num " keys=" keys " vals=" vals)
      (iter vals nil)))
  (define (r-iter n nums results)
    (if (null? nums)
        results
        (let ((rk (list 1 (car nums))))
          (r-iter n
                  (cdr nums)
                  (append results
                          (list (find-xy-wing ht n (cons rk (gen-keys-row rk)))))))))
  (define (c-iter n nums results)
    (if (null? nums)
        results
        (let ((ck (list (car nums) 1)))
          (c-iter n
                  (cdr nums)
                  (append results
                          (list (find-xy-wing ht n (cons ck (gen-keys-col ck)))))))))
  (define (iter nums)
    (if (null? nums)
        ht
        (begin
          (let ((r (r-iter (car nums) (enumerate-interval 1 9) nil)))
            (let ((rw (xy-wing r)))
              (and rw (xy-wing-upd-vals ht (car nums) (find-lis rw r) (find-val 1 rw)))))
          (let ((c (c-iter (car nums) (enumerate-interval 1 9) nil)))
            (let ((cw (xy-wing c)))
              (and cw (xy-wing-upd-vals ht (car nums) (find-val 1 cw) (find-lis cw c)))))
          (iter (cdr nums)))))

  (clear-update-flag)
  (debug-print "=== level 6 ===")
  (iter (enumerate-interval 1 9))
  (update?))

;; 仮置き法(未実装)
(define (solve-level-7 ht)
  (clear-update-flag)
  (debug-print "=== level 7 ===")
  ;; 仮置きしないと解けない問題は邪道らしいです。
  (update?))

;; 問題が解けたか?
(define (solve-end? ht)
  (let ((alis (hash-table->alist ht))
        (grid (hash->grid ht)))
    (and (null? (filter pair? (map cdr alis)))
         (equal? (list #t) (uniq (append (check-grid grid) (check-grid (transpose grid))))))))

;; メイン処理
;; ハッシュテーブルは、キーに(行,列)情報を、val に候補値もしくは確定値のいずれかの値を持つ。
;; 例) val=(1 2 3 6 7) ... val は現在未確定でありリスト内のいずれかの候補値に将来確定する事を表わす。
;;     val=5 ............. val は 5 で確定した事を表わす。
(define (solve-main ht c)
  (debug-print "ループ " c " 回目")
  (let ((result (or
                 (solve-level-1 ht)
                 (solve-level-2 ht)
                 ;;(solve-level-3 ht)
                 (solve-level-4 ht)
                 (solve-level-5 ht)
                 (solve-level-6 ht)
                 )))
    (if result
        (solve-main ht (+ c 1))
        (if (solve-end? ht)
            ht
            (begin
              (print "解けませんでした")
              ht)))))

(define (solve-test input-filename grid-no)
  (define grids (make-grids input-filename))
  (define ht (grid->hash (list-ref grids (- grid-no 1))))
  (debug-print "============")
  (solve-main (init-grid ht) 1))

完全に動作するコードを掲載するのがポリシーなので、全コードを掲載します。
Gauche をインストールして REPL(gosh) に丸ごと貼っ付けてください。

今回は過去に自分が書いたプログラムがイミフで大変だったので、
その反省を踏まえw、変数名や手続き名を見直しさらにコメントも書いてみましたw

同じフォルダに mondai.txt という名前で以下の内容のファイルを用意してください。
これはプロジェクトオイラーの問題96のナンプレ問題です。

Grid 01
003020600
900305001
001806400
008102900
700000008
006708200
002609500
800203009
005010300
Grid 02
200080300
060070084
030500209
000105408
000000000
402706000
301007040
720040060
004010003
Grid 03
000000907
000420180
000705026
100904000
050000040
000507009
920108000
034059000
507000000
Grid 04
030050040
008010500
460000012
070502080
000603000
040109030
250000098
001020600
080060020
Grid 05
020810740
700003100
090002805
009040087
400208003
160030200
302700060
005600008
076051090
Grid 06
100920000
524010000
000000070
050008102
000000000
402700090
060000000
000030945
000071006
Grid 07
043080250
600000000
000001094
900004070
000608000
010200003
820500000
000000005
034090710
Grid 08
480006902
002008001
900370060
840010200
003704100
001060049
020085007
700900600
609200018
Grid 09
000900002
050123400
030000160
908000000
070000090
000000205
091000050
007439020
400007000
Grid 10
001900003
900700160
030005007
050000009
004302600
200000070
600100030
042007006
500006800
Grid 11
000125400
008400000
420800000
030000095
060902010
510000060
000003049
000007200
001298000
Grid 12
062340750
100005600
570000040
000094800
400000006
005830000
030000091
006400007
059083260
Grid 13
300000000
005009000
200504000
020000700
160000058
704310600
000890100
000067080
000005437
Grid 14
630000000
000500008
005674000
000020000
003401020
000000345
000007004
080300902
947100080
Grid 15
000020040
008035000
000070602
031046970
200000000
000501203
049000730
000000010
800004000
Grid 16
361025900
080960010
400000057
008000471
000603000
259000800
740000005
020018060
005470329
Grid 17
050807020
600010090
702540006
070020301
504000908
103080070
900076205
060090003
080103040
Grid 18
080005000
000003457
000070809
060400903
007010500
408007020
901020000
842300000
000100080
Grid 19
003502900
000040000
106000305
900251008
070408030
800763001
308000104
000020000
005104800
Grid 20
000000000
009805100
051907420
290401065
000000000
140508093
026709580
005103600
000000000
Grid 21
020030090
000907000
900208005
004806500
607000208
003102900
800605007
000309000
030020050
Grid 22
005000006
070009020
000500107
804150000
000803000
000092805
907006000
030400010
200000600
Grid 23
040000050
001943600
009000300
600050002
103000506
800020007
005000200
002436700
030000040
Grid 24
004000000
000030002
390700080
400009001
209801307
600200008
010008053
900040000
000000800
Grid 25
360020089
000361000
000000000
803000602
400603007
607000108
000000000
000418000
970030014
Grid 26
500400060
009000800
640020000
000001008
208000501
700500000
000090084
003000600
060003002
Grid 27
007256400
400000005
010030060
000508000
008060200
000107000
030070090
200000004
006312700
Grid 28
000000000
079050180
800000007
007306800
450708096
003502700
700000005
016030420
000000000
Grid 29
030000080
009000500
007509200
700105008
020090030
900402001
004207100
002000800
070000090
Grid 30
200170603
050000100
000006079
000040700
000801000
009050000
310400000
005000060
906037002
Grid 31
000000080
800701040
040020030
374000900
000030000
005000321
010060050
050802006
080000000
Grid 32
000000085
000210009
960080100
500800016
000000000
890006007
009070052
300054000
480000000
Grid 33
608070502
050608070
002000300
500090006
040302050
800050003
005000200
010704090
409060701
Grid 34
050010040
107000602
000905000
208030501
040070020
901080406
000401000
304000709
020060010
Grid 35
053000790
009753400
100000002
090080010
000907000
080030070
500000003
007641200
061000940
Grid 36
006080300
049070250
000405000
600317004
007000800
100826009
000702000
075040190
003090600
Grid 37
005080700
700204005
320000084
060105040
008000500
070803010
450000091
600508007
003010600
Grid 38
000900800
128006400
070800060
800430007
500000009
600079008
090004010
003600284
001007000
Grid 39
000080000
270000054
095000810
009806400
020403060
006905100
017000620
460000038
000090000
Grid 40
000602000
400050001
085010620
038206710
000000000
019407350
026040530
900020007
000809000
Grid 41
000900002
050123400
030000160
908000000
070000090
000000205
091000050
007439020
400007000
Grid 42
380000000
000400785
009020300
060090000
800302009
000040070
001070500
495006000
000000092
Grid 43
000158000
002060800
030000040
027030510
000000000
046080790
050000080
004070100
000325000
Grid 44
010500200
900001000
002008030
500030007
008000500
600080004
040100700
000700006
003004050
Grid 45
080000040
000469000
400000007
005904600
070608030
008502100
900000005
000781000
060000010
Grid 46
904200007
010000000
000706500
000800090
020904060
040002000
001607000
000000030
300005702
Grid 47
000700800
006000031
040002000
024070000
010030080
000060290
000800070
860000500
002006000
Grid 48
001007090
590080001
030000080
000005800
050060020
004100000
080000030
100020079
020700400
Grid 49
000003017
015009008
060000000
100007000
009000200
000500004
000000020
500600340
340200000
Grid 50
300200000
000107000
706030500
070009080
900020004
010800050
009040301
000702000
000008006

用意できたら早速解いてみましょう。
50問をすべて解くには以下のようにします。

gosh> (begin (map (lambda (n) (print n) (print-grid (hash->grid (solve-test "./mondai.txt" n)))) (enumerate-interval 1 50)) 'done)
1
(4 8 3 9 2 1 6 5 7)
(9 6 7 3 4 5 8 2 1)
(2 5 1 8 7 6 4 9 3)
(5 4 8 1 3 2 9 7 6)
(7 2 9 5 6 4 1 3 8)
(1 3 6 7 9 8 2 4 5)
(3 7 2 6 8 9 5 1 4)
(8 1 4 2 5 3 7 6 9)
(6 9 5 4 1 7 3 8 2)
2
(2 4 5 9 8 1 3 7 6)
(1 6 9 2 7 3 5 8 4)
(8 3 7 5 6 4 2 1 9)
(9 7 6 1 2 5 4 3 8)
(5 1 3 4 9 8 6 2 7)
(4 8 2 7 3 6 9 5 1)
(3 9 1 6 5 7 8 4 2)
(7 2 8 3 4 9 1 6 5)
(6 5 4 8 1 2 7 9 3)
3
(4 6 2 8 3 1 9 5 7)
(7 9 5 4 2 6 1 8 3)
(3 8 1 7 9 5 4 2 6)
(1 7 3 9 8 4 2 6 5)
(6 5 9 3 1 2 7 4 8)
(2 4 8 5 6 7 3 1 9)
(9 2 6 1 7 8 5 3 4)
(8 3 4 2 5 9 6 7 1)
(5 1 7 6 4 3 8 9 2)
4
(1 3 7 2 5 6 8 4 9)
(9 2 8 3 1 4 5 6 7)
(4 6 5 8 9 7 3 1 2)
(6 7 3 5 4 2 9 8 1)
(8 1 9 6 7 3 2 5 4)
(5 4 2 1 8 9 7 3 6)
(2 5 6 7 3 1 4 9 8)
(3 9 1 4 2 8 6 7 5)
(7 8 4 9 6 5 1 2 3)
5
(5 2 3 8 1 6 7 4 9)
(7 8 4 5 9 3 1 2 6)
(6 9 1 4 7 2 8 3 5)
(2 3 9 1 4 5 6 8 7)
(4 5 7 2 6 8 9 1 3)
(1 6 8 9 3 7 2 5 4)
(3 4 2 7 8 9 5 6 1)
(9 1 5 6 2 4 3 7 8)
(8 7 6 3 5 1 4 9 2)
6
(1 7 6 9 2 3 5 8 4)
(5 2 4 8 1 7 6 3 9)
(8 9 3 6 5 4 2 7 1)
(9 5 7 3 4 8 1 6 2)
(6 3 8 1 9 2 4 5 7)
(4 1 2 7 6 5 3 9 8)
(2 6 5 4 8 9 7 1 3)
(7 8 1 2 3 6 9 4 5)
(3 4 9 5 7 1 8 2 6)
7
(1 4 3 9 8 6 2 5 7)
(6 7 9 4 2 5 3 8 1)
(2 8 5 7 3 1 6 9 4)
(9 6 2 3 5 4 1 7 8)
(3 5 7 6 1 8 9 4 2)
(4 1 8 2 7 9 5 6 3)
(8 2 1 5 6 7 4 3 9)
(7 9 6 1 4 3 8 2 5)
(5 3 4 8 9 2 7 1 6)
8
(4 8 7 1 5 6 9 3 2)
(3 6 2 4 9 8 7 5 1)
(9 1 5 3 7 2 8 6 4)
(8 4 6 5 1 9 2 7 3)
(5 9 3 7 2 4 1 8 6)
(2 7 1 8 6 3 5 4 9)
(1 2 4 6 8 5 3 9 7)
(7 3 8 9 4 1 6 2 5)
(6 5 9 2 3 7 4 1 8)
9
(8 1 4 9 7 6 5 3 2)
(6 5 9 1 2 3 4 7 8)
(7 3 2 8 5 4 1 6 9)
(9 4 8 2 6 5 3 1 7)
(2 7 5 3 4 1 8 9 6)
(1 6 3 7 9 8 2 4 5)
(3 9 1 6 8 2 7 5 4)
(5 8 7 4 3 9 6 2 1)
(4 2 6 5 1 7 9 8 3)
10
(7 6 1 9 2 8 4 5 3)
(9 2 5 7 4 3 1 6 8)
(4 3 8 6 1 5 9 2 7)
(3 5 7 4 6 1 2 8 9)
(8 9 4 3 7 2 6 1 5)
(2 1 6 5 8 9 3 7 4)
(6 8 9 1 5 4 7 3 2)
(1 4 2 8 3 7 5 9 6)
(5 7 3 2 9 6 8 4 1)
11
(9 7 6 1 2 5 4 3 8)
(1 5 8 4 3 6 9 2 7)
(4 2 3 8 7 9 1 5 6)
(2 3 4 7 6 1 8 9 5)
(8 6 7 9 5 2 3 1 4)
(5 1 9 3 8 4 7 6 2)
(7 8 2 5 1 3 6 4 9)
(3 9 5 6 4 7 2 8 1)
(6 4 1 2 9 8 5 7 3)
12
(9 6 2 3 4 1 7 5 8)
(1 4 8 9 7 5 6 2 3)
(5 7 3 2 6 8 1 4 9)
(3 2 1 6 9 4 8 7 5)
(4 8 7 5 1 2 9 3 6)
(6 9 5 8 3 7 4 1 2)
(8 3 4 7 2 6 5 9 1)
(2 1 6 4 5 9 3 8 7)
(7 5 9 1 8 3 2 6 4)
13
(3 9 7 6 8 1 5 2 4)
(6 4 5 2 7 9 8 1 3)
(2 1 8 5 3 4 9 7 6)
(8 2 3 9 5 6 7 4 1)
(1 6 9 7 4 2 3 5 8)
(7 5 4 3 1 8 6 9 2)
(4 7 2 8 9 3 1 6 5)
(5 3 1 4 6 7 2 8 9)
(9 8 6 1 2 5 4 3 7)
14
(6 3 9 2 1 8 4 5 7)
(4 7 1 5 3 9 2 6 8)
(8 2 5 6 7 4 1 3 9)
(5 6 4 8 2 3 7 9 1)
(7 9 3 4 5 1 8 2 6)
(2 1 8 7 9 6 3 4 5)
(3 5 2 9 8 7 6 1 4)
(1 8 6 3 4 5 9 7 2)
(9 4 7 1 6 2 5 8 3)
15
(6 9 7 1 2 8 3 4 5)
(4 2 8 6 3 5 1 9 7)
(3 1 5 4 7 9 6 8 2)
(5 3 1 2 4 6 9 7 8)
(2 8 6 3 9 7 4 5 1)
(9 7 4 5 8 1 2 6 3)
(1 4 9 8 5 2 7 3 6)
(7 5 2 9 6 3 8 1 4)
(8 6 3 7 1 4 5 2 9)
16
(3 6 1 7 2 5 9 4 8)
(5 8 7 9 6 4 2 1 3)
(4 9 2 8 3 1 6 5 7)
(6 3 8 2 5 9 4 7 1)
(1 7 4 6 8 3 5 9 2)
(2 5 9 1 4 7 8 3 6)
(7 4 6 3 9 2 1 8 5)
(9 2 3 5 1 8 7 6 4)
(8 1 5 4 7 6 3 2 9)
17
(3 5 9 8 6 7 1 2 4)
(6 4 8 3 1 2 5 9 7)
(7 1 2 5 4 9 8 3 6)
(8 7 6 9 2 4 3 5 1)
(5 2 4 7 3 1 9 6 8)
(1 9 3 6 8 5 4 7 2)
(9 3 1 4 7 6 2 8 5)
(4 6 5 2 9 8 7 1 3)
(2 8 7 1 5 3 6 4 9)
18
(7 8 6 9 4 5 3 1 2)
(2 1 9 8 6 3 4 5 7)
(5 3 4 2 7 1 8 6 9)
(1 6 5 4 8 2 9 7 3)
(3 2 7 6 1 9 5 4 8)
(4 9 8 5 3 7 1 2 6)
(9 5 1 7 2 8 6 3 4)
(8 4 2 3 5 6 7 9 1)
(6 7 3 1 9 4 2 8 5)
19
(7 4 3 5 1 2 9 8 6)
(5 8 9 3 4 6 2 1 7)
(1 2 6 9 8 7 3 4 5)
(9 3 4 2 5 1 7 6 8)
(6 7 1 4 9 8 5 3 2)
(8 5 2 7 6 3 4 9 1)
(3 9 8 6 7 5 1 2 4)
(4 1 7 8 2 9 6 5 3)
(2 6 5 1 3 4 8 7 9)
20
(7 8 2 6 1 4 3 5 9)
(4 3 9 8 2 5 1 7 6)
(6 5 1 9 3 7 4 2 8)
(2 9 3 4 7 1 8 6 5)
(5 6 8 3 9 2 7 1 4)
(1 4 7 5 6 8 2 9 3)
(3 2 6 7 4 9 5 8 1)
(9 7 5 1 8 3 6 4 2)
(8 1 4 2 5 6 9 3 7)
21
(4 2 8 5 3 1 7 9 6)
(3 6 5 9 4 7 1 8 2)
(9 7 1 2 6 8 4 3 5)
(2 1 4 8 9 6 5 7 3)
(6 9 7 4 5 3 2 1 8)
(5 8 3 1 7 2 9 6 4)
(8 4 9 6 1 5 3 2 7)
(7 5 2 3 8 9 6 4 1)
(1 3 6 7 2 4 8 5 9)
22
(4 2 5 7 8 1 9 3 6)
(1 7 8 3 6 9 5 2 4)
(3 6 9 5 2 4 1 8 7)
(8 9 4 1 5 7 3 6 2)
(6 5 2 8 4 3 7 9 1)
(7 1 3 6 9 2 8 4 5)
(9 8 7 2 1 6 4 5 3)
(5 3 6 4 7 8 2 1 9)
(2 4 1 9 3 5 6 7 8)
23
(3 4 8 2 6 7 9 5 1)
(5 7 1 9 4 3 6 2 8)
(2 6 9 1 8 5 3 7 4)
(6 9 7 3 5 1 4 8 2)
(1 2 3 8 7 4 5 9 6)
(8 5 4 6 2 9 1 3 7)
(4 1 5 7 9 8 2 6 3)
(9 8 2 4 3 6 7 1 5)
(7 3 6 5 1 2 8 4 9)
24
(1 2 4 9 8 6 7 3 5)
(8 6 7 4 3 5 9 1 2)
(3 9 5 7 1 2 6 8 4)
(4 7 8 3 5 9 2 6 1)
(2 5 9 8 6 1 3 4 7)
(6 3 1 2 7 4 5 9 8)
(7 1 2 6 9 8 4 5 3)
(9 8 3 5 4 7 1 2 6)
(5 4 6 1 2 3 8 7 9)
25
(3 6 1 5 2 4 7 8 9)
(7 8 9 3 6 1 4 2 5)
(5 2 4 8 7 9 3 6 1)
(8 9 3 1 5 7 6 4 2)
(4 1 2 6 8 3 5 9 7)
(6 5 7 9 4 2 1 3 8)
(1 4 8 7 9 6 2 5 3)
(2 3 5 4 1 8 9 7 6)
(9 7 6 2 3 5 8 1 4)
26
(5 8 1 4 7 9 2 6 3)
(3 2 9 1 5 6 8 4 7)
(6 4 7 3 2 8 1 5 9)
(9 5 6 7 3 1 4 2 8)
(2 3 8 9 6 4 5 7 1)
(7 1 4 5 8 2 9 3 6)
(1 7 2 6 9 5 3 8 4)
(8 9 3 2 4 7 6 1 5)
(4 6 5 8 1 3 7 9 2)
27
(3 8 7 2 5 6 4 1 9)
(4 6 9 7 8 1 3 2 5)
(5 1 2 4 3 9 8 6 7)
(1 2 3 5 4 8 9 7 6)
(7 5 8 9 6 3 2 4 1)
(6 9 4 1 2 7 5 8 3)
(8 3 5 6 7 4 1 9 2)
(2 7 1 8 9 5 6 3 4)
(9 4 6 3 1 2 7 5 8)
28
(3 4 5 8 7 1 2 6 9)
(2 7 9 6 5 3 1 8 4)
(8 6 1 4 2 9 5 3 7)
(1 9 7 3 4 6 8 5 2)
(4 5 2 7 1 8 3 9 6)
(6 8 3 5 9 2 7 4 1)
(7 3 8 2 6 4 9 1 5)
(5 1 6 9 3 7 4 2 8)
(9 2 4 1 8 5 6 7 3)
29
(2 3 5 7 6 1 4 8 9)
(4 1 9 3 2 8 5 7 6)
(8 6 7 5 4 9 2 1 3)
(7 4 6 1 3 5 9 2 8)
(5 2 1 8 9 6 7 3 4)
(9 8 3 4 7 2 6 5 1)
(3 9 4 2 8 7 1 6 5)
(6 5 2 9 1 3 8 4 7)
(1 7 8 6 5 4 3 9 2)
30
(2 9 8 1 7 5 6 4 3)
(6 5 7 3 9 4 1 2 8)
(1 3 4 2 8 6 5 7 9)
(8 2 1 6 4 9 7 3 5)
(5 7 3 8 2 1 4 9 6)
(4 6 9 7 5 3 2 8 1)
(3 1 2 4 6 8 9 5 7)
(7 8 5 9 1 2 3 6 4)
(9 4 6 5 3 7 8 1 2)
31
(7 6 1 5 4 3 2 8 9)
(8 3 2 7 9 1 6 4 5)
(5 4 9 6 2 8 1 3 7)
(3 7 4 2 1 5 9 6 8)
(1 2 8 9 3 6 5 7 4)
(6 9 5 4 8 7 3 2 1)
(4 1 7 3 6 9 8 5 2)
(9 5 3 8 7 2 4 1 6)
(2 8 6 1 5 4 7 9 3)
32
(1 3 2 6 4 9 7 8 5)
(7 5 8 2 1 3 6 4 9)
(9 6 4 7 8 5 1 2 3)
(5 4 3 8 9 7 2 1 6)
(2 7 6 5 3 1 8 9 4)
(8 9 1 4 2 6 5 3 7)
(6 1 9 3 7 8 4 5 2)
(3 2 7 1 5 4 9 6 8)
(4 8 5 9 6 2 3 7 1)
33
(6 9 8 1 7 3 5 4 2)
(3 5 4 6 2 8 1 7 9)
(1 7 2 5 4 9 3 6 8)
(5 3 1 8 9 7 4 2 6)
(9 4 6 3 1 2 8 5 7)
(8 2 7 4 5 6 9 1 3)
(7 6 5 9 3 1 2 8 4)
(2 1 3 7 8 4 6 9 5)
(4 8 9 2 6 5 7 3 1)
34
(8 5 2 7 1 6 9 4 3)
(1 9 7 8 4 3 6 5 2)
(4 6 3 9 2 5 1 8 7)
(2 7 8 6 3 4 5 9 1)
(6 4 5 1 7 9 3 2 8)
(9 3 1 5 8 2 4 7 6)
(7 8 6 4 9 1 2 3 5)
(3 1 4 2 5 8 7 6 9)
(5 2 9 3 6 7 8 1 4)
35
(4 5 3 2 1 8 7 9 6)
(6 2 9 7 5 3 4 8 1)
(1 7 8 4 9 6 5 3 2)
(7 9 6 5 8 2 3 1 4)
(3 1 4 9 6 7 8 2 5)
(2 8 5 1 3 4 6 7 9)
(5 4 2 8 7 9 1 6 3)
(9 3 7 6 4 1 2 5 8)
(8 6 1 3 2 5 9 4 7)
36
(5 1 6 2 8 9 3 4 7)
(8 4 9 1 7 3 2 5 6)
(7 3 2 4 6 5 9 1 8)
(6 9 8 3 1 7 5 2 4)
(3 2 7 9 5 4 8 6 1)
(1 5 4 8 2 6 7 3 9)
(9 6 1 7 3 2 4 8 5)
(2 7 5 6 4 8 1 9 3)
(4 8 3 5 9 1 6 7 2)
37
(9 4 5 6 8 1 7 2 3)
(7 8 1 2 3 4 9 6 5)
(3 2 6 7 5 9 1 8 4)
(2 6 9 1 7 5 3 4 8)
(1 3 8 9 4 2 5 7 6)
(5 7 4 8 6 3 2 1 9)
(4 5 7 3 2 6 8 9 1)
(6 1 2 5 9 8 4 3 7)
(8 9 3 4 1 7 6 5 2)
38
(3 6 5 9 4 2 8 7 1)
(1 2 8 7 5 6 4 9 3)
(9 7 4 8 1 3 5 6 2)
(8 1 9 4 3 5 6 2 7)
(5 3 7 2 6 8 1 4 9)
(6 4 2 1 7 9 3 5 8)
(2 9 6 3 8 4 7 1 5)
(7 5 3 6 9 1 2 8 4)
(4 8 1 5 2 7 9 3 6)
39
(1 3 4 5 8 7 2 9 6)
(2 7 8 1 6 9 3 5 4)
(6 9 5 2 3 4 8 1 7)
(3 5 9 8 1 6 4 7 2)
(8 2 1 4 7 3 5 6 9)
(7 4 6 9 2 5 1 8 3)
(9 1 7 3 4 8 6 2 5)
(4 6 2 7 5 1 9 3 8)
(5 8 3 6 9 2 7 4 1)
40
(1 9 3 6 7 2 4 8 5)
(4 6 2 3 5 8 9 7 1)
(7 8 5 9 1 4 6 2 3)
(5 3 8 2 9 6 7 1 4)
(6 7 4 1 3 5 2 9 8)
(2 1 9 4 8 7 3 5 6)
(8 2 6 7 4 1 5 3 9)
(9 4 1 5 2 3 8 6 7)
(3 5 7 8 6 9 1 4 2)
41
(8 1 4 9 7 6 5 3 2)
(6 5 9 1 2 3 4 7 8)
(7 3 2 8 5 4 1 6 9)
(9 4 8 2 6 5 3 1 7)
(2 7 5 3 4 1 8 9 6)
(1 6 3 7 9 8 2 4 5)
(3 9 1 6 8 2 7 5 4)
(5 8 7 4 3 9 6 2 1)
(4 2 6 5 1 7 9 8 3)
42
(3 8 4 5 6 7 9 2 1)
(1 2 6 4 3 9 7 8 5)
(7 5 9 8 2 1 3 4 6)
(5 6 3 7 9 8 2 1 4)
(8 4 7 3 1 2 6 5 9)
(9 1 2 6 4 5 8 7 3)
(2 3 1 9 7 4 5 6 8)
(4 9 5 2 8 6 1 3 7)
(6 7 8 1 5 3 4 9 2)
43
(4 6 9 1 5 8 3 7 2)
(7 1 2 4 6 3 8 5 9)
(5 3 8 2 9 7 6 4 1)
(9 2 7 6 3 4 5 1 8)
(3 8 5 7 1 9 4 2 6)
(1 4 6 5 8 2 7 9 3)
(6 5 3 9 4 1 2 8 7)
(2 9 4 8 7 6 1 3 5)
(8 7 1 3 2 5 9 6 4)
44
(3 1 6 5 4 9 2 7 8)
(9 8 7 3 2 1 6 4 5)
(4 5 2 6 7 8 9 3 1)
(5 9 4 2 3 6 8 1 7)
(2 3 8 4 1 7 5 6 9)
(6 7 1 9 8 5 3 2 4)
(8 4 5 1 6 2 7 9 3)
(1 2 9 7 5 3 4 8 6)
(7 6 3 8 9 4 1 5 2)
45
(5 8 6 1 2 7 9 4 3)
(7 2 3 4 6 9 8 5 1)
(4 9 1 8 5 3 2 6 7)
(1 3 5 9 7 4 6 2 8)
(2 7 9 6 1 8 5 3 4)
(6 4 8 5 3 2 1 7 9)
(9 1 7 2 4 6 3 8 5)
(3 5 2 7 8 1 4 9 6)
(8 6 4 3 9 5 7 1 2)
46
(9 5 4 2 1 3 6 8 7)
(6 1 7 5 4 8 9 2 3)
(8 3 2 7 9 6 5 4 1)
(7 6 3 8 5 1 2 9 4)
(1 2 8 9 7 4 3 6 5)
(5 4 9 3 6 2 1 7 8)
(2 8 1 6 3 7 4 5 9)
(4 7 5 1 2 9 8 3 6)
(3 9 6 4 8 5 7 1 2)
47
(1 5 9 7 4 3 8 6 2)
(2 7 6 5 8 9 4 3 1)
(3 4 8 6 1 2 7 5 9)
(6 2 4 9 7 8 3 1 5)
(9 1 7 2 3 5 6 8 4)
(5 8 3 1 6 4 2 9 7)
(4 3 5 8 2 1 9 7 6)
(8 6 1 4 9 7 5 2 3)
(7 9 2 3 5 6 1 4 8)
48
(8 6 1 3 5 7 2 9 4)
(5 9 7 4 8 2 3 6 1)
(4 3 2 6 1 9 7 8 5)
(9 1 6 2 7 5 8 4 3)
(3 5 8 9 6 4 1 2 7)
(2 7 4 1 3 8 9 5 6)
(7 8 9 5 4 1 6 3 2)
(1 4 3 8 2 6 5 7 9)
(6 2 5 7 9 3 4 1 8)
49
(2 9 4 8 6 3 5 1 7)
(7 1 5 4 2 9 6 3 8)
(8 6 3 7 5 1 4 9 2)
(1 5 2 9 4 7 8 6 3)
(4 7 9 3 8 6 2 5 1)
(6 3 8 5 1 2 9 7 4)
(9 8 6 1 3 4 7 2 5)
(5 2 1 6 7 8 3 4 9)
(3 4 7 2 9 5 1 8 6)
50
(3 5 1 2 8 6 4 9 7)
(4 9 2 1 5 7 6 3 8)
(7 8 6 9 3 4 5 1 2)
(2 7 5 4 6 9 1 8 3)
(9 3 8 5 2 1 7 6 4)
(6 1 4 8 7 3 2 5 9)
(8 2 9 6 4 5 3 7 1)
(1 6 3 7 9 2 8 4 5)
(5 4 7 3 1 8 9 2 6)
done

すべて解けました。

1問だけ解きたい場合は以下のようにします。

gosh> (print-grid (hash->grid (solve-test "./mondai.txt" 1)))
(4 8 3 9 2 1 6 5 7)
(9 6 7 3 4 5 8 2 1)
(2 5 1 8 7 6 4 9 3)
(5 4 8 1 3 2 9 7 6)
(7 2 9 5 6 4 1 3 8)
(1 3 6 7 9 8 2 4 5)
(3 7 2 6 8 9 5 1 4)
(8 1 4 2 5 3 7 6 9)
(6 9 5 4 1 7 3 8 2)
done

ナンプレにおいて、仮置法を使用するのは問題を解く人の自由ですが、
仮置法を前提とする問題は「邪道」とする人が多い気がします。
本プログラムにおいても仮置法は実装していません。