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.
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!
To give overall context, I have a 2d grid of size N (the size is known but can vary and is always a square i.e x axis = y axis) and M points on the grid that I'm trying to find (the amount of points is known but their locations are not). I want to iterate through every possible solution for said grid. Also the points don't have to be in a specific order, so
[(1,1),(1,2)]
is the same as
[(1,2),(1,1)]
So for example assume the grid was a 2x2 and their was 2 points. Then all the possible solutions would be
[(1,1),(1,2)]
[(1,1),(2,1)]
[(1,1),(2,2)]
[(1,2),(2,1)]
...and so on...
I'm trying to create a function that will output these to me.
I know the function below can create me a full grid, but I don't know how to use this to generate all the possible point locaitons. And whether this grid is even useful in the first place
createGrid :: Int -> [(Int, Int)]
createGrid num = [ (x,y) | x <- [1..num], y <- [1..num]]
Any help would be appreciated
It sounds like you just want a list of the unique ways to choose M items from a list (grid) of N*M items. You already know how to generate this list, so all you need is the ways to choose K items from a list. This is a well-trodden path; for example, see Function to generate the unique combinations of a list in Haskell.
In general it is useful to try to do this sort of splitting up: break your program into smaller pieces and see how many of them are easy to solve. If you try to do everything all at once in one function, you end up repeating work and often wind up with a function that is difficult to read.
For a given grid, if m is 0, then we return the empty list, when m is greater than 0, then we yield a point and recurse on the rest of the list, so:
possibleGrids :: Int -> Int -> [[(Int, Int)]]
possibleGrids n mm = go mm 1 0
where go 0 _ _ = [[]]
go m i j = [(x, y) : tl | x <- [i .. n], y <- [1 .. n], x > i || y > j, tl <- go (m-1) x y]
The first parameter here is n, the size of the grid. The second one is m, the number of points to mark. For a 2×2 grid, this gives us:
ghci> possibleGrids 2 0
[[]]
ghci> possibleGrids 2 1
[[(1,1)],[(1,2)],[(2,1)],[(2,2)]]
ghci> possibleGrids 2 2
[[(1,1),(1,2)],[(1,1),(2,1)],[(1,1),(2,2)],[(1,2),(2,1)],[(1,2),(2,2)],[(2,1),(2,2)]]
The code uses symmetry breaking, so it will not mark twice (or more) the same point, nor will it provide the list of points in a different order.
The following definitions represent a shape composed of coloured squares at specific coordinates on a grid:
type AltShape = [Point]
data Point = P Colour (Int,Int) deriving Eq
data Colour = Black | Red | Green | Blue deriving Eq
I should asume that coordinates always are positive and the coordinate (0,0) refers to the top left square of the picture, and the y-coordinates grow downwards
A Red L-shape could be represented by
lShape = [P Red (0,0), P Red (0,1), P Red (0,2), P Red (1,2)]
A different way to represent such shapes is as a list-of-lists, one list for each row:
type Shape = [Row]
type Row = [Square]
type Square = Maybe Colour
For example, the red L-shape above would be represented by the following value of type Shape:
lShape2 = [[x,o]
,[x,o]
,[x,x]] where x = Just Red
o = Nothing
My task is to define a function toShape :: AltShape -> Shape that converts from a AltShape to an Shape. I had another task to define a function fromShape :: Shape -> AltShape but where data Shape = S [Row]. I found that rather simple and wrote it like this:
fromShape :: Shape -> AltShape
fromShape (S rows) = [ P c (x,y) | (y,row) <- index rows, (x,Just c) <- index row]
where index = zip [0..]
However, I am having more trouble with this one. I started by creating the function
colourAndCoords :: Point -> (Colour,(Int,Int))
colourAndCoords ( P c (x,y) ) = (c,(x,y))
I then created a function
coords :: [Point] -> [(Int,Int)]
coords ps = map snd (map colourAndCoords ps)
My thought was to compare this list to another list of all possible coordinations and where there was a match add the right colour, and where there wasn't I would add Nothing. However, my teacher said I was making it too complicated and that I should think of another solution. But I am having a hard time thinking of one. So I guess my question is what is the easier way? I am not asking for a solution, just a nudge in the right direction.
Thanks a ton for anyone taking the time to read this and respond!!
If I come up with a solution I will come back and update this thread.
If you want an efficient solution, the accumArray function does almost exactly what you need (after computing the appropriate bounds).
λ> arr = accumArray (const Just) Nothing ((0, 0), (2, 1)) [((y, x), c) | P c (x, y) <- lShape]
λ> arr
array ((0,0),(2,1)) [((0,0),Just Red),((0,1),Nothing),((1,0),Just Red),((1,1),Nothing),((2,0),Just Red),((2,1),Just Red)]
λ> elems arr
[Just Red,Nothing,Just Red,Nothing,Just Red,Just Red]
Now the problem is reduced to split elements into groups.
λ> chunksOf 2 (elems arr)
[[Just Red,Nothing],[Just Red,Nothing],[Just Red,Just Red]]
For a real application you’d probably want to leave it as an array, since array indexing is fast (O(1)) and list indexing is slow (O(n)).
If efficiency is no concern, you could consider this approach:
Figure out the largest x coordinate (call it w), and the largest y coordinate (call it h).
Create a rectangular list of lists, length w by h, with a list comprehension or similar. At each position, look through the entire list of points for one with a matching position, and use its color if you find one (Nothing otherwise).
If efficiency is a concern, you could consider a more complicated approach:
Turn your [AltShape] into an IntMap (IntMap Colour), e.g. using this technique, which maps y and x to colour.
Iterate over occupied rows with toAscList; within each, iterate over occupied columns with toAscList. You will need to manually pad unoccupied rows with [] and unoccupied columns with Nothing.
An advantage (or possibly disadvantage, depending on your goals!) of the second approach is that it will naturally produce "ragged" Shapes which omit trailing Nothings.
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.
I have chosen to represent a graph in Haskell by a list of nodes (ex. n=[1,2,3,4]) and a list of pairs representing the edges (example m=[(1,2), (2,3)]). Now I have to see if the graph is strongly connected.
My main issue is how to find if there is a way between 2 nodes in the graph. I wrote something like that:
-- sees if 2 nodes are adjacent
adjacent x y [] = False
adjacent x y (mu:m) =
if(x== (fst mu) && y==(snd mu)) then True
else adjacent x y m
-- the successor of a node, ex for the edge (1,2) the succ of 1 is 2
suc x [] = 0
suc x (l:list) =
if(x==(fst l)) then snd l
else suc x list
-- my main function
way 0 y list = False
way x y (mu:m)
| x==y = True
| (adjacent x y (mu:m)) == True = True
| otherwise =
if ((way (suc x (mu:m)) y (mu:m))==False) then way (suc x m) y m
else True
It works when I have nodes of degree 1, but for the nodes with a greater degree it doesn't always work. Can you give me a clue about it?
Here are some questions to ask yourself:
Should adjacent 3 2 [(1,2),(2,3)] be True?
How many successors to 1 are there in the graph [(1,2),(2,3),(1,4),(3,4)]
Why does, or doesn't, way need to have both a x==y case and an adjacent x y ... case?
In the recursion step of way does the == False test really tell you something that lets you recurse on the smaller graph of m?
In general, you haven't written type signatures for your top level functions. It is usually very instructive to do so, and will communicate your design more clearly:
type Vertex = Int
type Edge = (Vertex, Vertex)
type Graph = [Edge]
adjacent :: Vertex -> Vertex -> Graph -> Bool
suc :: Vertex -> Graph -> Vertex
way :: Vertex -> Vertex -> Graph -> Bool
Think about if those types make sense, and if they decompose your problem as you would expect, just thinking about graphs in general.
Is your aim really the way function, or is it to determine if the graph is connected? You might be presupposing too much about the way in which you can determine if the graph is connected.
Lastly, a small part about Haskell syntax: Like most other languages, function application binds very tightly, tighter than == and && operators. Unlike most other languages, function application doesn't use parenthesis. Hence, adjacent can be recoded as:
adjacent x y [] = False
adjacent x y (mu:m) =
if x == fst mu && y == snd mu then True
else adjacent x y m
Which in turn could be simplified to:
adjacent x y [] = False
adjacent x y (mu:m) = (x == fst mu && y == snd mu) || adjacent x y m
You have two errors of understanding:
m, your list of edges is static throughout the entire search. Don't eat it up as you recur in way.
Each vertex can have more than one edge leaving it. You want to know whether any of the neighbours of x has a way to y. To find the neighbours you first have to filter the list of edges to find only the edges leaving x.
You also need to build up a list of nodes you've already visited on your quest to find a connection. If you end up on a node you've already seen, then that particular path has failed.
Some hints to make your code a lot shorter: for adjacent, try elem.
For succ, try Data.Maybe.fromMaybe and lookup.