2016-04-02 2 views
0

Die folgende funktioniert:Summe von Vielfachen von 3 und 5 unter 1000 in Haskell

sdb n = sum [n,n*2..999] 
main = print $ sdb 3 + sdb 5 - sdb 15 

Aber es ist nicht so effizient, da es 999/n-mal jedes Mal sdb genannt wird summiert hat. wenn ich sdb neu geschrieben:

sdb n = 
    let x = quot 999 n 
    in n*x*(x+1)/2 

und runhaskell der gesamte Code, habe ich eine ganze Seite des Irrtums. Summieren it up:

... No instance for (Show a0) arising from a use of `print' 
... No instance for (Integral a0) arising from a use of `sdb' 
... No instance for (Num a0) arising from a use of `-' 

Ich habe Typdeklaration für sdb:

sdb :: Integer -> Integer 

aber ich habe einen anderen Fehler:

No instance for (Fractional Integer) arising from a use of `/' 
    Possible fix: add an instance declaration for (Fractional Integer) 
    In the expression: n * x * (x + 1)/2 
    In the expression: let x = quot 999 n in n * x * (x + 1)/2 
    In an equation for `sdb': 
     sdb n = let x = quot 999 n in n * x * (x + 1)/2 

ich nicht bekommen.

  1. Was soll ich korrigieren? Kannst du mir auch erklären, warum ich diese Fehler bekommen habe? Gelöst: Ich änderte / mit div.

  2. Gibt es einen idiomatischen und/oder prägnanten Weg, denselben Algorithmus zu schreiben?

+1

Es ist 'Integer'. 'Integral' ist eine Typklasse. – zakyggaps

+0

danke, korrigiert, aber ich bekomme immer noch einen Fehler – Pigna

+1

'/' in 'n * x * (x + 1)/2 'ist nur für Bruchteile definiert. Sie können stattdessen "quot" oder "div" verwenden. – zakyggaps

Antwort

0

Wie wäre es damit:

sum [x | x <- [1..999], x `mod` 3 == 0 || x `mod` 5 == 0] 

bearbeiten

Für eine kleine obere wie 999 gebunden dies wäre ein idiomatischen und prägnante Art und Weise, aber wenn eine allgemeinere Lösung erforderlich ist, , wäre oben zu langsam. Hier ist ein besserer Ansatz, die in ähnlicher Weise die Fragen an sich selbst, verwendet „Gauß 'Trick“ Zahlen zu summieren teilbar durch n:

sumOfMults :: Integral a => a -> a -> a -> a 
sumOfMults n1 n2 m = sdb n1 + sdb n2 - sdb (lcm n1 n2) where 
    sdb n = let x = m `div` n 
      in n * x * (x + 1) `div` 2 
+1

kürzer, natürlich, aber langsamer:/und es ist ein anderer Algorithmus von mir. Ich fragte nach einem idiomatischen und/oder prägnanten Weg, den gleichen Algorithmus zu schreiben, weil ich neu bei Haskell bin und ich die beste Syntax lernen will – Pigna

+1

Es ist mehr idiomatisch und prägnant. Wenn man diesen Code betrachtet, ist es sehr einfach zu sehen, was tatsächlich vor sich geht, es ist fast wie eine Spezifikation des Problems selbst (Summe aller Zahlen von 1 bis 999, die durch 3 oder 5 teilbar sind). Ich stimme zu, dass es langsamer ist, aber das wäre nur von Bedeutung, wenn Sie mit Obergrenzen arbeiten, die viel höher sind als '999'. –

+0

oh sicher, aber ich habe 999 nur als Beispiel genommen. Tut mir leid, dass ich nicht klar bin! – Pigna

Verwandte Themen