美文网首页
Clojure逻辑式编程求解数独

Clojure逻辑式编程求解数独

作者: mingdongz | 来源:发表于2018-04-26 15:11 被阅读0次
(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逻辑式编程求解数独

  • Clojure 学习笔记 :5 我来组成函数~

    Clojure 零基础 学习笔记 函数式编程 函数即是值。 终于,我们要介绍 Clojure 中最重要的部分了。在...

  • 学习Clojure第十天

    主要函数(Bread and butter Functions) Clojure是函数式编程的语言(Functio...

  • clojure的设计哲学

    clojure在函数式编程和可变状态之间取得了很好的平衡。 clojure精心设计了用于并发的语义,从而保留了可变...

  • JS写九九乘法表

    也就是最近开始接触函数式编程。在大神博客的熏陶之下,通过Clojure体验了一把函数抽取的乐趣。本以为对函数式编程...

  • Day-14 - 类和对象(2018-10-17)

    一、面向对象编程 编程思想: 面向过程编程 ---> 算法,逻辑(数学逻辑) 函数式编程 ---> 函数,模块 ...

  • RxJava系列|RxJava简介(一)

    函数响应式编程 函数式编程是一种编程范式。 常见的编程范式有:命令式编程、函数式编程和逻辑式编程。 面向对象就是一...

  • 你真的理解面向对象吗?

    面向对象 我们常见的编程范式有命令式编程,函数式编程,逻辑式编程,而面向对象编程是一种命令式编程。 命令式编程是面...

  • 类和对象

    01-面向对象编程 ----编程思想 ✈ 1、面向过程编程 --> 算法,逻辑(数学逻辑)✈ 2、函数式编程 --...

  • 一名Clojurian的Emacs配置

    我是一名热衷于函数式编程的Clojurian(Clojure粉),网络ID是lambeta(λβ),读作/‘læm...

网友评论

      本文标题:Clojure逻辑式编程求解数独

      本文链接:https://www.haomeiwen.com/subject/awtmlftx.html