我想用递归来反转Haskell中的Integer。我有一个小问题。
以下是代码:
reverseInt :: Integer -> Integer
reverseInt n
| n>0 = (mod n 10)*10 + reverseInt(div n 10)
| otherwise = 0
示例345
我用作输入345,我想输出543
在我的程序中它会做....
reverseInt 345
345>0
mod 345 10 -> 5
reverseInt 34
34
34>0
mod 34 10 -> 4
reverseInt 3
3>0
mod 3 10 -> 3
reverseInt 0
0=0 (ends)
最后它返回它们的总和...... 5 + 4 + 3 = 12.
所以我希望每次在它们总结之前,将总和* 10加倍。所以它会...
5
5*10 + 4
54*10 + 3
543
答案 0 :(得分:4)
这是一个相对简单的问题:
reverseInt :: Int -> Int
reverseInt 0 = 0
reverseInt n = firstDigit + 10 * (reverseInt $ n - firstDigit * 10^place)
where
n' = fromIntegral n
place = (floor . logBase 10) n'
firstDigit = n `div` 10^place
基本上,
logBase 10
来给你它在哪个地方(10s,100s,1000s ......)floor
函数截断小数点后的所有内容。n 'div' 10^place
确定号码的第一个数字。例如,如果我们有543,我们会找到2的位置,所以firstDigit = 543/100 = 5(整数除法)编辑:也许更简洁易懂的版本可能是:
reverseInt :: Int -> Int
reverseInt 0 = 0
reverseInt n = mod n 10 * 10^place + reverseInt (div n 10)
where
n' = fromIntegral n
place = (floor . logBase 10) n'
这一次,我们不是通过第一个数字递归,而是通过最后一个数字递归并使用地方给它正确的零数。
答案 1 :(得分:1)
reverseInt :: Integer -> Integer
reverseInt n = snd $ rev n
where
rev x
| x>0 = let (a,b) = rev(div x 10)
in ((a*10), (mod x 10)*a + b)
| otherwise = (1,0)
留给读者的解释:)
答案 2 :(得分:1)
我不知道在第3行中你应该多次将(mod n 10)
乘以10的方便方法。我喜欢unfoldr
更多的解决方案:
import Data.List
listify = unfoldr (\ x -> case x of
_ | x <= 0 -> Nothing
_ -> Just(mod x 10, div x 10) )
reverse_n n = foldl (\ acc x -> acc*10+x) 0 (listify n)
在listify
函数中,我们以相反的顺序从整数生成数字列表,之后我们构建结果简单折叠列表。
答案 3 :(得分:0)
或者只是将其转换为字符串,将其反转并将其转换回整数:
reverseInt :: Integer -> Integer
reverseInt = read . reverse . show
答案 4 :(得分:0)
更多(不一定基于递归)答案非常好!
reverseInt 0 = 0
reverseInt x = foldl (\x y -> 10*x + y) 0 $ numToList x
where
numToList x = if x == 0 then [] else (x `rem` 10) : numToList (x `div` 10)
这基本上是两个函数的串联:numToList(将给定的整数转换为列表123 - &gt; [1,2,3])和listToNum(执行相反的操作)。
numToList函数通过重复获取数字的最低单位(使用rem
,Haskell的余数函数),然后将其删除(使用div
,Haskell的整数除法函数)来工作。一旦数字为0,将返回空列表,并将结果连接到最终列表中。请记住,此列表的顺序相反!
listToNum函数(未见)是一段非常性感的代码:
foldl (\x y -> 10*x + y) 0 xs
这从左边开始向右移动,将每一步的当前值乘以10,然后再添加下一个数字。
我知道已经给出了答案,但总是很高兴看到其他解决方案:)
答案 5 :(得分:0)
第一个函数是递归的,可以将整数转换为列表。它最初是倒车,但重新转换功能更容易扭转,所以我把它从第一个中取出。这些功能可以单独运行。第一个输出一对元组。第二个采用元组对。第二个不是递归,也不是必须的。
di 0 ls = (ls,sum ls); di n ls = di nn $ d:ls where (nn,d) = divMod n 10
di 3456789 []
([3,4,5,6,7,8,9],42)
rec (ls,n) = (sum [y*(10^x)|(x,y) <- zip [0..] ls ],n)
同时运行
rec $ di 3456789 []
(9876543,42)