2012-04-14 4 views
2

EDIT: Die Lösung ist das Ersetzen der '(1) mit (Liste 1) in der ersten (lassen ...) Form. Das ist, weil ich versuchte, Literal-Daten zu ändern. Danke für die Hilfe! (Ich würde Upvotes geben, aber anscheinend brauchen Sie 15 Ruf ...)Unerwartete Listenduplikation unter Verwendung der Sortierung mit gebräuchlicher Lisp

Dies ist meine erste Post auf dieser Website.

Ich war einige Project Euler Probleme heute lösen und stieß ich auf einige unerwartete Liste Sortierverhalten (na ja, zumindest für mich) in Common Lisp:

habe ich eine Funktion, die alle der echten Teiler einer Zahl findet x:

(defun divisors (x) 
    "Finds all of the proper divisors of x." 
    (let ((sq (sqrt x)) (divs '(1))) 
     (when (integerp sq) (push sq divs)) 
     (loop for i from 2 to (1- (floor sq)) do 
     (let ((div (/ x i))) 
      (when (integerp div) 
       (push i divs) 
       (push div divs)))) 
    divs)) 

Diese Funktion funktioniert hervorragend. Zum Beispiel:

(divisors 100) 
==> (20 5 25 4 50 2 10 1) 

Das Problem entsteht, wenn ich versuche, die resultierende Liste zu sortieren:

(sort (divisors 100) #'<) 
==> (1 2 4 5 10 20 25 50) 

Nun, das gut funktionierte. Aber was passiert, wenn ich wieder Divisoren anrufe?

(divisors 100) 
==> (20 5 25 4 50 2 10 1 2 4 5 10 20 25 50) 

Was? Vielleicht, wenn ich eine andere Anzahl versuchen ...

(divisors 33) 
==> (11 3 1 2 4 5 10 20 25 50) 

Die Teilern aus früheren Abfragen sind persistent, nachdem ich die Ergebnisliste sortieren. Wenn ich die Funktion neu kompiliere, bekomme ich keine Fehler, bis ich die resultierende Liste wieder sortiere. Ich nehme an, ich habe irgendwo in der Funktionsdefinition versaut, aber ich bin ziemlich neu in Lisp und ich kann den Fehler nicht finden. Könnte es ein Problem mit den verschachtelten (Let ...) Formen sein?

Vielen Dank im Voraus!

Antwort

9

Häufig gefragt.

Sie haben die Literaldaten geändert. Sie müssen neue Daten hinzufügen. Verwenden Sie die Funktion LIST oder die Funktion, um eine Kopie zu erstellen.

+0

Danke für die Antwort! Könnten Sie expliziter sein? Ich fürchte, ich verstehe es nicht. –

+3

@Lisper ''(1)' ist ein Listenliteral. Die Auswirkungen der Verwendung von destruktiven Operationen auf Literale sind nicht definiert, und "Sortieren" ist eine destruktive Operation. Verwenden Sie die Funktion "list", um Listen zu erstellen. –

3

Rainer hat Recht; wenn es nicht offensichtlich ist, kann der Code mit dieser Änderung behoben werden:

(let ((sq (sqrt x)) (divs (list 1))) 
+0

Rainer, nicht Ranier –

+0

Huch - Entschuldigung, Rainer! –

Verwandte Themen