Frage

Ich tue Projekt euler Frage 136 und kam mit der nach dem Beispiel zu testen gegeben:

module Main where
import Data.List

unsum x y z n = (y > 0) && (z > 0) && (((x*x)  - (y*y)- (z*z)) == n) && ((x - y) == (y - z))
answer = snub $ takeWhile (<100) [n|x<-[1..],d<-[1..x`div`2],n<-[x..100],y<-[x-d],z<-[y-d], unsum x y z n ]
    where 
      snub [] = []
      snub (x:xs) | elem x xs = snub (filter (/=x) xs)
                  | otherwise = x : snub xs

snub werden alle Zahlen entfernen, die Duplikate aus einer Liste enthalten sind.

Das Beispiel soll 25 Lösungen für n geben, wo x^2 - y^2 - z^2 == n und alle Zahlen positiv sind (oder so entnehme ich von der Frage) und sind eine arithmetische Progression, so dass x-y == y-z. Aber wenn ich den Code verwenden, wird eine Liste von 11 Lösungen für n zurückgegeben.

Was ich in meiner Liste Verständnis falsch gemacht haben und gibt es Optimierungen ich verpasst haben, aus?

War es hilfreich?

Lösung

Nummer 1

habe ich bei dieser Frage einen Versuch und fand, dass dies die Folge von ns war, die ich kam mit

[4,3,16,12,7,20,11,48,28,19,80,44,23,52,112,31,68,76,1156,43,176,559...

Das bedeutet möglicherweise, dass Ihr takeWhile (<100) die falsche Filterfunktion zu verwenden, um zu bestimmen, wann man aufhören. Über einen entsprechenden Hinweis, habe ich versucht, läuft folgendermaßen aus:

answer = snub $ filter (<=100) $ takeWhile (<200) [...listcomprehension...]

Aber ich gab auf, weil es zu lange fand. Das führt mich zu Punkt 2.


Punkt 2

Im Hinblick auf die Optimierungen, schauen, was Ihre Liste Verständnis in Bezug auf die Rohausgangssignal produziert.

Main> take 30 [(x,y,z,n) | x<-[1..], d<-[1..x`div`2], n<-[x..100], y<-[x-d], z<-[y-d]]
[(2,1,0,2),(2,1,0,3),(2,1,0,4),(2,1,0,5),(2,1,0,6),(2,1,0,7),(2,1,0,8),(2,1,0,9),
(2,1,0,10),(2,1,0,11),(2,1,0,12),(2,1,0,13),(2,1,0,14),(2,1,0,15),(2,1,0,16),(2,1,0,17),
(2,1,0,18),(2,1,0,19),(2,1,0,20),(2,1,0,21),(2,1,0,22),(2,1,0,23),(2,1,0,24),(2,1,0,25),
(2,1,0,26),(2,1,0,27),(2,1,0,28),(2,1,0,29),(2,1,0,30),(2,1,0,31)]

Das bedeutet, dass unsum auf jeder Kombination von x y z bezeichnet wird, und n, die ein wenig redundant ist, da wir wissen, dass 2^2 - 1^2 - 0^2 = 3.

Es ist auch viel einfacher und viel weniger redundant die Berechnung des n aus der Liste Verständnis (langsam, weil der oben) auf eine Funktion zu bewegen und nur Liste (x,y,z) Kombinationen zu verstehen, die gültig sind.

ns = map nsum [(x, x-d, x-d-d) | x <- [1..], d <- [1..x`div`2]]
nsum (x,y,z) = x^2 - y^2 - z^2

Dann ist es möglich, die Antwort von dieser unendlichen Liste zu berechnen, aber Vorsicht Takewhile zu verwenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top