我正在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
答案 0 :(得分:3)
数字0.99无法在基数2中准确表示。因此,您可能希望避免使用浮点数进行此分配。相反,要查看是否有99%的数字<= x
是保镖,请测试是否
100 * (x - bouncers x) == x
这是有效的,因为它(在数学上)与(x - bouncers x) == x / 100
相同,如果(x - bouncers x)
(非有弹性数字的数量)是x
的1%,则为真。请注意,因此无需定义nonBouncers
。
另外,定义bouncers
的另一种方法是
bouncers x = length $ filter isBouncy [1..x]
然而,您应该重新考虑您的设计。目前,您正在重新计算您尝试的每个x
的最高x
,的有弹性数字的数量。所以很多工作都在做一遍又一遍。您可能想要做的是生成一系列元组(x, n)
,其中n
是有弹性数字<= x
的数量。请注意,如果有n
个有弹性的数字<= x
,则有n
或n + 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