Haskell 中的回溯

发布于 2024-08-28 05:06:07 字数 2475 浏览 10 评论 0原文

我必须遍历一个矩阵并说出每种类型有多少个“特征区域”。

特征区域被定义为值n或>n的元素相邻的区域。

例如,给定矩阵:

0 1 2 2
0 1 1 2
0 3 0 0

有一个类型 1 的特征区域,它等于原始矩阵:

0 1 2 2
0 1 1 2
0 3 0 0

有两个类型 2 的特征区域:

0 0 2 2    0 0 0 0
0 0 0 2    0 0 0 0
0 0 0 0    0 3 0 0

和一个类型 3 的特征区域:

0 0 0 0 
0 0 0 0
0 3 0 0 

因此,对于函数调用:

countAreas [[0,1,2,2],[0,1,1,2],[0,3,0,0]] 

结果应为因为

[1,2,1]

我还没有定义 countAreas,所以当我的 visit 函数没有更多可能的方块来移动时,我会被卡住并且无法进行正确的递归调用。我是函数式编程的新手,对于如何在这里实现回溯算法我仍然摸不着头脑。看看我的代码,我能做些什么来改变它?

move_right :: (Int,Int) -> [[Int]] -> Int -> Bool
move_right (i,j) mat cond | (j + 1) < number_of_columns mat && consult (i,j+1) mat /= cond = True
               | otherwise = False

move_left :: (Int,Int) -> [[Int]] -> Int -> Bool
move_left (i,j) mat cond | (j - 1) >= 0 && consult (i,j-1) mat /= cond = True
               | otherwise = False

move_up :: (Int,Int) -> [[Int]] -> Int -> Bool
move_up (i,j) mat cond | (i - 1) >= 0 && consult (i-1,j) mat /= cond = True
               | otherwise = False

move_down :: (Int,Int) -> [[Int]] -> Int -> Bool
move_down (i,j) mat cond | (i + 1) < number_of_rows mat && consult (i+1,j) mat /= cond = True
               | otherwise = False

imp :: (Int,Int) -> Int
imp (i,j) = i


number_of_rows :: [[Int]] -> Int
number_of_rows i = length i

number_of_columns :: [[Int]] -> Int
number_of_columns (x:xs) =  length x

consult :: (Int,Int) -> [[Int]] -> Int
consult (i,j) l = (l !! i) !! j

visited :: (Int,Int) -> [(Int,Int)] -> Bool
visited x y = elem x y

add :: (Int,Int) -> [(Int,Int)] -> [(Int,Int)]
add x y = x:y

visit :: (Int,Int) -> [(Int,Int)] -> [[Int]] -> Int -> [(Int,Int)]
visit (i,j) vis mat cond | move_right (i,j) mat cond && not (visited (i,j+1) vis) = visit (i,j+1) (add (i,j+1) vis) mat cond
               | move_down (i,j) mat cond && not (visited (i+1,j) vis) = visit (i+1,j) (add (i+1,j) vis) mat cond
               | move_left (i,j) mat cond && not (visited (i,j-1) vis) = visit (i,j-1) (add (i,j-1) vis) mat cond
               | move_up (i,j) mat cond && not (visited (i-1,j) vis) = visit (i-1,j) (add (i-1,j) vis) mat cond
               | otherwise = vis

I have to traverse a matrix and say how many "characteristic areas" of each type it has.

A characteristic area is defined as a zone where elements of value n or >n are adjacent.

For example, given the matrix:

0 1 2 2
0 1 1 2
0 3 0 0

There's a single characteristic area of type 1 which is equal to the original matrix:

0 1 2 2
0 1 1 2
0 3 0 0

There are two characteristic areas of type 2:

0 0 2 2    0 0 0 0
0 0 0 2    0 0 0 0
0 0 0 0    0 3 0 0

And one characteristic area of type 3:

0 0 0 0 
0 0 0 0
0 3 0 0 

So, for the function call:

countAreas [[0,1,2,2],[0,1,1,2],[0,3,0,0]] 

The result should be

[1,2,1]

I haven't defined countAreas yet, I'm stuck with my visit function when it has no more possible squares in which to move it gets stuck and doesn't make the proper recursive call. I'm new to functional programming and I'm still scratching my head about how to implement a backtracking algorithm here. Take a look at my code, what can I do to change it?

