List Grid Elements - list

I have managed to make some progress in this part of my assignment but have attached part of the code below that I have made:
module Grid where
data State = On | Off deriving (Eq, Show)
next :: State -> State
next On = Off
next Off = On
type Row = [State]
type Grid = [[State]]
type Point = (Int,Int)
initialRow :: Int -> Row
initialRow w = replicate w Off
updateRow :: Row -> Int -> Row
updateRow (r:rs) x
| x==0 = next r:rs
| otherwise = r : (updateRow rs (x-1))
update :: Grid -> Point -> Grid
update [[]] (x,y) = [[]]
update [(g:gs)] (x,y) = [(updateRow (g:gs) x)]
As shown in the last line just above, I have managed to get update to work for when x = any Int as shown below (with the xth element inverted) - ghci.
*Grid> update [[Off,Off,Off,Off]] (2,0)
[[Off,Off,On,Off]]
*Grid>
It all comes unstuck however when I try working with multiple lists such as this, or select a certain list within the list to update the xth element:
*Grid> update [[Off,Off,Off,Off],[Off,Off,Off,Off]] (2,0)
*** Exception: Grid.hs:(24,0)-(25,47): Non-exhaustive patterns in function update
I can't seem to 'genralise' a formula in this function.
I also MUST follow THIS type convention:
updateRow :: Grid -> Point -> Grid
Basically, what I would like to do is update from something like this...
[[Off,Off,Off,Off],
[Off,Off,Off,Off],
[Off,Off,Off,Off],
[Off,Off Off,Off]]
to this:
[[Off,Off,Off,Off],
[Off,Off,**On**,Off],
[Off,Off,Off,Off],
[Off,Off Off,Off]]
where 'x' is the value of the element and 'y' is the value of the list within the list IYGWIM.
Thanks in advance.

update :: Grid -> Point -> Grid
update [[]] (x,y) = [[]]
This checks for a list that contains the empty list.
update [(g:gs)] (x,y) = [(updateRow (g:gs) x)]
This checks for a list that contains one list, the latter containing at least one element (bound to the variable g).
You want to check for a list that contains multiple lists.
The pattern should look like:
update :: Grid -> Point -> Grid
update [[]] (x, y) = [[]]
update (row:rows) (x, 0) = updateRow row x : rows
update (row:rows) (x,y) = -- I'll let you fill this, notice the 0 on the previous line
Remember a Grid is just a list of Rows.
The second line now means "if you want to update the 0th line of this grid, then update the first row", the last line should mean "if you want to update the yth line of this grid, then leave the first one as is, and recursively update the rest of the rows" (of course, y must be changed accordingly in the recursive call).

Here is the solution. After some thought, I came out with the following and filled the final line of the above 'pattern':
...
update (g:gs) (x,y) = g : update gs (x,(y-1))

Related

How to create a list of object by using some sort of filter with a predicate

I'm iterating through a list of nodes in order to create edges between them, however I want to check if the edge between two nodes are not crossing a 'dangerous' place, so I created a function that will work as a predicate to insure I do not create a such an edge. However I don't see how I would be able to properly build my list of edges.
The types manipulated are :
type position = float * float
type node = position
type edge = position * position * float
I have written this, it doesn't work, but this is what I had in mind, I don't know what I could use in OCaml to make it work
let create_edges nodes_list =
let rec create_edges_aux nodes =
match nodes with
| [] -> []
| x::[] -> (x,x,0.) :: []
| x::tl -> List.map (fun x2 -> if (is_safe_edge x x2) then (x,x2,extract_float(dist2 x x2))) tl # create_edges_aux tl
in create_edges_aux nodes_list
The problem is here obviously List.map (fun x2 -> if (is_safe_edge x x2) then (x,x2,extract_float(dist2 x x2))) tl # create_edges_aux tl
The function works perfectly if I do this : List.map (fun x2 -> (x, x2, (extract_float (dist2 x x2)))) tl # create_edges_aux tl but the unsafe edges aren't filtered ...
In the end my problem is that I'm not able to create a list of edges that satisfy the predicate function I coded and the goal is to be able to make that list.
If you have any ideas or solution, thanks.
What you want to do is filtering of the values, which cannot be done with List.map as it always take all the values.
One first option is to first filter the edges with List.filter then map.
If you use OCaml 4.08 or later you can use the dedicated List.filter_map function.
If you are using an older version of OCaml you can also use List.fold_left function to do the mapping and filtering.
In short, List.map can only modify all the values, if you need to filter out some values, it's not the function you need.
It looks to me like you just need an else part in your if.
A code pattern that you see a lot in OCaml is something like this:
let f x =
let x' = if x > 100 then 100 else x in
g x'
When using an if in a functional context, the if always needs an else, because the expression must have a value in both cases. Quite often the else value is the original (unmodified) input value.

