Мне нужно получить соседей ячеек на 1D замкнутом поле
Например:
соседи [1,2,3,4,5,-1] (6 элементов)
должен вернуть [[-1,1,2],[1,2,3],[2,3,4],[3,4,5],[4,5,-1],[5,-1 ,1]] (6 элементов)
мой код соседей
neighbours :: [a] -> [[a]]
neighbours l = concat [[[last l, head l, last $ take 2 l]], neighbours' l, [[l !! (length l - 2), last l, head l]]] where
neighbours' :: [a] -> [[a]]
neighbours' (a:b:c:xs) = [a, b, c]:neighbours (b:c:xs)
neighbours' _ = []
main = print $ neighbours [1, 2, 3, 4]
возвращает [[4,1,2],[1,2,3],[4,2,3],[2,3,4],[4,3,4],[3,4,3], [3,4,2],[3,4,1]] (8 элементов), но ожидается [[4,1,2],[1,2,3],[2,3,4],[3 ,4,1]] (4 элемента)
если я прокомментирую соседей, я вернусь [[4,1,2],[3,4,1]] как и ожидалось (2 элемента)
если ты оставишь только соседей, я вернусь [[1,2,3],[2,3,4]] как и ожидалось (2 элемента)
2+2=4, но в данном случае почему-то 8
почему это происходит?
P.S.
соседи создать середину списка
соседи' [1,2,3,4,5,-1] == [[1,2,3],[2,3,4],[3,4,5],[4,5,-1 ]]
[последняя л, голова л, последняя $ взять 2 л] создать начало списка [-1,1,2]
[л!! (length l - 2), last l, head l] создать последний элемент списка [5,-1,1]
Желаемый результат можно получить так: neighbors xs = let k = length xs in (drop (k-1) $ take (k+k-1) $ map (take 3) (tails (cycle xs)))
@dfeuer я добавил информацию о целях кода и его компонентов
Ваш код несколько сложен для понимания, потому что две ваши функции, neighbour
и neighbour'
, являются рекурсивными взаимно, что довольно необычно.
Ключевая строка в вашем коде:
neighbours' (a:b:c:xs) = [a, b, c] : neighbours (b:c:xs)
Если предположить, что это НЕТ преднамеренно, и вы просто хотели написать:
neighbours' (a:b:c:xs) = [a, b, c] : neighbours' (b:c:xs)
-----------------------------------------------+---------
тогда код работает так, как вы ожидаете.
Обратите внимание, что наличие длинных (более 80 символов) строк кода сильно затрудняет отладку.
Предлагаемый код:
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ExplicitForAll #-}
import qualified Data.List as L
neighbours :: [a] -> [[a]]
neighbours l = concat [
[[last l, head l, last $ take 2 l]],
neighbours' l,
[[l !! (length l - 2), last l, head l]]
]
where
neighbours' :: [a] -> [[a]]
neighbours' (a:b:c:xs) = [a, b, c] : neighbours' (b:c:xs)
neighbours' _ = []
-- neighbour is British English, neighbor is US English
neighbors :: [a] -> [[a]]
neighbors xs =
take count $ drop (count-1) allTriplets -- section of infinite list
where
count = length xs
allTriplets = map (take 3) (L.tails (cycle xs)) -- raw material
main :: IO ()
main = do
print $ "res1 = " ++ (show $ neighbours [1, 2, 3, 4])
print $ "res2 = " ++ (show $ neighbors [1, 2, 3, 4])
Вывод программы:
"res1 = [[4,1,2],[1,2,3],[2,3,4],[3,4,1]]"
"res2 = [[4,1,2],[1,2,3],[2,3,4],[3,4,1]]"
Я думаю, что вы можете сделать это проще без tails
. zip3 (drop (count-1) cycled) xs (drop 1 cycled)
Что ж, tails
относительно дешево, но идея хорошая, спасибо. Просто нужно преобразовать кортеж в список в конце.
Это был просто набросок. На самом деле вы бы использовали zipWith3 (\a b c -> [a,b,c])
.
Ваш код довольно загадочен, потому что вы не дали никакого контекста о том, что он должен иметь в виду. Пожалуйста, объясните в теле вашего вопроса. Использование
head
,last
и!!
еще больше затрудняет угадывание ваших намерений.