简体   繁体   English

Haskell中的8个皇后区未知错误

[英]8 queens unknown error in haskell

This function isn't terminating! 该功能没有终止! I'm trying to generate all possible safe combinations on an eight by eight chessboard for eight queens. 我试图在八乘八棋的八乘八棋盘上生成所有可能的安全组合。 I'm not sure what's going wrong. 我不知道怎么了。 My code is below. 我的代码如下。 The board is represented as [x1, x2...x8] where the value xi is the column, and the index of said value is the row. 木板用[x1,x2 ... x8]表示,其中值xi是列,而该值的索引是行。

the safeH function should create all the combinations of eight numbers without duplications for example [1,4,3,5,8,6,7,2],[6,4,8,2,5,1,3,7] and so on... safeH函数应创建八个数字的所有组合而没有重复,例如[1,4,3,5,8,6,7,2],[6,4,8,2,5,1,3,7]等等...

the safeD function will compare the first element with all successors elements to ensure that there is no queen placed on the diagonal of this queen(this element) and so on .. safeD函数将比较第一个元素和所有后继元素,以确保在该皇后(这个元素)的对角线上没有放置任何皇后。

queens = [ [x1,x2,x3,x4,x5,x6,x7,x8] | x1 <- [1..8], x2 <- [1..8]
                                     , x3 <- [1..8], x4 <- [1..8]
                                     , x5 <- [1..8], x6 <- [1..8]
                                     , x7 <- [1..8], x8 <- [1..8]
                                     , safeH [x2,x3,x4,x5,x6,x7,x8] x1
                                     , safeD [x2,x3,x4,x5,x6,x7,x8] x1
                                             [x1,x2,x3,x4,x5,x6,x7,x8] 1 ]

safeH l e =
  if elem e l then False
  else if length (l)/=0 then safeH(tail l)(head l)
       else True

safeD l e xs n =
  if last xs /= e then
    if length l /= 0 then
      if head l + n == e || head l - n == e then False
      else safeD (tail l) e xs (n + 1)
    else safeD (tail xs) (head xs) xs 1
  else True

In order to compute queens , one must iterate through 8^8 = 16777216 cases, each of which will be subject to safeH and safeD . 为了计算queens ,必须迭代8 ^ 8 = 16777216个案例,每种情况都必须遵守safeHsafeD This would take quite a while. 这将需要一段时间。

queens = [ [x1,x2,x3,x4,x5,x6,x7,x8] | x1 <- [1..8], x2 <- [1..8]
                                     , x3 <- [1..8], x4 <- [1..8]
                                     , x5 <- [1..8], x6 <- [1..8]
                                     , x7 <- [1..8], x8 <- [1..8]

You could look into how others have solved the 8-queens problem in Haskell . 您可以研究其他人如何解决Haskell中的8皇后问题

As per the comments on Simon's answer, rather than fix your code, I'll step through my own. 根据对Simon答案的评论,而不是解决您的代码,我将逐步解决。 I hope it's useful for you to get a better understanding of the problem and understand Haskell a little better. 我希望这对您有一个更好的了解问题并更好地了解Haskell有用。 Obviously, if this is for an assignment, you shouldn't submit my code. 显然,如果这是一项任务,则不应提交我的代码。

Fair warning -- I'm very new to Haskell too, so I'm open to any suggestions from the peanut gallery! 合理警告-我也是Haskell的新手,所以我欢迎花生画廊的任何建议!

import Data.List
{- myNQueens n will solve the n-queens problem for the given board-size nxn 
   for n queens. Each board is represented by [x1, x2..xn] where the index
   represents the column and the value of xi represents the row. -} 

--type: this function takes an Int and returns a list of lists of Ints.
myNQueens :: Int -> [[Int]]
-- here is a list comprehension that does away with your safeH function.
-- it checks all permutations of the numbers [1..n] to see if they represent
-- a legal board. As you'll see, queensSafe only checks diagonals. Horizontals
-- do not need to be checked because generating the permutations already takes
-- care of that. If you'd prefer not to use Data.List.permutations, it shouldn't
-- be too hard to hand-roll your own.
myNQueens n = [x | x <- permutations [1..n], queensSafe x]

--type: from list of Ints to bool. Returns True if legal board, else False.
queensSafe :: [Int] -> Bool
-- queensSafe is a recursive function that checks if the queen in the first column
-- can be captured. If so, it returns false. If not, it is called again with the board
-- without the first column.

-- base case: the empty board is safe
queensSafe [] = True
-- l@(x:xs) is just pattern matching. x is the first element of the
-- list, xs is the remaining elements, and l is just syntactic sugar for
-- referencing the whole list.
queensSafe l@(x:xs)
-- these "guards" are basically if-else statements.
-- if firstQueenSafe l == True then queensSafe x:xs = queensSafe xs. else, False.
    | firstQueenSafe l == True = queensSafe xs
    | otherwise = False



firstQueenSafe :: [Int] -> Bool
firstQueenSafe l@(x:xs) =
    -- unsafe1 generates a list of all of the unsafe diagonals down and to the right.
    -- unsafe2 generates a list of all of the unsafe diagonals up and to the left.
    let unsafe1 = [x, x - 1 .. x - length l]
        unsafe2 = [x, x + 1 .. x + length l]
        -- zipped just pairs unsafe1 and unsafe2 with copies of the actual board 
        -- (except the first element.) If any of tuples contain 2 of the same values,
        -- then the board is unsafe.
        zipped = zip (tail unsafe1) (tail l) ++ zip (tail unsafe2) (tail l)
        -- countMatches just checks if there are any matches in zipped.
        countMatches = length [x | x <- zipped, fst x == snd x]
    in if countMatches == 0 then True else False

Obviously, this is non-optimal, but I think it's pretty clear. 显然,这不是最佳选择,但我认为这很清楚。 And quite a short piece of code! 和相当短的代码! Just to show that it works: 只是为了证明它有效:

*Main> head $ myNQueens 8
[6,4,7,1,3,5,2,8]
*Main> head $ myNQueens 9
[6,3,5,8,1,4,2,7,9]
*Main> head $ myNQueens 10
[7,5,8,2,9,3,6,4,1,10]
*Main> length $ myNQueens 8 -- runs in about a second
92
*Main> length $ myNQueens 9 -- runs in about 20 seconds
352
*Main> length $ myNQueens 10 -- runs in a couple of minutes
724

Learn You a Haskell and Real World Haskell are both really good resources. 向您了解Haskell真实世界Haskell都是非常好的资源。 I'm also working through 99 Haskell Problems , which is where I originally saw this problem. 我还在研究99 Haskell Problems ,这是我最初看到此问题的地方。 If you'd like to see some simple code that solves some of these other problems, (I'm not really trying to optimize, just make easy and readable code so I can learn) you can fork https://github.com/ostrowr/99-Haskell-Problems 如果您希望看到一些简单的代码来解决其他一些问题,(我并不是真正在尝试优化,只需编写简单易懂的代码,以便我学习即可),可以派发https://github.com/ ostrowr / 99-Haskell问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM