I'm trying to make a function that will look for 3 identical and adjacent numbers given a list, for a solver I am trying to implement. Then, if there are 3 identical and adjacent numbers, it will mark the 1st and 3rd identical numbers to '0' and set the middle value to be negative.
I am wondering why this is giving me an error.:
change xs = chnge xs []
where
chnge xs acc
| length xs <= 2 = [acc]
| (head xs == xs !! 1) && (head xs == xs !! 2) = [0, (xs !! 1)*(-1), 0] ++ tail xs
| otherwise = chnge (tail xs) (acc ++ head xs)
Since acc
is a list, we don't want to return [acc]
in the first guard of chnge
, but just acc
; similarly in the otherwise
line you don't want acc ++ head xs
which would mean that xs
is a list of lists -- how else could its first member be appendable? Rather acc ++ [head xs]
So maybe:
change xs = chnge xs [] where
chnge xs acc
| length xs <= 2 = acc
| (head xs == xs !! 1) && (head xs == xs !! 2) = [0, (xs !! 1)*(-1), 0] ++ tail xs
| otherwise = chnge (tail xs) (acc ++ [head xs])
This seems a little off, but the real problem is the dearth of 'pattern matching' and the dangerous use of head
,tail
and !!
. Try something more like this, maybe? (It doesn't use an accumulator though):
change [] = []
change [x] = [x]
change [x,y] = [x,y]
change (x:y:z:ws) | x == y && y == z = 0 : (-y) : 0 : change ws
change (x:xs) = x : change xs
-- *Main> change [12,12,66,66,66,44,44,99,99,99,76,1]
-- [12,12,0,-66,0,44,44,0,-99,0,76,1]
The case of three in a row can be considered as a pattern, so that we make a special case for when they're equal.