我正在做另一个Project Euler问题,我需要找到这三个列表的结果相等的时候(我们第一次给出40755它们是相同的,我需要找到下一个:
hexag n = [ n*(2*n-1) | n <- [40755..]]
penta n = [ n*(3*n-1)/2 | n <- [40755..]]
trian n = [ n*(n+1)/2 | n <- [40755..]]
我尝试在其他列表中添加第一个列表的谓词,但这不起作用:
hexag n = [ n*(2*n-1) | n <- [40755..], penta n == n, trian n == n]
我被困在哪里可以离开这里。
我尝试绘制函数甚至微积分,但无济于事,所以我必须求助于Haskell解决方案。
答案 0 :(得分:2)
如果你真的想要一个扰流板来解决这个问题(但是没有错过这一点?):
binarySearch :: Integral a => (a -> Bool) -> a -> a -> a
binarySearch func low high
| low == high = low
| func mid = search low mid
| otherwise = search (mid + 1) high
where
search = binarySearch func
mid = (low+high) `div` 2
infiniteBinarySearch :: Integral a => (a -> Bool) -> a
infiniteBinarySearch func =
binarySearch func ((lim+1) `div` 2) lim
where
lim = head . filter func . lims $ 0
lims x = x:lims (2*x+1)
inIncreasingSerie :: (Ord a, Integral i) => (i -> a) -> a -> Bool
inIncreasingSerie func val =
val == func (infiniteBinarySearch ((>= val) . func))
figureNum :: Integer -> Integer -> Integer
figureNum shape index = (index*((shape-2)*index+4-shape)) `div` 2
main :: IO ()
main =
print . head . filter r $ map (figureNum 6) [144..]
where
r x = inIncreasingSerie (figureNum 5) x && inIncreasingSerie (figureNum 3) x
答案 1 :(得分:1)
以下是对您提出的问题的简单直接回答:
*Main> take 1 $ filter (\(x,y,z) -> (x == y) && (y == z)) $ zip3 [1,2,3] [4,2,6] [8,2,9]
[(2,2,2)]
当然,yairchu的回答在实际解决欧拉问题时可能更有用:)
答案 2 :(得分:0)
至少有几种方法可以做到这一点。
您可以查看第一项,并将其余项目与之比较:
Prelude> (\x -> all (== (head x)) $ tail x) [ [1,2,3], [1,2,3], [4,5,6] ]
False
Prelude> (\x -> all (== (head x)) $ tail x) [ [1,2,3], [1,2,3], [1,2,3] ]
True
或者您可以创建一个类似于前一个的显式递归函数:
-- test.hs
f [] = True
f (x:xs) = f' x xs where
f' orig (y:ys) = if orig == y then f' orig ys else False
f' _ [] = True
Prelude> :l test.hs
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, modules loaded: Main.
*Main> f [ [1,2,3], [1,2,3], [1,2,3] ]
True
*Main> f [ [1,2,3], [1,2,3], [4,5,6] ]
False
您也可以执行takeWhile并比较返回列表的长度,但这既不高效也不典型Haskell。
<小时/> 糟糕,只是看到根本没有回答你的问题。将此标记为CW,以防任何人通过Google绊倒您的问题。
答案 3 :(得分:0)
最简单的方法是稍微重新指定问题
而不是处理三个列表(注意删除多余的n参数):
hexag = [ n*(2*n-1) | n <- [40755..]]
penta = [ n*(3*n-1)/2 | n <- [40755..]]
trian = [ n*(n+1)/2 | n <- [40755..]]
例如,您可以生成一个列表:
matches :: [Int]
matches = matches' 40755
matches' :: Int -> [Int]
matches' n
| hex == pen && pen == tri = n : matches (n + 1)
| otherwise = matches (n + 1) where
hex = n*(2*n-1)
pen = n*(3*n-1)/2
tri = n*(n+1)/2
现在,您可以尝试通过注意重复来优化此性能。例如,在(n + 1)处计算下一个匹配时:
(n+1)*(n+2)/2 - n*(n+1)/2 = n + 1
所以你可以将(n + 1)添加到前一个tri以获得新的tri值。
类似的代数简化可以应用于其他两个函数,并且您可以将所有这些函数用于累积参数到函数匹配'。
也就是说,有更有效的方法来解决这个问题。