我尝试解决Advent of Code 2017中的第一个问题,并提出以下解决方案来计算所需的值:
checkRepetition :: [Int] -> Bool
checkRepetition [] = False
checkRepetition (x:xs)
| x == ( head xs ) = True
| otherwise = False
test :: [Int] -> Int
test [] = 0
test [x] = 0
test xs
| checkRepetition xs == True = ((head xs)*a) + (test (drop a xs))
| otherwise = test (tail xs)
where
a = (go (tail xs)) + 1
go :: [Int] -> Int
go [] = 0
go xs
| checkRepetition xs == True = 1 + ( go (tail xs) )
| otherwise = 0
但是,当我提供包含[1,3,3]
等重复数字的输入时,会出现错误
***例外:Prelude.head:空列表
然而,在1.5小时内,我无法弄清楚这个错误的确切位置。我的意思是test
函数中使用的任何函数都有[]
的定义,但它仍会抛出此错误,那么问题是什么?
请注意,我已查看this个问题,并且在给定的答案中,建议不要使用head
和tail
函数,但我已针对各种函数测试了这些函数输入,它们不会抛出任何错误,那究竟是什么问题?
我将不胜感激任何帮助或提示。
答案 0 :(得分:1)
正如评论中指出的那样,问题在于:
checkRepetition (x:xs)
| x == ( head xs ) = True
xs
不能保证是非空列表(单元素列表写为x:[]
,因此(x:xs)
模式与xs = []
匹配,并且在空列表上调用head
是运行时错误。
您可以通过将模式更改为仅匹配2+元素列表来处理此问题。
checkRepetition [] = False
checkRepetition [_] = False
checkRepetition (x1:x2:_) = x1 == x2
-- No need for the alternations on this function, by the way.
那就是说,你的算法似乎不必要复杂。您所要做的就是检查 next 值是否相等,如果是,则将当前值添加到总数中。假设您可以自己获取String -> [Int]
,请考虑以下内容:
filteredSum :: [Int] -> Int
filteredSum [] = 0 -- by definition, zero- and one-element lists
filteredSum [_] = 0 -- cannot produce a sum, so special case them here
filteredSum xss@(first:_) = go xss
where
-- handle all recursive cases
go (x1:xs@(x2:_)) | x1 == x2 = x1 + go xs
| otherwise = go xs
-- base case
go [x] | x == first = x -- handles last character wrapping
| otherwise = 0 -- and if it doesn't wrap
-- this should be unreachable
go [] = 0
对于它的价值,我认为最好在Maybe monad中工作并在Maybe [Int] -> Maybe Int
上操作,但幸运的是,这很容易,因为Maybe是一个算子。
digitToMaybeInt :: Char -> Maybe Int
digitToMaybeInt '0' = Just 0
digitToMaybeInt '1' = Just 1
digitToMaybeInt '2' = Just 2
digitToMaybeInt '3' = Just 3
digitToMaybeInt '4' = Just 4
digitToMaybeInt '5' = Just 5
digitToMaybeInt '6' = Just 6
digitToMaybeInt '7' = Just 7
digitToMaybeInt '8' = Just 8
digitToMaybeInt '9' = Just 9
digitToMaybeInt _ = Nothing
maybeResult :: Maybe Int
maybeResult = fmap filteredSum . traverse digitToMaybeInt $ input
result :: Int
result = case maybeResult of
Just x -> x
Nothing -> 0
-- this is equivalent to `maybe 0 id maybeResult`
答案 1 :(得分:0)
感谢您的链接。我先到那里去收集目的。 我假设输入将是一个字符串。下面的辅助函数构造了一个数字列表,用于汇总谓词是否为True,即压缩值是否相等,即每个数字与每个连续数字(该对)进行比较。
辅助函数'nl'使用数字列表调用主函数'invcap'Inverse Captcha。
nl函数是列表解析。 invcap函数是列表解析。也许这个问题的逻辑是错误的。过于复杂的逻辑更容易引入错误。当逻辑不繁琐时,证明非常容易。
主要功能“invcap”
invcap l = sum [ x | (x,y) <- zip l $ (tail l) ++ [head l], x == y]
将字符串转换为数字列表并使用数字列表调用invcap的辅助函数。
nl cs = invcap [ read [t] :: Int | t <- cs]
调用示例 前奏&GT; nl“91212129”...... 9'''''''''' 前奏&GT; nl“1122”...... 3