Advertisement
Guest User

Untitled

a guest
Jan 16th, 2012
125
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. (ns clj-sudoku.core
  2.   (:gen-class))
  3.  
  4. ;;; Records
  5.  
  6. (defrecord Square [pos x y num hints sure unit])
  7. (defrecord Item [square state])
  8.  
  9. ;;; Grids
  10.  
  11. (def easy-grid ".931.564.7.......55.12.93.72.......3.369.752.9.......13.24.81.96.......4.473.285.")
  12. (def medium-grid "4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......")
  13. (def hard-grid "..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9")
  14. (def hard-grid2 "....9..5..1.....3...23..7....45...7.8.....2.......64...9..1.....8..6......54....7")
  15. (def hard-grid3 "4...3.......6..8..........1....5..9..8....6...7.2........1.27..5.3....4.9........")
  16.  
  17. ;;; Gen table
  18.  
  19. (defn- parser [e y]
  20.   (map #(let [num (if (= \. %1) nil (Integer/parseInt (str %1)))]
  21.           (Square. (+ (* 9 (- y 1)) %2) %2 y num (if num nil (range 1 10))
  22.                    (if num true false) nil)) e (range 1 10)))
  23.  
  24. (defn- process [u i]
  25.   (map (fn [a]
  26.          (let [tmp (partition 3 a)]
  27.            (map (fn [e c]
  28.                   (map #(assoc % :unit c) e))
  29.                 tmp (range i (+ i 3))))) u))
  30.  
  31. (defn- make-units [sudoku]
  32.   (let [[tu1-3 tu4-6 tu7-9] (partition 3 (partition 9 (vals (sort sudoku))))]
  33.     (apply assoc sudoku
  34.            (mapcat
  35.             #(list (:pos %) %)
  36.             (flatten
  37.              (concat (process tu1-3 1)
  38.                      (process tu4-6 4)
  39.                      (process tu7-9 7)))))))
  40.  
  41. (defn- gen-sudoku [s]
  42.   (make-units (zipmap (range 1 82)
  43.                       (mapcat parser (partition 9 s) (range 1 10)))))
  44.  
  45. ;;; Methods
  46.  
  47. (defn- valid-state? [state]
  48.   (empty? (filter #(and (empty? (:hints %))
  49.                        (false? (:sure %))
  50.                        (nil? (:num %))) (vals state))))
  51.  
  52. (defn- valid-square? [square peers]
  53.   (empty? (filter #(= (:num %) (:num square)) peers)))
  54.  
  55. (defn- clean-hints [sq num]
  56.   (let [hints (remove #(= % num) (:hints sq))]
  57.     (assoc sq :hints hints)))
  58.  
  59. (defn- new-state [state square peers]
  60.   (let [n-state (apply assoc state
  61.                        (mapcat #(list (:pos %) %)
  62.                                (map #(clean-hints % (:num square)) peers)))]
  63.     (assoc n-state (:pos square) square)))
  64.  
  65. (defn- get-peers [state square]
  66.   (let [row (filter #(= (:y %) (:y square)) (vals state))
  67.         col (filter #(= (:x %) (:x square)) (vals state))
  68.         peers (filter #(= (:unit square) (:unit %)) (vals state))]
  69.     (remove #(= % square) (flatten [row col peers]))))
  70.  
  71. (defn- few-hints-square [state]
  72.   (let [v (vals state)
  73.         ss (filter #(not (empty? (:hints %))) v)]
  74.     (first (sort-by #(count (:hints %)) ss))))
  75.  
  76. (defn- complete-sures [state]
  77.   (let [sures (filter #(true? (:sure %)) (vals state))]
  78.     (loop [queue sures
  79.            state state]
  80.       (let [square (last queue)
  81.             peers (get-peers state square)
  82.             n-state (new-state state square peers)
  83.             n-queue (butlast queue)]
  84.         (if n-queue
  85.           (recur n-queue n-state)
  86.           n-state)))))
  87.  
  88. (defn- solve-sudoku [state]
  89.   (let [f-st (complete-sures state)]
  90.     (loop [queue (cons {:square (few-hints-square f-st)
  91.                         :state f-st} '())]
  92.       (let [current (last queue)
  93.             {square :square state :state} current]
  94.         (if (:hints square)
  95.           (let [hints (:hints square)
  96.                 nexts (reverse (map #(hash-map :square (assoc square :num % :hints nil)
  97.                                                :state state) hints))]
  98.             (recur (concat (butlast queue) nexts)))
  99.           (let [peers (get-peers state square)
  100.                 n-state (new-state state square peers)
  101.                 n-square (few-hints-square n-state)]
  102.             (if (and (valid-square? square peers)
  103.                      (valid-state? n-state))
  104.               (if n-square
  105.                 (recur (cons {:square n-square
  106.                               :state n-state} (butlast queue)))
  107.                 n-state)
  108.               (recur (butlast queue)))))))))
  109.  
  110. (defn solve-grid [grid]
  111.   (let [sudoku (gen-sudoku grid)]
  112.     (solve-sudoku sudoku)))
  113.  
  114. (defn -main []
  115.   (let [solution (solve-grid easy-grid)]
  116.     (map #(:num %) (vals (sort solution)))))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement