Question

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)
Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top