'Сoncatenation returns more elements than it should
I need get neighbours of cells on 1D closed field
for example:
neighbours [1,2,3,4,5,-1] (6 elements)
must return [[-1,1,2],[1,2,3],[2,3,4],[3,4,5],[4,5,-1],[5,-1,1]] (6 elements)
my code of neighbours
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]
returns [[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 elements), but expected [[4,1,2],[1,2,3],[2,3,4],[3,4,1]] (4 elements)
if I comment neighbours' l it return [[4,1,2],[3,4,1]] as expected (2 elements)
if you leave only neighbours' l it return [[1,2,3],[2,3,4]] as expected (2 elements)
2+2=4, but in this case for some reason it is 8
why it happens?
P.s.
neighbours' create middle of list
neighbours' [1,2,3,4,5,-1] == [[1,2,3],[2,3,4],[3,4,5],[4,5,-1]]
[last l, head l, last $ take 2 l] create head of list [-1,1,2]
[l !! (length l - 2), last l, head l] create last element of list [5,-1,1]
Solution 1:[1]
Your code is somewhat hard to grasp because your two functions, neighbour and neighbour', are mutually recursive, which is sort of unusual.
The key line in your code is:
neighbours' (a:b:c:xs) = [a, b, c] : neighbours (b:c:xs)
If we assume that this is NOT intentional, and you just meant to write:
neighbours' (a:b:c:xs) = [a, b, c] : neighbours' (b:c:xs)
-----------------------------------------------+---------
then the code works as you seem to expect.
Note that having long (over 80 characters) lines of code makes the thing very difficult to debug.
Suggested code:
{-# 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])
Program output:
"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]]"
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
