我必须更改我的代码才能工作吗?

What do I have to change in my code to work?

我不知道我的代码有什么问题。我可以得到一些帮助来理解它吗?

Use longestChain to see how long the longest string in a text is made up of identical characters!

Examples:
 longestChain "2111234" == 3
 longestChain "0023212212222" == 4
 longestChain "23232323232" == 1
 longestChain "+++++!!!-------" == 7
longestChain :: String -> Int
longestChain (x:y:xs)
 | x == y = 1 + longestChain xs
 | otherwise = longestChain (y:xs)

这不是干净的,但它有效。

longestChain :: String -> Int
longestChain [] = 0
longestChain xs = go xs 0 1 where
  go [] curr res = res
  go [x] curr res
    | curr > 0  = max (curr+1) res
    | otherwise = res
  go (x:y:xs) curr res
    | x == y = go (y:xs) (curr+1) (max (curr+1) res)
    | curr > 0 = go (y:xs) 0 (max (curr+1) res)
    | otherwise = go (y:xs) 0 res

当我们找到相似的字符时,将函数的结果加一是不够的。我们需要计算字符串中的每个链和 return 我们找到的最长长度。这就是 currres 所关心的。

此外,当您找到 2 个字符匹配时,您需要将第二个添加到您的列表中以与下一个匹配,否则您会错过一个。另外,当你找到一个不匹配的时候,如果你的curr大于0,说明这个字符属于上一个链的末尾,所以你加一个

> :m Data.List
Data.List> maximum $ map length $ group $ "+++++!!!-------"
7

group :: Eq a => [a] -> [[a]]Data.List.

“group 函数采用一个列表和 returns 一个列表列表,使得结果的串联等于参数。此外,结果中的每个子列表仅包含相等的元素。”

map length returns 一个列表,每个子列表都替换为它的长度。

maximum returns 这些长度的最大值。

我是怎么找到 group 的?我搜索了 Hoogle 具有该签名的函数。

更多的是@user1984 回答的风格。我仍然会说这段代码很难 read/is 混淆问题。

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)

(此处需要分支 go [] curr = ...,因为 longestChain 可能已将空字符串传递给 go。)

curr 总是计数 'in arrears',所以如果 go 在字符串末尾得到一个单例 [x],那一定是最后一个字符当前链,增加长度。

如果go找到相邻的相同字符x == y,为x加1,在尾部递归。

如果go找到相邻的不同字符otherwise,仍然为x加1(它是当前链的最后一个字符);开始新的尾巴计数。 Return 递增的max curr 从尾部cp max

测试:

Main> longestChain ""
0
Main> longestChain "a"
1
Main> longestChain "Mississippi"
2
Main> longestChain "+++++!!!-------"
7
Main> longestChain "+++++!!!-------*"
7