Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Clojure中,如何检查数独解决方案是否有效?_Clojure_Sudoku - Fatal编程技术网

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

在Clojure中,如何检查数独解决方案是否有效?,clojure,sudoku,Clojure,Sudoku,为了学习Clojure的基础知识,我正在编写一个数独解决方案检查器。我已将提供的解决方案存储在二维向量中 (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] [

为了学习Clojure的基础知识,我正在编写一个数独解决方案检查器。我已将提供的解决方案存储在二维向量中

(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有更好的方法?如何检查垂直线或正方形的总和?

水平线很容易。从字面上看,这只是
解决方案
:您需要一个数字列表,而这正是您已经拥有的

我无法想象为什么要求和,因为这与检查数独解决方案无关(应该包括检查唯一性)。但是,如果您这样做了,您可以使用
(map#(reduce+%)解决方案)
对每个水平面求和

垂直方向包含一个巧妙的技巧:您可以使用
(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)))

水平面很容易。从字面上看,这只是
解决方案
:您需要一个数字列表,而这正是您已经拥有的

我无法想象为什么要求和,因为这与检查数独解决方案无关(应该包括检查唯一性)。但是,如果您这样做了,您可以使用
(map#(reduce+%)解决方案)
对每个水平面求和

垂直方向包含一个巧妙的技巧:您可以使用
(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)))

虽然这并不是严格地回答您问题中的算法部分,但我认为值得指出的是,这段代码可能没有做您认为它正在做的事情:

(def horizontals [])

(for [i solution] 
  (conj horizontals (reduce + i)))
您似乎期望
以迭代的方式对
进行评估,并且每次调用
conj
更新var
水平
的内容,将每行的总和追加到向量。这显然不是Clojure的运作方式

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

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


最后,
for
在Clojure中不是循环结构,而是列表理解。本质上,它所做的是创建一个惰性序列,该序列由内部表达式的结果(调用
conj
函数)和您提供的绑定序列(部分
[i解决方案]
组成)。在使用生成的惰性序列之前,表达式实际上不会执行——在您的例子中,通过在REPL中打印结果。

虽然这并不是对问题的算法部分的严格回答,但我认为值得指出的是,这段代码可能没有做您认为它正在做的事情:

(def horizontals [])

(for [i solution] 
  (conj horizontals (reduce + i)))
您似乎期望
以迭代的方式对
进行评估,并且每次调用
conj
更新var
水平
的内容,将每行的总和追加到向量。这显然不是Clojure的运作方式

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

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

最后,
for
在Clojure中不是循环结构,而是列表理解。本质上,它所做的是创建一个由内部表达式的结果组成的惰性序列(代码