Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell Recursion using an Accumulator

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)
like image 392
user1670032 Avatar asked Aug 04 '26 06:08

user1670032


1 Answers

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.

like image 69
applicative Avatar answered Aug 05 '26 20:08

applicative



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!