Как посчитать количество единиц, окружающих данный элемент в 2D списке с помощью Haskell? - PullRequest
1 голос
/ 28 сентября 2011

Предположим, у меня есть следующий вложенный список:

list =   
  [[0, 1, 0],  
   [1, 9, 1],  
   [1, 1, 0]]

Предполагается, что вам даны только координаты x и y, равные 9. Как я использую код Haskell, чтобы узнать, сколько единиц окружает число 9?

Позвольте мне пояснить немного больше, предположим, что число 9 расположено в (0, 0).Я пытаюсь сделать следующее:

int sum = 0;
for(int i = -1; i <= 1; i++){
  for(int j = -1; j <= 1; j++){
    if(i == 0 || j == 0) continue;
    sum += list[i][j];
  }
}

Позиции, окружающие (0,0), следующие координаты:

 (-1, -1) (0, -1) (1, -1)
 (-1,  0)         (1,  0)
 (-1,  1) (0,  1) (1,  1)  

Ответы [ 2 ]

4 голосов
/ 28 сентября 2011
list = [[0,1,0],[1,9,1],[1,1,0]]
s x y = sum [list !! j !! i | i <- [x-1..x+1], j <- [y-1..y+1], i /= x || j /= y]
--s 1 1 --> 5

Обратите внимание, что исправление ошибок не выполняется, если координаты находятся на краю.Вы можете реализовать это, добавив больше условий к пониманию.

Список списков - не самая эффективная структура данных, если дела становятся больше.Вы могли бы рассмотреть векторы или Map (Int,Int) Int (особенно если у вас много нулей, которые можно было бы опустить).

[Edit]

Здесь немного быстрееверсия:

s x y xss = let snip i zs = take 3 $ drop (i-1) zs 
                sqr = map (snip x) $ snip y xss
            in sum (concat sqr) - sqr !! 1 !! 1     

Сначала мы «вырезаем» квадрат 3 x 3, затем делаем все вычисления на нем.Опять же, координаты по краям могут привести к неверным результатам.

0 голосов
/ 28 сентября 2011

Редактировать : переключен на суммирование вокруг 8, ​​а не вокруг 4

Как часто вы хотите, чтобы счетчик окружений был только для одной записи?Если вы хотите, чтобы это было для всех записей, списки по-прежнему работают довольно хорошо, вам просто нужно взглянуть на это целостно.

module Grid where
import Data.List (zipWith4)

-- given a grid A, generate grid B s.t.
-- B(x,y) = A(x-1,y-1) + A(x,y-1) + A(x+1,y-1)
--        + A(x-1,y)              + A(x+1,y)
--        + A(x-1,y+1) + A(x,y+1) + A(x+1,y+1)
-- (where undefined indexes are assumed to be 0)
surrsum :: [[Int]] -> [[Int]]
surrsum rs = zipWith3 merge rs ([] : init rs') (tail rs' ++ [[]])
  where -- calculate the 3 element sums on each row, so we can reuse them
        rs'            = flip map rs $ \xs -> zipWith3 add3 xs (0 : xs) (tail xs ++ [0])
        add3 a b c     = a+b+c
        add4 a b c d   = a+b+c+d
        merge [] _  _  = []
        -- add the left cell, right cell, and the 3-element sums above and below (zero-padded)
        merge as bs cs = zipWith4 add4 (0 : init as) (tail as ++ [0]) (bs ++ repeat 0) (cs ++ repeat 0)

-- given a grid A, replace entries not equal to 1 with 0
onesOnly :: [[Int]] -> [[Int]]
onesOnly = map . map $ \e -> if e == 1 then 1 else 0

list :: [[Int]]
list = [[0, 1, 0]
       ,[1, 9, 1]
       ,[1, 1, 0]]

Теперь вы можете перейти к ghci, чтобы увидеть, как оно работает:

*Grid Control.Monad> mapM_ (putStrLn . unwords . map show) list
0 1 0
1 9 1
1 1 0
*Grid Control.Monad> mapM_ (putStrLn . unwords . map show) $ onesOnly list
0 1 0
1 0 1
1 1 0
*Grid Control.Monad> mapM_ (putStrLn . unwords . map show) . surrsum $ onesOnly list
2 2 2
3 5 2
2 3 2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...