在Clojure中,我如何检查数独解决方案是否有效?

时间:2014-05-14 18:21:26

标签: clojure sudoku

为了学习Clojure的基础知识,我正在编写一个Sudoku解决方案 checker 。我已将提供的解决方案存储在二维矢量中。

(def solution [[4 2 9 8 1 3 5 6 7]  
               [5 1 6 4 7 2 9 3 8] 
               [7 8 3 6 5 9 2 4 1] 
               [6 7 2 1 3 4 8 5 9] 
               [3 9 5 2 8 6 1 7 4] 
               [8 4 1 7 9 5 6 2 3] 
               [1 5 8 3 6 7 4 9 2] 
               [9 3 4 5 2 8 7 1 6] 
               [2 6 7 9 4 1 3 8 5]])

在Java中,我可以很容易地使用嵌套循环来分割水平线,垂直线和正方形,但我不知道如何在Clojure中处理它。

我的第一次尝试产生了这样的东西来获得横向的总和:

(def horizontals [])

(for [i solution] 
  (conj horizontals (reduce + i)))

打印出来的:

([45] [45] [45] [45] [45] [45] [45] [45] [45])

这是检查水平线的“正确”方法吗?或者在Clojure中有更好的方法吗?我如何检查垂直或正方形的总和?

2 个答案:

答案 0 :(得分:4)

水平很容易。它实际上只是solutions:你想要一个数字列表清单,这就是你已有的数据!

我无法想象为什么要总结一些东西,因为这与检查数独解决方案无关(这应该涉及检查唯一性)。但是,如果你这样做,你可以用(map #(reduce + %) solution)对每个水平相加。

纵向涉及一个巧妙的技巧:你可以使用(apply map vector m)转置"矩阵"嵌套向量。所以只需将解决方案旋转90度,然后检查水平线!当然,如果你想,你可以用同样的方式添加它们,虽然我再也不知道为什么。

正方形更有趣,有几种方法可以解决它。我会使用get-in和一系列坐标对,例如:

 (defn squares [solution]
   (for [y (range 3)
         x (range 3)]
     (for [y' (range 3)
           x' (range 3)]
       (get-in solution [(+ y' (* 3 y))
                         (+ x' (* 3 x))]))))

为了完整性:我确实说你应该检查唯一性而不是总结(毕竟,9 5s总和45,但这绝对不是一个好的解决方案!)。这是验证9个数字列表构成有效行/列/方块的一种方法:

(defn valid? [numbers]
  (and (= 9 (count numbers)) 
       (= (set (range 1 10)) 
          (set numbers)))

答案 1 :(得分:1)

虽然这不是问题的算法部分的严格答案,但我认为值得指出的是,这段代码可能没有按照您的想法进行:

(def horizontals [])

(for [i solution] 
  (conj horizontals (reduce + i)))

您似乎希望以迭代方式评估for,并且每次调用conj以更新var horizontals的内容,将每行的总和追加到矢量。这绝对是在Clojure中的运作方式。

相反,空向量[]是不可变的;在向量上调用conj不会改变向量的内容 - 它返回一个全新的向量,它与原始向量相同但添加了新的元素。

同样,调用(conj horizontals (reduce + i))不会更新horizontals的当前值。它是一个函数调用,它取当前值horizontals(向量)并返回一个新值(另一个不同的向量);这取决于你对这个结果做些什么。通常,一旦你def变量,它在整个程序中保持不变,除非你明确地改变它。通过重新定义变量进行编程在Clojure中非常不受欢迎。

最后,for不是Clojure中的循环结构,它是列表理解。基本上它所做的是创建一个惰性序列,该序列由内部表达式(conj函数调用)的结果组成,包含您提供的一系列绑定([i solution]部分)。在使用生成的延迟序列之前,表达式实际上不会执行 - 在您的情况下,通过在REPL中打印结果。