Tracks
/
Swift
Swift
/
Übungen
/
Die 1. Regel des Poetry-Clubs
Die 1. Regel des Poetry-Clubs

Die 1. Regel des Poetry-Clubs

Lernübung

Einführung

Importieren

Swift bietet in seiner Standardbibliothek viele Funktionen, aber du kannst auf viele weitere Möglichkeiten zugreifen, indem du externe Bibliotheken und Frameworks importierst. Diese Module können direkt aus dem Swift-Projekt stammen (etwa Swift Argument Parser), aus Apples Plattform-Frameworks (etwa Foundation und das Network Framework) oder aus Open-Source-Bibliotheken von Drittanbietern (etwa SwiftyBeaver).

Kernmodule wie Foundation, eine der am weitesten verbreiteten Bibliotheken in Swift, sind Teil der Swift-Toolchain. Bibliotheken von Drittanbietern müssen deiner Projektkonfiguration hinzugefügt werden (zum Beispiel mit dem Swift Package Manager), bevor du sie importieren kannst.

Um ein Modul zu importieren, schreibst du das Schlüsselwort import gefolgt vom Namen des Moduls. Foundation importierst du zum Beispiel, indem du Folgendes in dein Programm einfügst:

import Foundation

Wenn du ein Modul importierst, stehen seine Typen, Methoden und Funktionen in deinem Code zur Verfügung. Wenn du beispielsweise Foundation importierst, wird String um nützliche Hilfsmethoden wie components(separatedBy:) erweitert.

Nach Konvention stehen import-Anweisungen am Anfang einer Swift-Datei, damit jeder, der den Code liest, die Abhängigkeiten sofort sieht.

String-Indizierung

Auf einzelne Zeichen in einem String kannst du mit der Indexschreibweise zugreifen, die du von Arrays kennst. Die Indizes, die für Strings verwendet werden, sind jedoch keine Ganzzahlen und du kannst nicht direkt mit ihnen arbeiten. Stattdessen musst du sie ausgehend von einem anderen bekannten Index berechnen, etwa startIndex, der auf die Position des ersten Zeichens in einem nicht leeren String zeigt. Dafür nutzt du die Methoden aus den Bibliotheken String und NSString (wenn das Modul Foundation importiert ist, haben Strings in Swift Zugriff auf alle Eigenschaften und Methoden von NSString).

Zum Beispiel bei folgendem String:

let csv = "apple,pear,peach,orange,cherry,lime,goosberry"

Du kannst nicht csv[21] schreiben, um das „g“ in „orange“ zu bekommen. Stattdessen musst du einen Wert vom Typ String.Index berechnen und diesen Index verwenden. Beachte, dass diese Indizes nicht dafür gedacht sind, von Menschen direkt gelesen zu werden. Sie werden als opake Indizes bezeichnet, denn Menschen müssen nicht wissen, was in ihnen steckt.

let index = csv.index(csv.startIndex, offsetBy: 21)
csv[index]
// "g"
print(index)
// prints Index(_rawBits: 1376513)

Beachte aber: Wenn der Offset kein gültiger Index ist, also wenn er einen Index vor startIndex oder nach endIndex ergeben würde, löst die Operation einen Fehler aus und das Programm stürzt ab. Um das zu verhindern, kannst du einen begrenzenden Index angeben. Dieser gibt einen optionalen Index zurück und liefert nil für Indizes, die sonst ungültig wären.

let tooFar = csv.index(csv.startIndex, offsetBy: 200)
// error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
let tooFarButSafe = csv.index(csv.startIndex, offsetBy: 200, limitedBy: csv.endIndex)
// nil

Außerdem lassen sich Indizes nicht zwischen Strings teilen. Wenn du zum Beispiel mit dem oben berechneten index des „g“ in „orange“ in den String fam = "This is my family: 👨‍👩‍👦‍👦, this is our dog: 🐶, this is our cat: 🐱!" indexieren willst, also fam[index], dann stürzt dein Programm ab.

Dafür gibt es viele Gründe, aber im Kern laufen sie alle darauf hinaus, dass „Unicode knifflig ist“.

Im Allgemeinen gilt: Wenn du wahlfreien Zugriff auf einzelne Zeichen brauchst, solltest du wahrscheinlich eine andere Datenstruktur verwenden, etwa Array<Character>.

Einige nützliche Methoden

Swift bietet die Methoden first und last, um das erste und letzte Zeichen eines Strings zu erhalten. Diese Methoden geben ein optionales Zeichen zurück. Ist der String leer, liefern sie nil.