Filter tuples in list of lists [Haskell]

I have a list of lists of tuples:
let list = [[(1,(2,2)),(0,(3,2)),(0,(4,2))],[(0,(2,3)),(0,(3,3)),(0,(4,3))],[(0,(2,4)),(0,(3,4)),(0,(4,4))]]
I would like to filter them by the first value of each tuple.
That's what I tried...
compute :: Matrix -> Coordinates -> Matrix
compute m (x,y) = filter (\(a,(_,_)) -> a /= 1) [row | row <- list]
with
type Matrix = [[Int]]
type Coordinates = (Int, Int)
That's the error I got:
ContiguousRegion.hs:20:36:
Couldn't match expected type ‘[Int]’
with actual type ‘(Integer, (t0, t1))’
In the pattern: (a, (_, _))
In the first argument of ‘filter’, namely
‘(\ (a, (_, _)) -> a /= 1)’
In the expression:
filter
(\ (a, (_, _)) -> a /= 1) [row | row <- checkAround m (x, y)]
ContiguousRegion.hs:20:58:
Couldn't match type ‘(Int, (Int, Int))’ with ‘Int’
Expected type: [Int]
Actual type: [(Int, (Int, Int))]
In the expression: row
In the second argument of ‘filter’, namely
‘[row | row <- checkAround m (x, y)]’
Failed, modules loaded: none.
How can I solve this?
Thanks!
Let's take a few steps to simplify the compute function and figure out the problem:
First of all, [row | row <- list] does nothing, it's equivalent to just list, so we can remove it and replace it with list, to make the function easier to read:
compute m (x,y) = filter (\(a,(_,_)) -> a /= 1) list
By the way, in your message I see that list isn't what the argument to filter is actually called. Instead, it's a checkAround m (x, y), so compute should probably look like this:
compute m (x,y) = filter (\(a,(_,_)) -> a /= 1) $ checkAround m (x, y)
The function you're passing to filter is unnecessarily complicated, we can replace it with \(a,_) -> a /= 1 or even (/=1) . fst to make it less noisy. Doing that gives us:
compute m (x,y) = filter ((/=1) . fst) list
I'd say it's now much easier to see the problem. Your list has the type [[(Int, (Int, Int))]], ie. it's a list of lists of tuples.
But the predicate your passing into filter is expecting a tuple, therefore filter itself is expecting a list of tuples.
This is an obvious type mismatch. How do we solve this? I don't know, that's up to you, but I guess you want to filter the inner list.
How do we do this? Well, we need to go through each of the inner lists, filter them and put the filtered ones in a new list. This is exactly what map (or fmap) can help us with. Let's map the filter we've constructed over list:
compute m (x,y) = map (filter ((/=1) . fst)) list
Unfortunately, the above still gives us a type error:
Couldn't match type ‘(Integer, (Integer, Integer))’ with ‘Int’
Expected type: [[Int]]
Actual type: [[(Integer, (Integer, Integer))]]
Well, why is that? We know that the Actual type is the type of list and the type of the filtered list as well, but what is the Expected type and why is it a [[Int]]?
The answer lies in your type signature, Matrix -> Coordinates -> Matrix. compute is supposed to produce a list of lists of Ints, but we're filtering something a bit different.
At this point I don't really know what you'd like to do, so I'll just end here, but I suspect you either need to change compute's type signature or you need to somehow merge m with the filtered results to create a new matrix.
Problem 1: Your definition of compute refers to list, but list is not a parameter.
Problem 2: If you change list to m your code is correct, but the type signature you gave is not correct.
Solution:
Change list to m, and don't give a type a signature:
compute m (x,y) = filter (\(a,(_,_)) -> a /= 1) [row | row <- m]
Now ask ghci what the type signature should be:
ghci> :t compute
compute
:: (Eq a, Num a) => [(a, (t2, t3))] -> (t, t1) -> [(a, (t2, t3))]
Now you see that that type Matrix should be defined as
type Matrix = [ (Int, (Int,Int) ]
Is this what you are trying to do?
type SparseMatrix = [Row]
type Row = [Element]
type Element = (Int, Coordinates)
type Coordinates = (Int, Int)
removeRowVal :: Row -> Int -> Row
removeRowVal row i = filter ((/= i).fst) row
removeSMVal :: SparseMatrix -> Int -> SparseMatrix
removeSMVal sm i = [removeRowVal row i | row <- sm]
Even if your list is not some kind of oddly structured sparse matrix representation, I think the final result is what you described.

Move items up in a list

How do you move items up in a list.
The input list would look like: let list = [1;2;3;4;5]
And the output list would look like one of the following:
[1;2;3;5;4]
.........>
[2;1;3;4;5]
...>......
Plot twist: I want to be able to move any index in the list up
From what I understand is this not something you aim to do with F# or functional languages, but it's a must have on my program.
I believe this can be done using both recursions and higher order(HO) functions, but since my knowlegde with HO's are very limited I tried to solve this using a recursion.
My approach to moving down an item in the list included a simple recursion with index and list as arguments like so:
let rec moveDownAt index list =
match index, list with
| -1, _ -> list
| 0, h1::h2::t -> h2::h1::t
| index, h::t -> h::moveDownAt (index - 1) t
| _, [] -> list
However, to move in the other direction I would need to reference the previous "head" and I assume I would have issues on the third match line | index, h::t -> h::moveDownAt (index - 1) t where i perform h:: since I add the head to the list (which would be the previous the next call if I add that argument).
Switching place on two elements means that one is moving up, and one is moving down.
Simple using the following code will solve the problem:
let moveUpAt index list = moveDownAt (index-1) list
This will displace the index making "index to be moved down" turn into "index to be moved up".
The basic idea is the following: First, return the nth element of the list. Then append the rest elements, except the nth element since you have already returned it. Here's the code:
let MoveToTop index xs =
List.nth xs index // take nth item
:: // and prepend it to the beginning of the
// original list, except the nth element
(
xs // original data
|> List.mapi
(fun i x -> i, x) // associate each element with its ordinal index
|> List.filter
(fun (i, _) -> i <> index) // allow only the elements whose index
// is not equal to requested index
|> List.map snd // remove the index from the data
// as we no longer need it
)
// test
[1; 2; 3; 4; 5]
|> MoveToTop 1 // don't forget, the index is zero-based
|> printfn "%A"
// output: [2; 1; 3; 4; 5]
Note that if index is outside the length of the list, an ArgumentException will be thrown.
A recursive algorithm is also possible, but it would be certainly less performant due to creation of excessive data and performing excessive computations.

Recursion using lists - Haskell

I am trying to write a recursive function that will take a list containing a list of integers as an input and return a tuple of type ([Int],Int).
([Int],Int)
This is for a "board game" where you are supplied with a board:
[[5,4,3,8,6],
[0,2,1,0,7],
[0,1,9,4,3],
[2,3,4,0,9]]
This would be a board with 4 rows and 5 columns. The numbers inside the list are "coin values".
The objective of this board game would be to go from the top of the list to the bottom collecting the coins. You are able to start in any position from the top row and to move down, you can go straight down, or diagonally to left or right. You would want the path that will give you the largest total coin values.
I've created a first function where you input a list of paths [([Int],Int)] and it returns the path ([Int],Int) with maximum coin value.
Now I need to create a function to actually generate the list of paths that I will input into the first function.
I know that I will have to use recursion.
I will input the board (like one above) and a starting column.
I will have to take the column number and then create a list of all possible paths.
If I start with a column number, my next possible steps are positions (in the next row)- same column number, column num -1 and column num +1. I would need to recursively call this until I reach the bottom.
How would I be able to store these path steps as I go and then store the final - list of all possible paths?
([Int],Int) - [Int] is the position in list / column numbers or the rows and the Int is the coin value.
I'm new to haskell and while I understand what I have to do, it's really difficult to write the code.
You don't "store" intermediate values in some variable in idiomatic functional code. Rather, you keep them as an accumulating parameter which you pass along using a function such as foldr.
http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:foldr
I guess I am now in a position to (easily) adapt my answer for another question to this one. I listed the allowed index combinations and mapped the board to them. (pat's comment helped me improve index_combinations)
*Main> :load "new1.hs"
[1 of 1] Compiling Main ( new1.hs, interpreted )
Ok, modules loaded: Main.
*Main> result
([8,7,4,9],28)
*Main> path
[3,4,3,4]
import Data.List
import Data.Ord
import Data.Maybe
r = [[5,4,3,8,6],
[0,2,1,0,7],
[0,1,9,4,3],
[2,3,4,0,9]]
r1 = r !! 0
r2 = r !! 1
r3 = r !! 2
r4 = r !! 3
index_combinations =
[[a,b,c,d] | a <- [0..4], b <- [max 0 (a-1)..min 4 (a+1)],
c <- [max 0 (b-1)..min 4 (b+1)], d <- [max 0 (c-1)..min 4 (c+1)]]
mapR xs = [r1 !! (xs !! 0), r2 !! (xs !! 1),
r3 !! (xs !! 2), r4 !! (xs !! 3)]
r_combinations = map mapR index_combinations
r_combinations_summed = zip r_combinations $ map (foldr (+) 0) r_combinations
result = maximumBy (comparing snd) r_combinations_summed
path = index_combinations !! fromJust (elemIndex result r_combinations_summed)
If you're interested in using my package grid (userguide)
here as an example to get you started.
(And if you don't want to use it, you may find some of the
source code helpful.)
Create a grid with 4 rows and 5 columns.
λ> :m + Math.Geometry.Grid
λ> let g = rectSquareGrid 4 5
λ> indices g
[(0,0),(0,1),(0,2),(0,3),(1,0),(1,1),(1,2),(1,3),(2,0),(2,1),(2,2),(2,3),(3,0),(3,1),(3,2),(3,3),(4,0),(4,1),(4,2),(4,3)]
We want to be able to map "coin values" to grid positions, so we'll
create a GridMap.
λ> :m + Math.Geometry.GridMap
λ> let m = lazyGridMap g [5,4,3,8,6,0,2,1,0,7,0,1,9,4,3,2,3,4,0,9]
λ> m
lazyGridMap (rectSquareGrid 4 5) [5,4,3,8,6,0,2,1,0,7,0,1,9,4,3,2,3,4,0,9]
λ> toList m
[((0,0),5),((0,1),4),((0,2),3),((0,3),8),((1,0),6),((1,1),0),((1,2),2),((1,3),1),((2,0),0),((2,1),7),((2,2),0),((2,3),1),((3,0),9),((3,1),4),((3,2),3),((3,3),2),((4,0),3),((4,1),4),((4,2),0),((4,3),9)]
We can find out the neighbours of any cell in the grid,
but for your application, we run into a bit of a problem: my
RectSquareGrid type doesn't allow diagonal moves.
λ> neighbours (1,2) m
[(0,2),(1,3),(2,2),(1,1)]
Now, I'd be happy to create a new type of Grid that would meet your
needs. Alternatively, you could write your own function
which would include diagonal neighbours:
λ> let neighbours2 (x, y) g = filter (`inGrid` g) [(x-1,y-1), (x-1,y), (x-1,y+1), (x,y-1), (x,y+1), (x+1,y-1), (x+1,y), (x+1,y+1)]
λ> neighbours2 (1,2) m
[(0,1),(0,2),(0,3),(1,1),(1,3),(2,1),(2,2),(2,3)]
But you're only interested in allowing downward moves, either straight down or diagonal, so here's a more useful function:
λ> let allowedMoves (x, y) g = filter (`inGrid` g) [(x+1,y-1), (x+1,y), (x+1,y+1)]
λ> allowedMoves (1,2) m
[(2,1),(2,2),(2,3)]
So now we can write a function that gives you all possible paths from a given index to the bottom row of the grid.
allPathsFrom a g | fst a == fst (size g) = [[a]]
| otherwise = Prelude.map (a:) xs
where xs = concatMap (\x -> allPathsFrom x g) ys
ys = allowedMoves a g
For example:
λ> allPathsFrom (0,1) m
[[(0,1),(1,0),(2,0),(3,0),(4,0)],[(0,1),(1,0),(2,0),(3,0),(4,1)],[(0,1),(1,0),(2,0),(3,1),(4,0)],[(0,1),(1,0),(2,0),(3,1),(4,1)],[(0,1),(1,0),(2,0),(3,1),(4,2)],[(0,1),(1,0),(2,1),(3,0),(4,0)],[(0,1),(1,0),(2,1),(3,0),(4,1)],[(0,1),(1,0),(2,1),(3,1),(4,0)],[(0,1),(1,0),(2,1),(3,1),(4,1)],[(0,1),(1,0),(2,1),(3,1),(4,2)],[(0,1),(1,0),(2,1),(3,2),(4,1)],[(0,1),(1,0),(2,1),(3,2),(4,2)],[(0,1),(1,0),(2,1),(3,2),(4,3)],[(0,1),(1,1),(2,0),(3,0),(4,0)],[(0,1),(1,1),(2,0),(3,0),(4,1)],[(0,1),(1,1),(2,0),(3,1),(4,0)],[(0,1),(1,1),(2,0),(3,1),(4,1)],[(0,1),(1,1),(2,0),(3,1),(4,2)],[(0,1),(1,1),(2,1),(3,0),(4,0)],[(0,1),(1,1),(2,1),(3,0),(4,1)],[(0,1),(1,1),(2,1),(3,1),(4,0)],[(0,1),(1,1),(2,1),(3,1),(4,1)],[(0,1),(1,1),(2,1),(3,1),(4,2)],[(0,1),(1,1),(2,1),(3,2),(4,1)],[(0,1),(1,1),(2,1),(3,2),(4,2)],[(0,1),(1,1),(2,1),(3,2),(4,3)],[(0,1),(1,1),(2,2),(3,1),(4,0)],[(0,1),(1,1),(2,2),(3,1),(4,1)],[(0,1),(1,1),(2,2),(3,1),(4,2)],[(0,1),(1,1),(2,2),(3,2),(4,1)],[(0,1),(1,1),(2,2),(3,2),(4,2)],[(0,1),(1,1),(2,2),(3,2),(4,3)],[(0,1),(1,1),(2,2),(3,3),(4,2)],[(0,1),(1,1),(2,2),(3,3),(4,3)],[(0,1),(1,2),(2,1),(3,0),(4,0)],[(0,1),(1,2),(2,1),(3,0),(4,1)],[(0,1),(1,2),(2,1),(3,1),(4,0)],[(0,1),(1,2),(2,1),(3,1),(4,1)],[(0,1),(1,2),(2,1),(3,1),(4,2)],[(0,1),(1,2),(2,1),(3,2),(4,1)],[(0,1),(1,2),(2,1),(3,2),(4,2)],[(0,1),(1,2),(2,1),(3,2),(4,3)],[(0,1),(1,2),(2,2),(3,1),(4,0)],[(0,1),(1,2),(2,2),(3,1),(4,1)],[(0,1),(1,2),(2,2),(3,1),(4,2)],[(0,1),(1,2),(2,2),(3,2),(4,1)],[(0,1),(1,2),(2,2),(3,2),(4,2)],[(0,1),(1,2),(2,2),(3,2),(4,3)],[(0,1),(1,2),(2,2),(3,3),(4,2)],[(0,1),(1,2),(2,2),(3,3),(4,3)],[(0,1),(1,2),(2,3),(3,2),(4,1)],[(0,1),(1,2),(2,3),(3,2),(4,2)],[(0,1),(1,2),(2,3),(3,2),(4,3)],[(0,1),(1,2),(2,3),(3,3),(4,2)],[(0,1),(1,2),(2,3),(3,3),(4,3)]]
Note that since GridMaps are also Grids, we can invoke all of the above functions on m or g.
λ> allPathsFrom (0,1) m
Let me know (amy at nualeargais dot ie) if you would like me to add
a grid allowing diagonal moves to my grid package.

Update 'x'th element of list - Haskell [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Replace individual list elements in Haskell?
I have managed to make some progress in this part of my assignment but have attached part of the code below that I have made:
module Grid where
data State = On | Off deriving (Eq, Show)
next :: State -> State
next On = Off
next Off = On
type Row = [State]
updateRow :: Row -> Int -> Row
updateRow (r:rs) x
| x == 0 = next r:rs
-- | otherwise = ........????
As shown in the last line just above, I have managed to get updateRow to work for when x = 0, as shown below (with the 0th element inverted).
*Grid> updateRow [Off,Off,Off,Off] 0
[On,Off,Off,Off]
*Grid>
It all comes unstuck however when I try inverting other elements of this list. I can't seem to 'genralise' a formula in this function.
I also MUST follow THIS type convention:
updateRow :: Row -> Int -> Row
Thanks in advance.
Something like that:
module Grid where
data State = On | Off deriving (Eq, Show)
next :: State -> State
next On = Off
next Off = On
type Row = [State]
updateRow :: Row -> Int -> Row
updateRow (r:rs) x
| x == 0 = next r:rs
| otherwise = r : (updateRow rs (x-1))
updateRow [] x = []
Use the function provided for you in the previous question you asked. It works for lists of any type and I think it does what you want to do here.
How about a general update function?
update i a as = map repl $ zip as [0..] where
repl (a',i') | i == i' = a
| otherwise = a'
I guess there are more performant versions, but this one is easy to understand and good enough for short lists. It replaces the ith element (if there is any) in as with a.
Actually the idea for the otherwise part of your updateRow function is similar to the what you have in the replace of your other question.
The idea is: if x is not zero, then you want to skip the element r (which is at position zero) and call updateRow on rs at a position that is x - something (where something takes into account the one position that you just skipped).
I hope this helps