Ich bin ein Lisp Anfänger. Ich versuche, eine rekursive Funktion zur Berechnung der Anzahl der Begriffe in einem Collatz sequence (für Problem 14 in Project Euler) Memo. Mein Code als die noch ist:Wie stelle ich eine rekursive Funktion in Lisp fest?
(defun collatz-steps (n)
(if (= 1 n) 0
(if (evenp n)
(1+ (collatz-steps (/ n 2)))
(1+ (collatz-steps (1+ (* 3 n)))))))
(defun p14()
(defvar m-collatz-steps (memoize #'collatz-steps))
(let
((maxsteps (funcall m-collatz-steps 2))
(n 2)
(steps))
(loop for i from 1 to 1000000
do
(setq steps (funcall m-collatz-steps i))
(cond
((> steps maxsteps)
(setq maxsteps steps)
(setq n i))
(t())))
n))
(defun memoize (fn)
(let ((cache (make-hash-table :test #'equal)))
#'(lambda (&rest args)
(multiple-value-bind
(result exists)
(gethash args cache)
(if exists
result
(setf (gethash args cache)
(apply fn args)))))))
Die memoize Funktion ist das gleiche wie die in dem On Lisp Buch gegeben ist.
Dieser Code gibt keine Beschleunigung im Vergleich zu der nicht memoisierten Version. Ich glaube, es liegt an den rekursiven Aufrufen, die die nicht memoisierte Version der Funktion aufrufen, die den Zweck vereitelt. Was ist in diesem Fall die richtige Art, die Memo-Erstellung hier durchzuführen? Gibt es eine Möglichkeit, alle Aufrufe der ursprünglichen Funktion die Memo-Version selbst aufrufen zu lassen, ohne das spezielle m-collatz-steps-Symbol zu benötigen?
EDIT: Korrigierte der Code
(defvar m-collatz-steps (memoize #'collatz-steps))
zu haben, das ist, was ich in meinem Code hatte. Vor der Bearbeitung hatte ich fälschlicherweise gesagt:
(defvar collatz-steps (memoize #'collatz-steps))
zu sehen, dass Fehler gab mir eine andere Idee, und ich versuchte, diese letzte defvar mit sich selbst und das Ändern der rekursiven Aufrufe zu
(1+ (funcall collatz-steps (/ n 2)))
(1+ (funcall collatz-steps (1+ (* 3 n))))
Diese zu führen scheint zu die Memoisierung (Beschleunigung von etwa 60 Sekunden auf 1,5 Sekunden), erfordert jedoch das Ändern der ursprünglichen Funktion. Gibt es eine sauberere Lösung, bei der die ursprüngliche Funktion nicht verändert wird?
Dies würde funktionieren, wenn Sie das Setf nach der Funktionsdefinition –