一个棘手的haskell问题

时间:2011-07-08 11:47:55

标签: haskell functional-programming

我的Haskell课程有这个任务,但我觉得很难。如果你能帮助一点。 你有一个迷宫

maze = ["x xxx",
        "x   x",
        "x x x",
        "x x  ",
        "xxxxx"]

你只能走过空间。你从(0,1)开始,函数必须返回一个字符串,其中包含避开迷宫的方向:

f - forward
r- turn right
l - turn left 

如果你有一个选择,你总是喜欢向前,向前向左。  对于当前示例,答案为ffllffrffrfflf

提前致谢

data Direction = N | W | S | E deriving (Show,Eq)

maze = ["x xxx",
        "x   x",
        "x x x",
        "x x  ",
        "xxxxx"]

d = 's'
pos = (0,1)

fpath d pos | fst pos == (length maze - 1) = ""
            | snd  (pos) ==0 || (snd ( pos ) == ((length (maze!!0))-1)) = ""
            | rightPossible d pos = "r" ++ ( fpath (rightRotate d) pos )
            | forwardPossible d  pos = "f" ++ ( fpath d (nstep d pos) )
            | True = "l" ++ fpath (leftRotate d) pos
            where nstep :: Direction -> (Int, Int) -> (Int, Int) {-next step-}
                  nstep N (x,y) = (x-1,y)
                  nstep W  (x,y) = (x,y-1) 
                  nstep S (x,y) = (x+1,y) 
                  nstep E  (x,y) = (x,y+1)

                  rightPossible :: Direction -> (Int, Int) -> Bool 
                  rightPossible N (x,y)= (maze !! x)!! (y+1) == ' '
                  rightPossible W (x,y)= (maze !! (x-1))!! y   == ' '              
                  rightPossible S (x,y)= (maze !! x)!! (y-1) == ' '                   
                  rightPossible E (x,y)= (maze !! (x+1))!! y   == ' '

                  rightRotate :: Direction -> Direction 
                  rightRotate N = E
                  rightRotate W = N
                  rightRotate S = W
                  rightRotate E = S

                  forwardPossible :: Direction -> (Int, Int) -> Bool 
                  forwardPossible N (x,y)= ((maze !! (x-1))!! y) == ' ' 
                  forwardPossible W (x,y)= ((maze !! x)!! (y-1)) == ' '
                  forwardPossible S (x,y)= ((maze !! (x+1))!! y) == ' '
                  forwardPossible E (x,y)= ((maze !! x)!! (y+1)) == ' '

                  leftRotate :: Direction -> Direction
                  leftRotate N = W
                  leftRotate W = S
                  leftRotate S = E
                  leftRotate E = N

2 个答案:

答案 0 :(得分:7)

我看到的第一件事是,你有一个优先问题。表达式(maze !! x)!! y-1被解析为((maze !! x)!! y)-1,而您希望将其解析为(maze !! x)!! (y-1)。添加大括号来解决此问题。

添加此内容后,您的代码会编译,但您的算法似乎已被破坏。也许其他人可以帮助你。

一些编码建议:

  • 在适当的位置添加类型签名以简化调试。 (如果类型失败,编译器将更有可能在正确的位置显示错误)
  • 使用模式匹配而不是额外的case语句。而不是

    nstep d (x,y)   {-next step-}
                    | d == 'n' = (x-1,y)
                    | d == 'w' = (x,y-1)
                    | d == 's' = (x+1,y)
                    | d == 'e' = (x,y+1)
    

    nstep 'n' (x,y) = (x-1,y)
    nstep 'w' (x,y) = (x,y-1)
    nstep 's' (x,y) = (x+1,y)
    nstep 'e' (x,y) = (x,y+1)
    
  • 编写您自己的data类型,而不是依赖于字符。例如,您可以为方向创建自己的数据类型:

    data Direction = N | W | S | E deriving (Show,Eq)
    

答案 1 :(得分:2)

我同意FUZxxl。如果您创建新数据类型,则可以执行

之类的操作

数据类型

data Direction = North | West | South | East deriving (Show,Eq) 
type Point = (Int, Int)

以可读且有效的方式使用数据类型

nstep :: Direction -> Point -> Point
nstep North (x,y) = (x-1,y)
nstep West  (x,y) = (x,y-1) 
nstep South (x,y) = (x+1,y) 
nstep East  (x,y) = (x,y+1)

再来一次。另外,使用命名良好的函数而不仅仅是r,这并不意味着什么。

rightPossible :: Direction -> Point -> Bool
rightPossible North = (maze !! x)!! (y-1) == ' '
rightPossible West  = (maze !! x+1)!! y   == ' '              
rightPossible South = (maze !! x)!! (y+1) == ' '                   
rightPossible East  = (maze !! x-1)!! y   == ' '
     

希望这有助于您理解语言。

修改:将data Point更改为type Point