let str = "Hello, world!"
print(str.first) // Prints Optional("H")
print(str.last)  // Prints Optional("!")

Du kannst auch die Methoden prefix und suffix verwenden, um einen Teilstring eines Strings zu erhalten. Diese Methoden nehmen eine Ganzzahl als Argument und geben einen Teilstring zurück, der die ersten bzw. letzten n Zeichen des Strings enthält.

let str = "Hello, world!"
print(str.prefix(5)) // Prints "Hello"
print(str.suffix(6)) // Prints "world!"

String-Methoden

Die Arbeit mit Text ist eine häufige Aufgabe beim Programmieren. Swift bietet zusammen mit dem Foundation-Framework viele praktische Methoden und Eigenschaften, um Strings zu untersuchen, umzuwandeln und zu bearbeiten.

Strings aufteilen mit components(separatedBy:)

Um einen String anhand eines Trennzeichens in ein Array aus Teilstrings aufzuteilen, verwendest du components(separatedBy:) (erfordert den Import von Foundation):

import Foundation

let sentence = "Hello, world!"
let words = sentence.components(separatedBy: " ")
print(words) // Prints ["Hello,", "world!"]

Präfixe und Suffixe prüfen mit hasPrefix(_:) und hasSuffix(_:)

Um zu prüfen, ob ein String mit einer bestimmten Zeichenfolge beginnt oder endet, verwendest du hasPrefix(_:) und hasSuffix(_:):

let greeting = "Hello, world!"
print(greeting.hasPrefix("Hello"))  // Prints true
print(greeting.hasSuffix("world!")) // Prints true

Groß- und Kleinschreibung ändern

Die Groß- und Kleinschreibung eines Strings kannst du mit diesen Standardmethoden und -eigenschaften ändern:

  • lowercased(): Gibt eine Kopie des Strings in Kleinbuchstaben zurück.
  • uppercased(): Gibt eine Kopie des Strings in Großbuchstaben zurück.
  • capitalized: Gibt eine Kopie zurück, in der der erste Buchstabe jedes Wortes großgeschrieben ist (aus Foundation).
let greeting = "hello, world!"
print(greeting.lowercased())  // Prints "hello, world!"
print(greeting.uppercased())  // Prints "HELLO, WORLD!"
print(greeting.capitalized)   // Prints "Hello, World!"

Teilstrings ersetzen mit replacingOccurrences(of:with:)

Um alle Vorkommen eines Ziel-Teilstrings durch einen anderen String zu ersetzen, verwendest du replacingOccurrences(of:with:) (aus Foundation):

let greeting = "Hello, world!"
let updated = greeting.replacingOccurrences(of: "world", with: "Swift")
print(updated) // Prints "Hello, Swift!"

Strings verbinden mit joined(separator:)

Die Methode joined(separator:) gehört zu Sammlungen von Strings, etwa [String]. Sie fügt Elemente mit einem Trennzeichen zu einem einzigen String zusammen:

let words = ["Hello", "world"]
let sentence = words.joined(separator: ", ")
print(sentence) // Prints "Hello, world"

Anleitung

In der Stadt hat ein neuer Poesieclub eröffnet, und du überlegst, hinzugehen. Weil es in der Vergangenheit Zwischenfälle gegeben hat, hat der Club eine ganz eigene Einlasspolitik, die du beherrschen musst, bevor du einen Eintritt versuchst.

Der Poesieclub hat zwei Türen, und beide sind bewacht. Um hineinzukommen, musst du das Passwort des Tages herausfinden:

1. Einen String in einzelne Zeilen aufteilen

Als Erstes musst du das Gedicht in einzelne Zeilen aufteilen. Der Wächter sagt ein Gedicht auf, und du musst es in Zeilen aufteilen.

Implementiere die Funktion splitOnNewlines, die einen String entgegennimmt und ihn anhand des Zeilenumbruchzeichens als Trennzeichen in ein Array aus Strings aufteilt. Die Funktion sollte ein Array aus Strings zurückgeben, in dem jeder String eine Zeile des Gedichts ist.

splitOnNewlines("Hello.\nHow are you?\n\nI'm doing fine.")
// returns ["Hello." ,"How are you?", "", "I'm doing fine"].

2. Die Vordertür

  1. Der Wächter sagt ein Gedicht auf.
  2. Du musst das Gedicht in einzelne Zeilen aufteilen.
  3. Du musst den ersten Buchstaben jeder Zeile nehmen.
    • Wenn die Zeile leer ist, solltest du stattdessen _ verwenden.
  4. Du musst die Buchstaben zusammensetzen, die dann ein Wort ergeben.

