2009-08-13 18 views
0

私は別のProject Eulerの問題を抱えていますが、これらの3つのリストの結果が等しいときに見つける必要があります(40755が最初に等しくなったときに次を探します:haskellの3つの出力リストを比較する

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解に頼らなければなりません。

+1

先頭のn(arg)が何であるか分かりません。それは無視されます。 – jrockway

+0

重複した質問:http://projecteuler.net/index.php?section=problems&id=45 :) – yairchu

答えて

2
  • あなたの機能は変です。彼らはnを取得し、それを無視しますか?
  • また、関数の入力と出力の間に混乱があります。あなたが本当に問題にスポイラーをしたい場合は第四万七百五十五六角形の数は3321899295、ない40755.

である(ただし、ポイントを見逃さない?):

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 
+0

私はまだHaskellを学んでいます.... 私はこの問題を解決する方法はちょうど計算することですその結果の数字がすべて等しい場合の結果のみを表示します。 私はモナドまたはそれについてまだ何も学んでいません。 –

+0

@Jonno_FTW:cool。ここでは「メイン」以外のモナドは使用されていないことに注意してください。 – yairchu

0

これを行うには、少なくとも2つの方法があります。

あなたが最初の項目を見て、そこに残りの項目を比較することができます:

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でもありません。


あなたの質問にはまったく答えられませんでした。誰かがGoogle経由であなたの質問に遭遇した場合、これをCWとしてマークしてください。

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の答えは、実際にオイラー問題を解決する上で、より便利かもしれません:)

0

hexag = [ n*(2*n-1) | n <- [40755..]] 
penta = [ n*(3*n-1)/2 | n <- [40755..]] 
trian = [ n*(n+1)/2 | n <- [40755..]] 

あなたは、例えば1つのリストを生成することがありました:最も簡単な方法は、わずか

よりもむしろ3つのリスト(余分n引数の除去に注意してください)との契約問題を再指定することです

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)追加することができます。

同様の代数単純化を他の2つの関数に適用することができ、それらをすべて関数の一致にパラメータを累積することで運ぶことができます。

つまり、この問題に取り組むより効率的な方法があります。

関連する問題