move_right :: (Int,Int) -> [[Int]] -> Int -> Bool
move_right (i,j) mat cond | (j + 1) < number_of_columns mat && consult (i,j+1) mat /= cond = True
               | otherwise = False

move_left :: (Int,Int) -> [[Int]] -> Int -> Bool
move_left (i,j) mat cond | (j - 1) >= 0 && consult (i,j-1) mat /= cond = True
               | otherwise = False

move_up :: (Int,Int) -> [[Int]] -> Int -> Bool
move_up (i,j) mat cond | (i - 1) >= 0 && consult (i-1,j) mat /= cond = True
               | otherwise = False

move_down :: (Int,Int) -> [[Int]] -> Int -> Bool
move_down (i,j) mat cond | (i + 1) < number_of_rows mat && consult (i+1,j) mat /= cond = True
               | otherwise = False

imp :: (Int,Int) -> Int
imp (i,j) = i


number_of_rows :: [[Int]] -> Int
number_of_rows i = length i

number_of_columns :: [[Int]] -> Int
number_of_columns (x:xs) =  length x

consult :: (Int,Int) -> [[Int]] -> Int
consult (i,j) l = (l !! i) !! j

visited :: (Int,Int) -> [(Int,Int)] -> Bool
visited x y = elem x y

add :: (Int,Int) -> [(Int,Int)] -> [(Int,Int)]
add x y = x:y

visit :: (Int,Int) -> [(Int,Int)] -> [[Int]] -> Int -> [(Int,Int)]
visit (i,j) vis mat cond | move_right (i,j) mat cond && not (visited (i,j+1) vis) = visit (i,j+1) (add (i,j+1) vis) mat cond
               | move_down (i,j) mat cond && not (visited (i+1,j) vis) = visit (i+1,j) (add (i+1,j) vis) mat cond
               | move_left (i,j) mat cond && not (visited (i,j-1) vis) = visit (i,j-1) (add (i,j-1) vis) mat cond
               | move_up (i,j) mat cond && not (visited (i-1,j) vis) = visit (i-1,j) (add (i-1,j) vis) mat cond
               | otherwise = vis

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

坐在坟头思考人生 2024-09-04 05:06:07

在这里使用数组类型而不是列表列表会对您有帮助吗?你仍然在进行函数式编程,只是使用了更好的数据结构。

如果适合您,您可以创建一个Array (Int,Int) Int。请参阅:

http:// hackage.haskell.org/packages/archive/array/0.2.0.0/doc/html/Data-Array-IArray.html

import Data.Array

...获取库。

Would it help you to use an Array type here, rather than a list-of-lists? You are still doing functional programming, just using a better data structure.

You can create an Array (Int,Int) Int if that works for you. See:

http://hackage.haskell.org/packages/archive/array/0.2.0.0/doc/html/Data-Array-IArray.html

import Data.Array

...to get the library.

柠檬色的秋千 2024-09-04 05:06:07

我认为回溯实际上并不是您所追求的。在我看来,您的目标是让您的 visit 函数建立一个访问列表,因为它从满足某些条件的某个点找到矩阵中的所有连接元素。你需要考虑的是什么算法可以实现这一点。不要担心用函数式或命令式编程来表达它(还)。试想一下:该算法本质上是递归的吗?迭代?如果你在计算过程中停止它,你怎么知道算法下一步要做什么?您需要什么数据?

我现在不担心代码中的各种改进(使用 Array 或消除 if 语句等),您可以稍后再进行处理。您缺少的关键是可行的算法。

I don't think backtracking is actually what you are after. Seems to me that your aim is to have your visit function build up a visited list as it finds all the connected elements in the matrix from some point that meet some condition. What you need to think about is what algorithm will achieve this. Don't worry about expressing it in terms of functional or imperative programming (yet). Just think: Is the algorithm recursive in nature? Iterative? If you stopped it in the middle of computing, how would you know what to do next in the algorithm? What data would you need?

I wouldn't worry about various improvements in the code for now (using Array or eliminating the if statements, etc...), you can get to those later. The key you are missing is a viable algorithm.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文