计算Haskell中2个整数之间的回文数的线性递归方法
Linear recursive method for counting palindrome numbers between 2 integers in Haskell
我正在解决 Haskell 中的一道练习题,我试图计算 2 个给定整数之间的回文数。个位数是回文。我试过用辅助函数解决它,但我不能让它从主函数中获取较小的数字。任何帮助,将不胜感激!
到目前为止,我输入了这个:
main :: IO()
main = do
print $ countPalindromes 5 13 == 5 -- 6 7 8 9 11
print $ countPalindromes 13 5 == 5 -- 6 7 8 9 11
rev :: Int -> Int
rev n = helper n 0
where
helper :: Int -> Int -> Int
helper 0 result = result
helper n result = helper (div n 10) (result * 10 + mod n 10)
isPalindrome :: Int -> Bool
isPalindrome x = rev x == x
countPalindromes :: Int -> Int -> Int
countPalindromes a b
| a > b = helper b a 0
| otherwise = helper a b 0
where
helper :: Int -> Int -> Int -> Int
helper a b count
| a <= b && isPalindrome (a - 1) = count + 1
| otherwise = helper (a - 1) b count
那不是你的问题。问题是如果 a
是回文,helper a b count
只有 return 和 count + 1
,而不会检查 a + 1
、a + 2
等是否是回文也是如此。当第一个数字是回文时,它 returns 0 + 1 == 1
就完成了。 (您对 helper
的定义也以错误的方式计数;它是 decrementing a
而不是 incrementing如果您希望 a <= b
为假,请执行此操作。)
helper
需要递归是否a
是否回文;唯一的区别在于其 第三个 参数的值。
helper a b count | a > b = count -- base
| isPalindrome a = helper (a + 1) b (count + 1)
| otherwise = helper (a + 1) b count
注意 b
永远不会改变;它不需要成为 helper
的参数。相反,您可以递归调用 countPalindromes
以确保 a < b
:
countPalindromes :: Int -> Int -> Int
countPalindromes a b
| a > b = countPalindromes b a
| otherwise = helper a 0
where
helper :: Int -> Int -> Int
helper a count
| a > b = count -- base case
| isPalindrom a = helper (a + 1) (count + 1)
| otherwise = helper (a + 1) count
尾递归在 Haskell 中也不是特别重要。你可以写helper
更自然
helper a | a > b = 0
| isPalindrome a = 1 + helper (a + 1)
| otherwise = helper (a + 1)
还请注意,isPalindrome
return 与 True
或 False
之间的唯一区别在于您添加的是 1
还是 0
到递归 return 值。您可以使用 fromEnum
:
捕获它
helper a | a > b = 0
| otherwise = (fromEnum (isPalindrome a)) + helper (a + 1)
作为练习,请注意您根本不需要显式递归。您可以使用 filter
获取回文范围内的值,然后简单地计算结果列表中值的数量。
我正在解决 Haskell 中的一道练习题,我试图计算 2 个给定整数之间的回文数。个位数是回文。我试过用辅助函数解决它,但我不能让它从主函数中获取较小的数字。任何帮助,将不胜感激! 到目前为止,我输入了这个:
main :: IO()
main = do
print $ countPalindromes 5 13 == 5 -- 6 7 8 9 11
print $ countPalindromes 13 5 == 5 -- 6 7 8 9 11
rev :: Int -> Int
rev n = helper n 0
where
helper :: Int -> Int -> Int
helper 0 result = result
helper n result = helper (div n 10) (result * 10 + mod n 10)
isPalindrome :: Int -> Bool
isPalindrome x = rev x == x
countPalindromes :: Int -> Int -> Int
countPalindromes a b
| a > b = helper b a 0
| otherwise = helper a b 0
where
helper :: Int -> Int -> Int -> Int
helper a b count
| a <= b && isPalindrome (a - 1) = count + 1
| otherwise = helper (a - 1) b count
那不是你的问题。问题是如果 a
是回文,helper a b count
只有 return 和 count + 1
,而不会检查 a + 1
、a + 2
等是否是回文也是如此。当第一个数字是回文时,它 returns 0 + 1 == 1
就完成了。 (您对 helper
的定义也以错误的方式计数;它是 decrementing a
而不是 incrementing如果您希望 a <= b
为假,请执行此操作。)
helper
需要递归是否a
是否回文;唯一的区别在于其 第三个 参数的值。
helper a b count | a > b = count -- base
| isPalindrome a = helper (a + 1) b (count + 1)
| otherwise = helper (a + 1) b count
注意 b
永远不会改变;它不需要成为 helper
的参数。相反,您可以递归调用 countPalindromes
以确保 a < b
:
countPalindromes :: Int -> Int -> Int
countPalindromes a b
| a > b = countPalindromes b a
| otherwise = helper a 0
where
helper :: Int -> Int -> Int
helper a count
| a > b = count -- base case
| isPalindrom a = helper (a + 1) (count + 1)
| otherwise = helper (a + 1) count
尾递归在 Haskell 中也不是特别重要。你可以写helper
更自然
helper a | a > b = 0
| isPalindrome a = 1 + helper (a + 1)
| otherwise = helper (a + 1)
还请注意,isPalindrome
return 与 True
或 False
之间的唯一区别在于您添加的是 1
还是 0
到递归 return 值。您可以使用 fromEnum
:
helper a | a > b = 0
| otherwise = (fromEnum (isPalindrome a)) + helper (a + 1)
作为练习,请注意您根本不需要显式递归。您可以使用 filter
获取回文范围内的值,然后简单地计算结果列表中值的数量。