(ns fun.sudoku
(:refer-clojure :exclude [==])
(:require [clojure.core.logic :as logic]
[clojure.core.logic.fd :as fd]))
;; 定义数独数据
(def b1 '[- - 1 - - - 2 - -
- 6 - - - 5 - 1 3
- - - - 1 - 7 - 6
6 - - 5 - 9 - - 8
- - 8 3 - 4 - 9 -
9 - - - - - - 2 -
- 1 - - - - - - 2
- 5 6 7 - - - - -
2 - 7 - - 1 5 - -])
;; 定义一些函数
(defn print-board [board] ;; 打印数独题目
(let [row-sep (apply str (repeat 37 "-"))
bx (map #(partition 3 %) (partition 9 board))]
(println row-sep)
(dotimes [row (count bx)]
(print "| ")
(doseq [subrow (nth bx row)]
(doseq [cell (butlast subrow)]
(print (str cell " ")))
(print (str (last subrow) " | ")))
(println)
(when (zero? (mod (inc row) 3))
(println row-sep)))))
;; 按行分组
(defn rowify [board]
(->> board
(partition 9)
(map vec)
vec))
;; 按列分组
(defn colify [rows]
(apply map vector rows))
;; 按3x3分组
(defn subgrid [rows]
(partition 9
(for [row (range 0 9 3)
col (range 0 9 3)
x (range row (+ row 3))
y (range col (+ col 3))]
(get-in rows [x y]))))
;; 接下来定义逻辑
;; 按数独数据初始化“知识”
(defn init [[lv & lvs] [cell & cells]]
(if lv
(logic/fresh []
(if (= '- cell)
logic/succeed
(logic/== lv cell))
(init lvs cells))
logic/succeed))
;; 初始化逻辑变量
(def logic-board #(repeatedly 81 logic/lvar))
;; ok,开始推理
(defn solve-logically [board]
(let [legal-nums (fd/interval 1 9)
lvars (logic-board)
rows (rowify lvars)
cols (colify rows)
grids (subgrid rows)]
(logic/run 1 [q]
(init lvars board)
(logic/everyg #(fd/in % legal-nums) lvars) ;; 条件1: 只能填1-9
(logic/everyg fd/distinct rows) ;; 条件2: 行不能重复
(logic/everyg fd/distinct cols) ;; 条件3: 列不能重复
(logic/everyg fd/distinct grids) ;; 条件4: 3x3方格内不能重复
(logic/== q lvars)))) ;; 结果
(comment
(-> b1
print-board)
(-> b1
solve-logically
first
print-board))
Clojure逻辑式编程求解数独
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
推荐阅读更多精彩内容
- 这些是C/C++能做的 服务器开发工程师、人工智能、云计算工程师、信息安全(黑客反黑客)、大数据 、数据平台、嵌入...
- 特此说明:文章分别来自网易数码和和讯新闻,仅作模仿练习使用。 第一篇: 原标题:极米无屏电视H1体验评测真的能代替...