开发者

A tricky haskell problem

开发者 https://www.devze.com 2023-03-18 18:25 出处:网络
Ihad this task for my Haskell class, but I find it quite difficult. If you could help a bit. You are given a maze

I had this task for my Haskell class, but I find it quite difficult. If you could help a bit. You are given a maze

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

and you can walk through spaces only . You start from (0,1) and the function have to return a string with directions to escape the maze which are :

f - forward
r- turn right
l - turn left 

And if you have a choice you always prefer right to forward, and forward to left. For the current example the answer is ffllffrffrfflf

Thanks in advance

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)

                  ri开发者_开发百科ghtPossible :: 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


The first thing I see is, that you have a precedence issue. The expression (maze !! x)!! y-1 is parsed as ((maze !! x)!! y)-1 whereas you want it parsed as (maze !! x)!! (y-1). Add braces to solve this issue.

After adding this, your code compiles, although your algorithm seems to be broken. Maybe somebody else can help you.

Some coding advises:

  • Add type signatures at appropriate places to ease debugging. (If the type fails, the compiler will more likely show the error in the right place)
  • Use pattern matching instead of extra case statements. Instead of

    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)
    

    write

    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)
    
  • Write your own data types instead of relying on characters. For instance, you could create an own datatype for directions:

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


I agree with FUZxxl. If you make a new data type, you can do stuff like

Data types

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

Using the data types in a readable and efficient way

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)

Again here. Also, using well-named functions instead of just r, which doesn't mean much.

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   == ' '

Hope this helps you understand the language a little.

edit: changed data Point to type Point

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号