Tracks
/
Common Lisp
Common Lisp
/
Übungen
/
Der Schlüssel zum Vergleich
Der Schlüssel zum Vergleich

Der Schlüssel zum Vergleich

Lernübung

Einführung

Gleichheit

Common Lisp hat viele verschiedene Gleichheitsprädikate. Das unterscheidet sich von anderen Programmiersprachen, die vielleicht nur ein oder zwei haben (zum Beispiel == und ===). Einige dieser Prädikate in Common Lisp sind typspezifisch, andere sind generisch. Hier geht es um die letzteren.

Es gibt vier generische Gleichheitsprädikate, die sich darin unterscheiden, wie streng sie sind, was sie als „gleich“ betrachten. Sie lauten, von der restriktivsten bis zur am wenigsten restriktiven: eq, eql, equal und equalp.

Eine kurze Zusammenstellung von Definitionen (ein paar Details lassen wir weg) lautet so:

  • eq: definiert Gleichheit so, dass die beiden Objekte identisch sind. z. B.:
(eq 'a 'a)                 ; => T
(eq (list 1 2) (list 1 2)) ; => NIL
  • eql: definiert Gleichheit so, dass zwei Zahlen denselben Typ und denselben Wert haben, zwei Zeichen gleich sind, oder für alles andere, wenn sie eq sind. z. B.:
