Ich habe das folgende (ungolfed) Haskell-Programm für die Code-Golf- Herausforderung erstellt, bei der die ersten Werte von A229037 berechnet wurden .
Dies ist meine vorgeschlagene Lösung zur Berechnung des ten Wertes:
a n | n<1 = 0
| n<3 = 1
| otherwise = head (goods n)
goods n = [x | x <- [1..], isGood x n]
isGood x n = and [ x - a(n-k) /= a(n-k) - a(n-k-k) || a(n-k-k) == 0 | k <- [1..n] ]
Beachten Sie, dass Haskell diese Werte nicht automatisch zwischenspeichert oder speichert.
Die OEIS-Seite für die Sequenz gibt die Tatsache an, dass , so dass das durch ersetzt werden könnte , da der Algorithmus niemals ein größer als .x n + 1[1..]
[1..(n+1)/2]
Beim Versuch, Funktionsaufrufe zu zählen, habe ich die folgende Obergrenze , die Anzahl der Funktionsaufrufe, die der Algorithmus für eine Eingabe :n
Ich habe die endgültige Formel in Mathematica eingefügt:
RSolve[{T[n] == 2*T[n - 1]*n*(n + 1), T[1] == 1}, T[n], n]
Und bekam nach einer kleinen Vereinfachung:
Das durchschnittliche Verhältnis zwischen diesem und der Ausführungszeit des Haskell-Programms für beträgt und die Standardabweichung der Verhältnisse liegt bei . (Seltsamerweise scheint das logarithmische Diagramm der Verhältnisse eine gerade Linie zu sein).2,0 ≤ 10 39 6,0 ≤ 10 39
Die Verhältnisse mit der ersten Linie, die , haben einen Mittelwert und eine Standardabweichung von bzw. , aber ihre Darstellung springt viel herum.4,8 ≤ 10 6 1,8 ≤ 10 6
Wie kann ich die zeitliche Komplexität dieses Algorithmus besser einschätzen?
Hier ist der Algorithmus in gültigem C (minus Vorwärtsdeklarationen), der meiner Meinung nach in etwa dem Haskell-Code entspricht:
int a(int n){
if (n < 1) {
return 0;
} else if (n < 3) {
return 1;
} else {
return lowestValid(n);
}
}
int lowestValid(int n){
int possible = 1; // Without checking, we know that this will not exceed (n+1)/2
while (notGood(possible, n)) {
possible++;
}
return possible;
}
int notGood(int possible, int n){
int k = 1;
while (k <= n) {
if ( ((possible - a(n-k)) == (a(n-k) - a(n-2*k))) && (a(n-2*k) != 0) ) {
return 1;
} else {
k++;
}
}
return 0;
}
Die C-Version benötigt ungefähr 5 Minuten, um zu berechnen, und die Haskell-Version benötigt ungefähr die gleiche Zeit für .a ( 19 )
Die ersten Male der Versionen:
Haskell: [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0e-2,3.0e-2,9.0e-2,0.34,1.42,11.77,71.68,184.37,1815.91]
C: [2.0e-6, 1.0e-6, 1.0e-6, 2.0e-6, 1.0e-6, 6.0e-6, 0.00003,0.00027, 0.002209, 0.005127, 0.016665, 0.080549, 0.243611, 0.821537, 4.56265, 24.2044, 272.212]
quelle
a
Antworten:
Sie können Ihre Wiederholung als Insbesondere . Dies bedeutet, dass die Sequenz sehr schnell wächst, insbesondere Daher ist Dies bedeutet, dass Und somit Dies verbessert Ihre Bindung durch eine Quadratwurzel.
quelle