Zum Beispiel ist einer ihrer Lieblingsautoren Michael Lockwood, der das folgende Akrostichon geschrieben hat. Das bedeutet, dass die ersten Buchstaben der einzelnen Sätze ein Wort ergeben:

Stands so high
Huge hooves too
Impatiently waits for
Reins and harness
Eager to leave

Wenn der Wächter das Gedicht aufsagt, teilst du es in einzelne Zeilen auf und antwortest mit den ersten Buchstaben jeder Zeile, also ["S", "H", "I", "R", "E"].

Der Wächter gibt dir dann das Wort zurück, das die Buchstaben aus deiner Antwort bilden, damit du es großschreibst. Das Passwort, das du am Ende zurückgibst, ist "SHIRE", und du kommst hinein.

Implementiere die Funktion frontDoorPassword, die einen String entgegennimmt, der das Gedicht darstellt. Die Funktion sollte das Passwort zurückgeben, das du dem Wächter geben würdest.

frontDoorPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nReins and harness\nEager to leave")
// returns "SHIRE"

3. Die Hintertür

Im hinteren Teil des Clubs findest du die berühmtesten Dichter, so etwas wie der VIP-Bereich. Weil das nicht für alle gedacht ist, ist der Ablauf an der Hintertür etwas komplizierter.

  1. Der Wächter sagt ein Gedicht auf.
  2. Du musst das Gedicht in Zeilen aufteilen.
  3. Du musst den letzten Buchstaben jeder Zeile nehmen.
    • Die Zeile hat manchmal Leerzeichen am Ende, die du entfernen musst.
  4. Du musst die Buchstaben zusammensetzen und dann ", please" an das Ende des Wortes anhängen, das die Buchstaben ergeben.

Zum Beispiel ist das vorher erwähnte Gedicht auch ein Telestichon, was bedeutet, dass die letzten Buchstaben der einzelnen Sätze ein Wort ergeben:

Stands so high
Huge hooves too
Impatiently waits for
Reins and harness
Eager to leave

Wenn der Wächter das Gedicht aufsagt, teilst du es in einzelne Zeilen auf, entfernst alle Leerzeichen am Ende und antwortest mit den ersten Buchstaben jeder Zeile, also ["h", "o", "r", "s", "e"].

Der Wächter gibt dir dann das Wort zurück, das die Buchstaben aus deiner Antwort bilden, damit du es großschreibst und ", please" anhängst. Das Passwort, das du am Ende zurückgibst, ist "horse, please", und du kommst hinein.

Implementiere die Funktion backDoorPassword, die einen String entgegennimmt, der das Gedicht darstellt. Die Funktion sollte das Passwort zurückgeben, das du dem Wächter geben würdest.

backDoorPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nReins and harness\nEager to leave")
// returns "horse, please"

4. Der geheime Raum

Im hinteren Raum des Clubs gibt es noch eine Tür, die in den geheimen Raum führt, den nur die allerbesten Dichter betreten dürfen.

  1. Der Wächter sagt ein Gedicht auf.
  2. Du musst das Gedicht in Zeilen aufteilen.
  3. Du musst den iten Buchstaben der iten Zeile nehmen.
  4. Du musst die Buchstaben zusammensetzen und dann "!" an das Ende des Wortes anhängen, das die Buchstaben ergeben.
  5. Du musst das Wort in Großbuchstaben umwandeln.

Zum Beispiel passt eine abgewandelte Version des vorher erwähnten Gedichts zu diesem Muster:

Stands so high
Huge hooves too
Impatiently waits for
Rider with harness
Eager to leave

Wenn der Wächter das Gedicht aufsagt, teilst du es in einzelne Zeilen auf, entfernst alle Leerzeichen am Ende und antwortest mit den iten Buchstaben jeder Zeile, also ["S", "u", "p", "e", "r"].

Der Wächter gibt dir dann das Wort zurück, das die Buchstaben aus deiner Antwort bilden, damit du es in Großbuchstaben umwandelst und "!" anhängst. Das Passwort, das du am Ende zurückgibst, ist SUPER!, und du kommst hinein.

Implementiere die Funktion secretRoomPassword, die einen String entgegennimmt, der das Gedicht darstellt. Die Funktion sollte das Passwort zurückgeben, das du dem Wächter geben würdest.

secretRoomPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nRider with harness\nEager to leave")
// returns "SUPER!"
Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab
Swift Exercism

Bereit, mit Die 1. Regel des Poetry-Clubs zu starten?

Melde dich bei Exercism an, um Swift mit 35 Konzepte116 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.