More in the style of @user1984's answer. I'd still say this code is hard to read/is muddling concerns.
longestChain :: String -> Int
longestChain xs = go xs 0 where
go [] curr = curr
go [x] curr = curr+1
go (x:y:xs) curr | x == y = go (y:xs) (curr+1)
| otherwise = max (curr+1) (go (y:xs) 0)
(Here the branch go [] curr = ...
is needed, because longestChain
might have passed an empty string to go
.)
curr
is always counting 'in arrears', so if go
gets to a singleton [x]
at the end of the string, that must have been the last Char of the current chain, increment the length.
If go
finds adjacent same Chars x == y
, add 1 for the x
, recurse on the tail.
If go
finds adjacent different chars otherwise
, still add 1 for the x
(it was the last Char of the current chain); start a new count for the tail. Return the max
of the incremented curr
cp the max
from the tail.
Tests:
Main> longestChain ""
0
Main> longestChain "a"
1
Main> longestChain "Mississippi"
2
Main> longestChain "+++++!!!-------"
7
Main> longestChain "+++++!!!-------*"
7