Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.
Vorherige Überarbeitung | |||
— | gf_informatik:suchen_und_sortieren [2025-02-17 10:15] (aktuell) – [Aufgabe A3: Zäh Millione Kombinatione] hof | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | ====== Suchen und Sortieren ====== | ||
+ | |||
+ | Weiter zu [[gf_informatik: | ||
+ | |||
+ | Direkt zu [[gf_informatik: | ||
+ | |||
+ | ==== Einführung ==== | ||
+ | |||
+ | Das Ziel einer Suche ist es, in einer grossen Datenmenge möglichst schnell das gesuchte Element zu finden. Beispielsweise suchen wir in einem Lexikon oder Wörterbuch den Eintrag zu einem Begriff, im Telefonbuch die Nummer einer Person oder eines Geschäfts. Heutzutage suchen wir zumeist im Internet - aber wie schafft es [[https:// | ||
+ | |||
+ | ==== Lineare Suche ==== | ||
+ | < | ||
+ | Gäb si mir wenigschtens d Vorwahl\\ | ||
+ | Per favore\\ | ||
+ | De gäbs nume no zäh Millione Kombinatione, | ||
+ | 079 het si gseit\\ | ||
+ | „Du weisch immer no nüt“, het si gseit\\ | ||
+ | Nidmau tschüss het si gseit, ey\\ | ||
+ | Und i frage si ob ig ihri - tüt tüt tüt het si gseit, tüt tüt | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Der Sänger von _079_ will die Telefonnummer der Angebeteten unter allen möglichen Schweizer Mobilfunknummern (10-stellig) mit dem Präfix `079` herausfinden. Dafür probiert er sämtliche Nummern von `079 000 00 00` bis `079 999 99 99` durch, was natürlich ziemlich lange dauert... | ||
+ | #### Aufgabe A1 - 079 | ||
+ | |||
+ | **Tipp**: Höre oder lese den Liedtext genau ([[https:// | ||
+ | |||
+ | 1. Wie viele Telefonnummern muss der Sänger von _079_ durchprobieren? | ||
+ | 1. Wie lange dauert das Probieren einer Telefonnummer? | ||
+ | 1. Wie lange dauert die Suche nach der richtigen Nummer bei _079_? | ||
+ | 1. Wieso dauert es so lange? Was ist die Rechnung, die hinter der genannten Dauer steckt? | ||
+ | 1. Wie lange dauerte die Suche, wenn wir nicht einmal die Vorwahl kennen würden (aber wüssten, dass alle Nummern mit `0` beginnen)? | ||
+ | |||
+ | <nodisp 1> | ||
+ | ++++Lösung| | ||
+ | |||
+ | 1. 10 Mio - <q>De gäbs nume no zäh Millione Kombinatione, | ||
+ | 1. 20 Sekunden - <q>U weni nächär pro Minute drü vo de Nummere usprobier</ | ||
+ | 1. 6.5 Jahre - <q>De chönnts maximal nume sächsehalb Jahr lang ga</ | ||
+ | 1. $\frac{10\, | ||
+ | 1. Wir hätten nochmals zwei Dezimalstellen, | ||
+ | |||
+ | ++++ | ||
+ | </ | ||
+ | |||
+ | === Algorithmus === | ||
+ | Der einfachste Such-Algorithmus probiert alle Telefonnummern von der kleinsten zur grössten durch. Die Zeit für die Suche steigt proportional mit der Anzahl möglichen Nummern an - wir sagen auch, dass die Zeit **linear** mit der Grösse des Suchbereichs wächst, und sprechen von **Linearer Suche**. | ||
+ | |||
+ | Würden wir statt _079_ nicht einmal die Vorwahl kennen, wäre die Suche nochmals zwei Dezimalstellen länger (wenn alle Telefonnummern mit 0 beginnen). Wir müssten also statt 6.5 sogar über 600 Jahre suchen. | ||
+ | |||
+ | {{: | ||
+ | |||
+ | |||
+ | === Aufgabe A2: Lineare Suche in Python === | ||
+ | |||
+ | Betrachte folgenden Datensatz mit Namen und Telefonnummern. Wir haben zwei parallele Listen, die erste mit Namen, die zweite mit den dazugehörigen Telefonnummern. Am gleichen Index ist in der ersten Liste der Name, in der zweiten die Telefonnummer gespeichert. | ||
+ | |||
+ | Zum Beispiel finden für den Index `1` Anela in `names[1]` und ihre Nummer 0790000001 in `numbers[1]`. | ||
+ | |||
+ | <code python lineare_suche.py> | ||
+ | names = [' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | numbers = [' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | </ | ||
+ | - Schreibe eine Python-Funktion `linear_search(l, | ||
+ | - Test: Der Funktionsaufruf `print(linear_search(names, | ||
+ | - Nun wissen wir, dass die gesuchte Dame `Lyanna` (_die Geheimnisvolle_) heisst. Nutze nun diese Funktion, um die Telefonnummer von ' | ||
+ | |||
+ | **Achtung: | ||
+ | |||
+ | ++++Tipps (zuerst ohne Tipps versuchen!)| | ||
+ | - Gehe IN der Funktion die Liste `l` alle möglichen Indices (Positionen) durch. | ||
+ | - Vergleiche das Element an jedem Index mit dem gesuchten Wert `v`. | ||
+ | - Wenn es gleich ist: Gib den Index zurück. | ||
+ | - Ausserhalb der Funktion: Lese nun aus der **anderen** Liste das Element mit dem eben ermittelten Index aus. | ||
+ | ++++ | ||
+ | |||
+ | |||
+ | <nodisp 1> | ||
+ | ++++Lösung| | ||
+ | <code python> | ||
+ | def linear_search(l, | ||
+ | for i in range(len(l)): | ||
+ | if l[i] == v: | ||
+ | return i | ||
+ | return None | ||
+ | |||
+ | index = linear_search(names, | ||
+ | print(numbers[index]) | ||
+ | </ | ||
+ | ++++ | ||
+ | </ | ||
+ | |||
+ | === Aufgabe A3: Zäh Millione Kombinatione === | ||
+ | Für das kleine Telefonbuch oben ist es nicht so wichtig, wie schnell der Such-Algorithmus ist. Was aber, wenn wir wirklich alle 10 Millionen Kombinationen durchprobieren? | ||
+ | |||
+ | Für diese Aufgabe benötigst du zusätzlich eine weitere Python-Datei, | ||
+ | |||
+ | <code python> | ||
+ | from null79 import names, numbers | ||
+ | </ | ||
+ | |||
+ | Damit das funktioniert, | ||
+ | |||
+ | == Mit WebtigerPython == | ||
+ | Am einfachsten geht das mit [[https:// | ||
+ | |||
+ | == Mit TigerPython == | ||
+ | Lade die Datei [[https:// | ||
+ | |||
+ | Du kannst das Telefonbuch wie folgt importieren und den Namen für eine Telefonnummer herausfinden. Der Code muss im gleichen Ordner wie `null79.py` abgespeichert werden! | ||
+ | |||
+ | <code python> | ||
+ | from null79 import names, numbers | ||
+ | |||
+ | index = 42 | ||
+ | name = names[index] | ||
+ | telnr = numbers[index] | ||
+ | print(" | ||
+ | </ | ||
+ | |||
+ | == Aufgabe == | ||
+ | |||
+ | Verwende deine `linear_search()` Funktion, um die richtige Telefonnummer von Lyanna herauszufinden. Wie lange dauert die Suche? | ||
+ | |||
+ | <nodisp 1> | ||
+ | ++++Lösung mit Code| | ||
+ | <code python Aufgabe A3.py> | ||
+ | from null79 import names, numbers | ||
+ | |||
+ | def linear_search(l, | ||
+ | for i in range(len(l)): | ||
+ | if l[i] == v: | ||
+ | return i | ||
+ | return None | ||
+ | |||
+ | name = ' | ||
+ | idx = linear_search(names, | ||
+ | if idx == None: | ||
+ | print(" | ||
+ | else: | ||
+ | tel = numbers[idx] | ||
+ | print(" | ||
+ | print(" | ||
+ | print(" | ||
+ | print(" | ||
+ | </ | ||
+ | |||
+ | ++++ | ||
+ | </ | ||
+ | |||
+ | === Aufgabe A4: Maximal sächsehalb Jahr lang === | ||
+ | Wir möchten genau wissen, wie lange die Suche dauert, auch wenn es hoffentlich nicht 6.5 Jahre sind. | ||
+ | |||
+ | Um in Python die Zeit zu stoppen, kannst du das `time` Modul verwenden. Wie lange dauert die Suche für die `Lyanna`? Wie lange für `Annina`? Weshalb der Unterschied? | ||
+ | |||
+ | <code python> | ||
+ | import time | ||
+ | start = time.time() | ||
+ | # do something | ||
+ | elapsed = time.time() - start | ||
+ | print(" | ||
+ | </ | ||
+ | |||
+ | <nodisp 1> | ||
+ | ++++Lösung| | ||
+ | <code python time_algos.py> | ||
+ | from null79 import names, numbers | ||
+ | import time | ||
+ | |||
+ | def linear_search(l, | ||
+ | for i in range(len(l)): | ||
+ | if l[i] == v: | ||
+ | return i | ||
+ | return None | ||
+ | |||
+ | def stopwatch(name): | ||
+ | start = time.time() | ||
+ | index = linear_search(names, | ||
+ | elapsed = time.time() - start | ||
+ | print(" | ||
+ | |||
+ | stopwatch(' | ||
+ | stopwatch(' | ||
+ | </ | ||
+ | ++++ | ||
+ | </ | ||
+ | |||
+ | === Aufgabe A5: Umgekehrte Suche === | ||
+ | Finde heraus, wem die Telefonnummer `0791234567` gehört. | ||
+ | |||
+ | ++++Lösung| | ||
+ | Xassemb | ||
+ | ++++ | ||
+ | |||
+ | <nodisp 1> | ||
+ | ++++Code| | ||
+ | <code python> | ||
+ | idx = linear_search(numbers, | ||
+ | print(names[idx]) | ||
+ | </ | ||
+ | ++++ | ||
+ | </ | ||
+ | |||
+ | === Aufgabe A6: Verbesserte lineare Suche (optional) === | ||
+ | |||
+ | Wenn wir nach einem Namen suchen, der gar nicht in der Liste vorkommt, z.B. `Alaska`, so dauert die Suche lange, weil die ganze Liste durchsucht wird. | ||
+ | |||
+ | Nun sind die Namen in `null79.names` *alphabetisch sortiert*. Sobald wir einen Namen antreffen, der alphabetisch nach dem gesuchten Wert liegt, können wir die Suche abbrechen. Strings können in Python mit den `>` und `<` Operatoren verglichen werden: | ||
+ | |||
+ | <code python> | ||
+ | s1 = ' | ||
+ | s2 = ' | ||
+ | if s1 < s2: | ||
+ | print(s1 + ' liegt im Alphabet vor ' + s2) | ||
+ | else: | ||
+ | print(s1 + ' liegt im Alphabet nach ' + s2) | ||
+ | </ | ||
+ | |||
+ | Erweitere deine Funktion `linear_search()` wie folgt: | ||
+ | * Füge einen Parameter mit Default-Argument `is_sorted=False` hinzu. | ||
+ | * Wenn die Liste nicht sortiert ist, soll die Suche wie bisher ablaufen. | ||
+ | * Ist die Liste sortiert, soll die Suche abbrechen, wenn wir im Alphabet bereits weiter sind als der gesuchte Wert. | ||
+ | |||
+ | <nodisp 1> | ||
+ | ++++Lösung| | ||
+ | <code python> | ||
+ | def linear_search(l, | ||
+ | for i in range(len(l)): | ||
+ | if l[i] == v: | ||
+ | return i | ||
+ | if is_sorted and l[i] > v: | ||
+ | return None | ||
+ | return None | ||
+ | </ | ||
+ | ++++ | ||
+ | </ | ||
+ | |||
+ | === Aufgabe A7: Besserer Algorithmus? | ||
+ | |||
+ | Hast du eine Idee für einen besseren, sprich effizienteren Suchalgorithmus einer bereits sortierten Liste? Bespreche mit der Lehrperson und implementiere danach in Python. | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | Weiter zu [[gf_informatik: | ||