tags:

views:

94

answers:

2
t = True
f = False
anzNachbarn :: [[Bool]] -> (Integer,Integer) -> Integer
anzNachbarn a (x,y)
       | x < 0 || y < 0=-1
       | otherwise ... here comes the comparison

This is an example matrix:

[[True,False,False],
 [True,False,False],
 [False,True,False]]

here i need an algorithm, where it calculates (for given x and y position in matrix) its neighbours (only "true" neighboors) and increase it by 1 for each true neighboor.

For example: anzNachbarn [[True,False,False],[True,False,False],[False,True,False]] (0,1)

returns 2 back.

:Edit

I still have a question how can I now implement each component of the result matrix, the number of named elements with True neighboring fields indicates the corresponding component of the argument matrix Applies to

[[True, False, False],

[True, False, False],

[False, True , False]]

the function func returns the results matrix [[1,2,0], [2,3,1], [2,1,1]] with signature func :: [[Bool]] -> [[Integer]] have you got any idea about this ?

+3  A: 

You almost certainly want to use an array (from Data.Array) in this situation, since looking up an item in a list by its index is very slow.

Here's a quick implementation using Array:

countNeighbors :: Array (Int, Int) Bool -> (Int, Int) -> Int
countNeighbors board (x, y) = length
  [ (x', y')
  | x' <- [x - 1, x, x + 1]
  , y' <- [y - 1, y, y + 1]
  , x' /= x || y' /= y
  , inRange (bounds board) (x', y')
  , board ! (x', y')
  ]

This is a list comprehension with two generators and three guards. The generators simply give us the indices of the nine positions in a three-by-three square centered at (x, y) (you'll need a minor change if you don't want neighbors at the corners to be considered).

The first guard (x' /= y') ignores (x, y) itself. The second throws out positions that aren't within the bounds of the array. The final guard throws out positions that are in the array but have a False value.

So we now have a list of indices for the neighbors with True values. The length of this list is the desired count.

Travis Brown
thank you for your help but i need it without Array
marco
+1  A: 

This is ugly, but seems to work...

anzNachbarn :: [[Bool]] -> (Int,Int) →  Integer
anzNachbarn a (x,y)
   | x < 0 || y < 0 = -1
   | otherwise = sum [v x' y' | x' <- [max 0 (x-1)..x+1], 
                                y' <- [max 0 (y-1)..y+1], 
                                x ≠ x' || y ≠ y' ]
     where v i j = if j >= length a 
                      || i >= length (a !! 0) 
                      || not (a !! j !! i) 
                   then 0 else 1

[Edit]

In order to convert the whole array, you can write the equally ugly

conv a = [line y | y <- [0 .. (length a) - 1]]
    where line y = [anzNachbarn a (x,y) | x <- [0 .. ((length (a !! 0) - 1)]]

Note that the performance of this is terrible.

Landei