Reputation: 1861
Well I can't figure out how I could make it in haskell. For example, I have such matrix
[[1,2],[3,4]]
and I want to generate a list of lists with all possible neighbours of each element for this matrix.
Expected result is:
[[1,2],[1,3],[1,4],[2,1],[2,3],[2,4],[3,1],[3,2],[3,4],[4,1],[4,2],[4,3]]
I know how to make function which will create list of list with cords of neighbours of each cell:
pos how = [ (0+dx,0+dy) | dx <- [0..(how-2)], dy <- [0..how-1] ] :: [(Int,Int)]
neighbour (x,y) how = [ (x+dx,y+dy) | dy <- [-1..1], dx <- [-1..1],
x+dx >= 0, y+dy >= 0, x+dx<=how-2, y+dy <= how-1,
(x,y)/=(x+dx,y+dy) ] :: [(Int,Int)]
all_n how = [ p | x <- pos how, let p = neighbour x how ] :: [[(Int,Int)]]
but I can't change it to work as I described.
Upvotes: 0
Views: 1328
Reputation: 152707
To correct the code you have now, I provide a few questions for which a thoughtful answer may help you make progress:
how-2
is a strange thing. Why is 2
the right number to subtract?all_n
is quite strange. Why is it a function? (What does its argument represent?) Why does it return a nested list, rather than a flat one?(!!) :: [a] -> Int -> [a]
.) If you have a list of coordinates, do you know how to do this for each element in the list? (Hint: there is a function map :: (a -> b) -> ([a] -> [b])
.)Good luck!
Upvotes: 1
Reputation: 152707
Let me sketch a very different approach to the one you suggested. When talking about neighbors, I'll say a d-neighbor of e is the element one step in direction d from element e. So, for example, in the matrix [[1,2],[3,4]]
, the number 2
is a right-neighbor of number 1
. We'll need to use some library code.
import Data.List
We'll start from the very simplest thing: let's just find right-neighbors of a one-dimensional list.
rightList (x:y:rest) = (x,y) : rightList (y:rest)
rightList _ = []
We can find all the right-neighbors in a matrix by nondeterministically choosing a row of the matrix and finding all right-neighbors in that row.
right m = m >>= rightList
We can take any function for finding neighbors and create the function for finding neighbors in the other direction by reversing the tuples. For example, left neighbors are the same as right neighbors, but with the tuple elements swapped, so:
swap (x,y) = (y,x)
co direction = map swap . direction
left = co right
What about down-neighbors? Actually, down-neighbors are just right-neighbors in the transposed matrix:
down = right . transpose
up = co down
The next direction of interest are down-right-neighbors. This one is a little trickier; what we're going to do is walk down two lists in parallel, but offset by one.
downRight (xs:ys:rest) = zip xs (drop 1 ys) ++ downRight (ys:rest)
downRight _ = []
upLeft = co downRight
There's one final direction, namely up-right-neighbors; these are down-right-neighbors if we flip the matrix upside down.
upRight = downRight . reverse
downLeft = co upRight
Finally, to form all neighbors, we can nondeterministically choose a neighboring direction, then find all neighbors in that direction.
allDirections = [right, left, up, down,
downRight, upLeft, upRight, downLeft]
neighbors m = allDirections >>= ($m)
The output isn't in exactly the order you specified, but I imagine this may not matter so much.
Upvotes: 6