I am trying to implement a maze solver based on the algorithm described in the below link in Haskell.
http://www.cs.bu.edu/teaching/alg/maze/
I am pretty new to haskell and functional programming, and I basically try to code the algorithm as described in the link, I tried to go through many other resources online but I am stuck in the part where the walking stops when the goal (It doesn't stop, it back tracks to the origin) is reached, and I am unable to unmark the bad positions in the maze.
The maze looks like
.########
.......#.
#.####..#
#.#######
...#.G...
##...####
#..######
my code is as follows
findPath :: Int->Int->Maze->(Bool,Maze)
findPath x y maze
| not (isSafe maze x y) = (False,maze)
| isChar maze x y 'G' = trace ("Solution: "++ show maze)(True,maze)
| isChar maze x y '#' = (False,maze)
| isChar maze x y '!' = (False,maze)
| fst walkNorth = (True,markedList)
| fst walkEast = (True,markedList)
| fst walkSouth = (True,markedList)
| fst walkWest = (True,markedList)
| otherwise = (False,unMarkedList)
where markedList = replaceCharInMaze maze x y '+'
unMarkedList = replaceCharInMaze maze x y '!'
walkNorth = findPath x (y-1) markedList
walkEast = findPath (x+1) y markedList
walkSouth = findPath x (y+1) markedList
walkWest = findPath (x-1) y markedList
the isSafe function just checks for bounds, the isChar is just character matching at a given x,y position and the replaceCharInMaze function replaces the character at the x,y position with the supplied character.
isSafe :: [String]->Int->Int->Bool
isSafe list x y
| y >= 0 && y < length (head list) && x >= 0 && x < length list && (isChar list xy '.' || isChar list x y 'G') = True
| otherwise = False
So, I have two problems
I am not able to persist the un-marking being done at the Otherwise case to the next recursion call, how do I go about persisting the state of the maze, so that even the un-marked state be part of the solution?
Then as the algorithm proceeds, It walks till the goal and comes back to the start, how to stop this from happening?
As I am new to Haskell and algorithms, I looked in to topics such has state monads, which seemed to be like the solution, but I am not quite sure about proceeding with it, I also tried looking into other stack overflow posts, but couldn't find anything that would help me.
The output for a maze obtained during the trace statement is as follows
+++#..###..#.
.#+++#+++.##.
####+#+#+#-##
...#+++#+#...
.#.####++.##.
.#G+++++#....
.############
....####.....
But it doesn't stop there it comes backtracks to the origin and prints the output as
+..#..###..#.
.#...#....##.
####.#.#.#.##
...#...#.#...
.#.####...##.
.#G.....#....
.############
....####.....
Here's what happens when you run your program with your example. The first four guards are clearly False, so not much happens up to that point. It evaluates walkNorth by recursing once, in order to find that fst walkNorth is also False. Then it evaluates walkEast, which takes a while, since eventually that leads to the goal. It finds that fst walkEast is True, so it returns (True,markedList). It's important to realise that the markedList in the returned pair has only been 'marked' once (hence there is a single '+' in your output). Lots of 'markings' have been happening on the way to the goal, but those aren't visible from where the program returns its output. Each time you pass a markedList into one of the walkXXX functions, you're essentially creating a new list, with an additional marking, which can only be seen in the function call you're passing it into. What you actually want is the maze with the markings at the point where it's been solved. At the end of the day, the walkXXX functions either return (False,maze) when walking in the XXX direction doesn't lead to the goal (because the 1st or 3rd guard evaluates to True), or (True,maze) if it does lead to the goal (the 2nd guard evaluates to True), in which case, maze at that point will have all the correct markings. So instead of returning markedList for the fst walkXXX cases, return snd walkXXX. i.e.
| fst walkNorth = (True,snd walkNorth)
| walkEast = (True,snd walkEast)
| walkSouth = (True,snd walkSouth)
| walkWest = (True,snd walkWest)
Your first question is a bit complicated. I think what you want is to change your walkXXX definitions to something very roughly like this:
walkNorth = findPath x (y-1) markedList
walkEast = findPath (x+1) y (replaceCharInMaze markedList x (y-1))
walkSouth = findPath x (y+1) (replaceCharInMaze (replaceCharInMaze markedList x (y-1)) (x+1) y)
and I'll let you fill in the last one. If you are walking east, you know that you've tried walking north and not found the goal, so you can unmark it, and so on. (This isn't quite going to work, at the very least because it will probably try to replace walls and characters outside of the maze, but the idea is there.)
You seem to be not yet accustomed to Haskell's lack of mutable state and frequent recursion. Some other things (I'm not certain about these): I don't think your otherwise case ever runs, and it doesn't really do anything -- try taking it out and see what happens; I also don't think the Trues in your (True,markedList) pairs ever have any effect -- try changing them to False.
Related
I am trying to write a basic function in Haskell as shown below. My aim is provide the code to square only even numbers while odd numbers will stay same. Would you please help me regarding this issue.
square:: Int -> Int
square x = [ x*x | x <- [1..10], mod x 2 == 0 ]
regards
You are here filtering. You should determine if the number is even or odd and then square the number or not, this can be done in the yield part of the list comprehension.
But the type signature hints that you do not need to construct a list at all. You simply check if the parameter x is even, and if that is the case return x*x, otherwise return x:
square:: Int -> Int
square x = if even x then x*x else x
or through guards:
square:: Int -> Int
square x
| even x = x*x
| otherwise = x
One quite straightforward answer to your question is, you can inline a if statment directly into your list comprehension like so:
[ if even x then x * x else x | x <- [1..10] ]
This is possible since if is an expression in Haskell, meaning it evaluates to a value, so things like this are valid:
let _ = if 1 + 1 == 2 then "foo" else "bar"
It can also be good to look at this problem in another direction. List comprehensions can be quite nice, but sticking an if within it can get pretty messy. Willem's solution of factoring out the method is great, so let's look at other ways we can leverage it with your code:
-- This is the function we're trying to implement
evenSquares :: [Int] -> [Int]
-- We could start by noting that `if` expression has a nice name,
-- which can be factored out to make things look cleaner
-- Same implementation as Willem's
evenSquares xs = [ squareIfEven x | x <- xs ] where
squareIfEven x = if even x then x * x else x
-- List comprehensions are nice, but there's also another name for what we're doing,
-- which is mapping over a collection of values and applying a method
evenSquares xs = map squareIfEven xs where
squareIfEven x = if even x then x * x else x
-- Note how the `xs` is an argument to `evenSquares` and also the last argument to `map`
-- We can actually get rid of `xs` entirely via this rule:
-- https://wiki.haskell.org/Eta_conversion
evenSquares = map squareIfeven where
squareIfEven x = if even x then x * x else x
-- This one's a bit of a stretch, but conceptually quite useful
-- The idea of 'apply a method if a condition is true' can be expressed as a method
-- which takes a predicate method, a transformation method, and a value
-- We can leverage this ourselves to make `squareIfEven` more generic too
evenSquares = map (if' even square id) where
square x = x * x
if' pred fst snd x = if pred x then fst x else snd x
-- There's a bunch more solutions we can try, including things like `do` notation
-- This is just an idea of how you could look at your problem
-- Pick one which makes your solution clear and concise!
Exercise
Hello every one!
I have been struggling to get this function working in the specific way they want.
I tried everything and the only output I could make was without the starting and ending point, eg: [((a,b),(b,c))]
Could someone please give me some help? I am stucked...
Update: type Point = (Float, Float)
Well since you got it working without the starting/ending point. An easy way to complete would be use your function but add the starting/ending point in the list in an inner function. So your interface is still same.
Another way using recursion, pattern matching and guards is:
-- assuming the inputs to be int as definition of point not given
solve x z [] = [(x,z)]
solve x z (y:ys)
| x == 0 = solve y z ys -- x ==0 to be replaced by null/empty condition on x
| null ys && z == 0 = [] -- z ==0 to be replaced by null/empty condition on z
| null ys = [(y, z)]
| otherwise = (x,y) : solve y z ys
Added a base case when the list is empty or start/end points not valid based on darthfennec comment.
Say I had a Haskell algorithm which, through recursion, progressed through a Cartesian plane where each x/y coordinate had a specific value.
Position (0,0) is known, each other can be calculated by progressing back to the origin.
For example, to look at (0,3) I need to look at (-1,2), (0,2) and (1,2), which have to look in turn at (-2,1),(-1,1),(0,1) and (-1,1),(0,1),(1,1) and (0,1),(1,1),(2,1) respectively.
In order to avoid for (-1,1) and (0,1) to be calculated twice, is there any way I can create a data structure so that the algorithm can first look to see if a certain position ahs been calculated already and, if not, only then proceeds to calculating it?
Thanks :)
It sounds like memoization as m09 and cdk suggest might be what you're looking for. But if you want an algorithm that returns an array of positions, then simple boxed arrays (meaning they hold lazy values) and some knot tying can give you a nice declarative solution (sorry for the ugly code)
import Data.Array
-- for positive u
plane :: Int -> Array (Int,Int) Int
plane u = let knownOrigin = ((0,0) , 0)
l = negate u
otherCoords = [ (x,y) | let cs = [l .. u]
, x <- cs , y <- cs
, (x,y) /= (0,0)
]
a = array ((l,l),(u,u)) $
knownOrigin : map solution otherCoords
-- example recursive thing, referenceing lazy values in 'a':
solution c#(x,y) = let x' | x <0 = x+1
| x >0 = x-1
| x==0 = 0
y' | y <0 = y+1
| y >0 = y-1
| y==0 = 0
in (c , a ! (x',y') + 1)
in a
You could also use a Map or vector, or any other lazy structure that works best for your problem.
I was trying to implement a Haskell function that takes as input an array of integers A
and produces another array B = [A[0], A[0]+A[1], A[0]+A[1]+A[2] ,... ]. I know that scanl from Data.List can be used for this with the function (+). I wrote the second implementation
(which performs faster) after seeing the source code of scanl. I want to know why the first implementation is slower compared to the second one, despite being tail-recursive?
-- This function works slow.
ps s x [] = x
ps s x y = ps s' x' y'
where
s' = s + head y
x' = x ++ [s']
y' = tail y
-- This function works fast.
ps' s [] = []
ps' s y = [s'] ++ (ps' s' y')
where
s' = s + head y
y' = tail y
Some details about the above code:
Implementation 1 : It should be called as
ps 0 [] a
where 'a' is your array.
Implementation 2: It should be called as
ps' 0 a
where 'a' is your array.
You are changing the way that ++ associates. In your first function you are computing ((([a0] ++ [a1]) ++ [a2]) ++ ...) whereas in the second function you are computing [a0] ++ ([a1] ++ ([a2] ++ ..)). Appending a few elements to the start of the list is O(1), whereas appending a few elements to the end of a list is O(n) in the length of the list. This leads to a linear versus quadratic algorithm overall.
You can fix the first example by building the list up in reverse order, and then reversing again at the end, or by using something like dlist. However the second will still be better for most purposes. While tail calls do exist and can be important in Haskell, if you are familiar with a strict functional language like Scheme or ML your intuition about how and when to use them is completely wrong.
The second example is better, in large part, because it's incremental; it immediately starts returning data that the consumer might be interested in. If you just fixed the first example using the double-reverse or dlist tricks, your function will traverse the entire list before it returns anything at all.
I would like to mention that your function can be more easily expressed as
drop 1 . scanl (+) 0
Usually, it is a good idea to use predefined combinators like scanl in favour of writing your own recursion schemes; it improves readability and makes it less likely that you needlessly squander performance.
However, in this case, both my scanl version and your original ps and ps' can sometimes lead to stack overflows due to lazy evaluation: Haskell does not necessarily immediately evaluate the additions (depends on strictness analysis).
One case where you can see this is if you do last (ps' 0 [1..100000000]). That leads to a stack overflow. You can solve that problem by forcing Haskell to evaluate the additions immediately, for instance by defining your own, strict scanl:
myscanl :: (b -> a -> b) -> b -> [a] -> [b]
myscanl f q [] = []
myscanl f q (x:xs) = q `seq` let q' = f q x in q' : myscanl f q' xs
ps' = myscanl (+) 0
Then, calling last (ps' [1..100000000]) works.
I'm trying to implement a function using list comprehensions that copies an element an amount of times as specified. I'm really stuck on this but I'm trying to
for example
copy 2 'a' = aa
This is what I have so far:
copy2 :: Int->a->[a]
copy2 x y = func1 y [b|b<-[1..x]]
where func1 is somehow mapping y to every element of x
It's not a lot but I'm really clueless on this one sorry guys.
Even though an answer has been accepted, I want to point out that you said something profoundly important in your very question, which could have led you to an answer.
You said:
copy2 :: Int->a->[a]
copy2 x y = func1 y [b|b<-[1..x]]
where func1 is somehow mapping y to every element of x
If we clean up the phrasing a bit -- I am sure it's what you meant -- we actually want something that maps every element of the list produced by the comprehension to the constant value y.
Well, making a function that produces a value y for a single x is simple:
const y x = y
In fact, the function is useful enough that it exists in the Prelude already!
Now we just need to map over every element of the list.
copy2 x y = map (const y) [b | b <- [1..x]]
or a bit simplified, to really show how close we are to your original description, (even though I know you needed the list comprehension)
copy2 x y = map (\x -> y) [1..x]
"map x to y for every x."
So you see, you had it all along.
copy2 qty item = [item|_<-[1..qty]]