如何递归地比较Haskell中数字中的数字

时间:2009-11-23 15:03:26

标签: haskell recursion

我正在Project Euler上做problem 112并提出以下测试示例案例(我将answer中的数字更改为0.99以获得真正的答案):

isIncre  x | x == 99 = False
           | otherwise = isIncre' x
                where
                    isIncre' x = ???

isDecre  x = isIncre (read $ reverse $ show x :: Int)
isBouncy x = (isIncre x == False) && (isDecre x == False)

bouncers x = length [n|n<-[1..x],isBouncy n]
nonBouncers x = length [n|n<-[1..x],(isBouncy n) == False] 

answer = head [x|x<-[1..],((bouncers x) / (nonBouncers x)) == 0.5]

但是我不知道怎么做是定义一个函数isIncre',它测试一个数字中的数字是否大于或等于左边的数字。我知道它需要递归完成但是如何?

另一方面,我知道我只能在两个浮点数上使用/但是如何使bouncers的输出为浮点数而不是整数?

编辑:

感谢您的帮助,但当我将=更改为:{/ p>时,它不喜欢isIncre

isIncre  x | x <= 99 = False
           | otherwise = isIncre' (mshow x)
                        where
                            isIncre' (x:y:xs) = (x <= y) && (isIncre' (y:xs))
                            isIncre' _ = True

3 个答案:

答案 0 :(得分:3)

  1. 数字0.99无法在基数2中准确表示。因此,您可能希望避免使用浮点数进行此分配。相反,要查看是否有99%的数字<= x是保镖,请测试是否

    100 * (x - bouncers x) == x
    

    这是有效的,因为它(在数学上)与(x - bouncers x) == x / 100相同,如果(x - bouncers x)(非有弹性数字的数量)是x的1%,则为真。请注意,因此无需定义nonBouncers

  2. 另外,定义bouncers的另一种方法是

    bouncers x = length $ filter isBouncy [1..x]
    
  3. 然而,您应该重新考虑您的设计。目前,您正在重新计算您尝试的每个x的最高x的有弹性数字的数量。所以很多工作都在做一遍又一遍。您可能想要做的是生成一系列元组(x, n),其中n是有弹性数字<= x的数量。请注意,如果有n个有弹性的数字<= x,则有nn + 1有弹性数<= x + 1

    更具体地说,要计算(x + 1, n'),您只需要(x, n)isbouncy (x + 1)的输出。

答案 1 :(得分:2)

如果你有一个整数的字符串表示,你可以写这样的isIncre函数(ord将一个字符转换为一个整数,字符串只是一个字符列表):

isIncre (x:y:xs) = ord x <= ord y && isIncre (y:xs)
isIncre _ = True

在没有ord的情况下编写isIncre函数,处理任何有序类型,然后在调用它时将其与“map ord”结合起来可能更好。那么实现就是:

isIncre (x:y:xs) = x <= y && isIncre (y:xs)
isIncre _ = True

如果x是整数

,则可以这样调用
isIncre (map ord (show x))

答案 2 :(得分:1)

如果你有intetger的字符串表示,我会使用非常好的isIncre函数版本。

isIncre :: (Ord a) => [a] -> Bool
isIncre list = and $ zipWith (<=) list (tail list)

如果没有,只需用show撰写。

isIncreNum :: Integer -> Bool
isIncreNum = isIncre . show