(eql 1 1)     ; => T
(eql #\a #\a) ; => T
(eql 1 1.0)   ; => NIL
(eql #\a #\A) ; => NIL
  • equal: definiert Gleichheit so: Zwei Listen sind equal, wenn jedes Element ebenfalls equal ist; zwei Strings sind equal, wenn jedes Element eql ist; zwei Arrays sind equal, wenn sie eq sind; alles andere ist equal, wenn es eql ist. z. B.:
(equal (list 1 2) (list 1 2)) ; => T
(equal #(1 2) #(1 2))         ; => NIL
(equal "foo" "foo")           ; => T
  • equalp: definiert Gleichheit so: Strings und Zeichen werden ohne Berücksichtigung der Groß- und Kleinschreibung verglichen; Zahlen werden mit einer gewissen Typumwandlung verglichen; Listen und Arrays sind equalp, wenn jedes Element ebenfalls equalp ist, Strukturen, wenn sie denselben Typ haben und alle Slots equalp sind, und Hash-Tabellen, wenn ihre Schlüssel und Werte equalp sind. z. B.:
(equalp "foo" "FoO")                          ; => T
(equalp 3 3.0)                                ; => T
(equalp (make-a-structure :slot1 1 :slot2 2) 
        (make-a-structure :slot1 1 :slot2 2)) ; => T

Anleitung

Leslie, das Lisp-Alien, programmiert einen Labyrinth-Roboter (wie junge Lisp-Aliens das nun einmal tun) und braucht dabei etwas Hilfe. Das Labyrinth besteht aus einer Reihe von Räumen. Jeder Raum hat mehrere Türen zur Auswahl. Jede Tür braucht einen Schlüssel. Wenn du an einer Tür den falschen Schlüssel benutzt, explodiert sie wahrscheinlich (keine Sorge, dem Roboter passiert nichts, aber die Brandspuren wieder wegzupolieren ist für Leslie ziemlich ärgerlich). Wenn der Roboter keinen Schlüssel hat, der irgendeine Tür öffnet, dann explodiert der ganze Raum! (Noch einmal: keine Sorge, es geht nichts kaputt, aber das Saubermachen ist lästig.)

Du sollst Leslie dabei helfen, dem Roboter den richtigen Schlüssel für jeden Raum zu geben. Der Roboter probiert den Schlüssel der Reihe nach an jeder Tür im Raum aus und geht durch die erste Tür, die sich öffnet.

Jeder Test steht für ein Labyrinth und jede Assertion ist ein Raum. Du musst Prädikatfunktionen schreiben, die zu T ausgewertet werden, wenn die Argumente gleich sind, und zu NIL, wenn nicht.

1. Das Labyrinth der Objektgleichheit

Dieses Labyrinth hat nur einen einzigen Raum. Du musst eine Funktion bereitstellen, die feststellen kann, ob zwei Objekte dasselbe Objekt sind.

Zum Beispiel:

a                         ; => "pizza"
b                         ; => "pizza"

(key-object-identity a a) ; => T
(key-object-identity a b) ; => NIL

denn obwohl a und b gleich aussehen, sind sie nicht dasselbe Objekt.

2. Das Labyrinth der Zahlen

Dieses Labyrinth hat zwei Räume. Der erste hat eine Tür, die sich öffnen lässt, wenn dein Schlüssel feststellen kann, ob zwei Zahlen strikt gleich sind. Der zweite Raum braucht einen Schlüssel, der beim Prüfen, ob Zahlen gleich sind, etwas flexibler ist.

Zum Beispiel:

a                                    ; => 13
b                                    ; => 13.0
c                                    ; => 13

(key-numbers a b)                    ; => NIL
(key-numbers a c)                    ; => T
(key-numbers-of-different-types a b) ; => T

denn obwohl a und b numerisch gleich sind, haben sie verschiedene Typen.

3. Das Labyrinth der Zeichen

Dieses Labyrinth hat zwei Räume. Der erste hat eine Tür, die sich öffnen lässt, wenn dein Schlüssel feststellen kann, ob zwei Zeichen strikt gleich sind. Der zweite Raum braucht einen Schlüssel, der einen Vergleich der Zeichen ohne Beachtung der Groß- und Kleinschreibung erlaubt.

Zum Beispiel:

a                                       ; => #\X
b                                       ; => #\x
c                                       ; => #\X

(key-characters a b)                    ; => NIL
(key-characters a c)                    ; => T
(key-characters-case-insensitively a b) ; => T

denn nur sehr großzügige Gleichheitsprädikate ignorieren die Groß- und Kleinschreibung, wenn sie zwei Zeichen vergleichen.

4. Das Labyrinth der Strings

Wie im Labyrinth der Zeichen braucht der erste Raum einen Schlüssel, der prüft, ob zwei Strings gleich sind; der zweite Raum braucht einen Schlüssel, der einen Vergleich ohne Beachtung der Groß- und Kleinschreibung erlaubt.

Zum Beispiel:

a                                    ; => "pizza"
b                                    ; => "PIZZA"
c                                    ; => "pizza"

(key-strings a b)                    ; => NIL
(key-strings a c)                    ; => T
(key-strings-case-insensitively a b) ; => T

denn nur sehr großzügige Gleichheitsprädikate ignorieren die Groß- und Kleinschreibung, wenn sie zwei Strings vergleichen.

5. Das Labyrinth der Conses

Dies ist ein großes Labyrinth mit vielen Räumen. Jeder Raum braucht einen Schlüssel, der prüft, ob die Conses die Dinge, die gleich sind, enthalten. Jeder Raum prüft die Gleichheit von Conses mit unterschiedlichen Inhalten: Symbole, Zahlen, Zeichen, und für manche brauchst du flexiblere Gleichheitsdefinitionen für diese Inhalte.

Zum Beispiel:

syms-a                                     ; => (left . right)
syms-b                                     ; => (up . down)
syms-c                                     ; => (left . right)
chars-a                                    ; => (#\x . #\y)
chars-b                                    ; => (#\x . #\Y)
chars-c                                    ; => (#\x . #\y)
nums-a                                     ; => (13 . 23)
nums-b                                     ; => (13 . 23.0)
nums-c                                     ; => (13 . 23)


(key-conses-of-symbols syms-a syms-b)      ; => NIL
(key-conses-of-symbols syms-a syms-c)      ; => T

(key-conses-of-characters chars-a chars-b) ; => NIL
(key-conses-of-characters chars-a chars-c) ; => T
(key-conses-of-characters-case-insensitively 
  chars-a chars-b)                         ; => T

(key-conses-of-numbers nums-a nums-b)      ; => NIL
(key-conses-of-numbers nums-a nums-c)      ; => T
(key-conses-of-numbers-of-different-types 
  nums-a nums-b)                           ; => T

denn selbst ein Gleichheitsprädikat, das in ein Cons hineinschaut, ist vielleicht noch nicht großzügig genug, um beim Vergleichen die Groß- und Kleinschreibung oder den numerischen Typ zu ignorieren.

6. Das Labyrinth der Arrays

Dieses Labyrinth ist einfacher und hat nur zwei Räume. Der erste braucht einen Schlüssel, der prüft, ob die Arrays dieselben Arrays sind. Der zweite braucht einen Schlüssel, der den Inhalt der Arrays prüft.

Zum Beispiel:

a                        ; => #[13 23]
b                        ; => #[13 23]
c                        ; => #[13 23.0]

(key-arrays a b)         ; => NIL
(key-arrays a c)         ; => NIL
(key-arrays-loosely a b) ; => T
(key-arrays-loosely a c) ; => T

denn nur sehr großzügige Gleichheitsprüfer stellen fest, ob die Inhalte der Arrays gleich sind.

Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab
Common Lisp Exercism

Bereit, mit Der Schlüssel zum Vergleich zu starten?

Melde dich bei Exercism an, um Common Lisp mit 27 Konzepte92 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.