====== Suchen und Sortieren ====== Weiter zu [[gf_informatik:suchen_und_sortieren:binaersuche|Binäre Suche]] Direkt zu [[gf_informatik:suchen_und_sortieren:sortieren|Sortieren]] ==== 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://dict.leo.org/englisch-deutsch/search|dict.leo.org]] einen Suchbegriff innert Millisekunden zu finden? Wie findet [[https://tel.search.ch/kantonsschule%20romanshorn|tel.search.ch]] den richtigen Eintrag? ==== Lineare Suche ====
Gäb si mir wenigschtens d Vorwahl\\ Per favore\\ De gäbs nume no zäh Millione Kombinatione, ja\\ 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 [[https://www.youtube.com/watch?v=C8Xv7MKigYo|079 by Lo & Leduc]]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://www.songtexte.com/songtext/lo-and-leduc/079-g5bed3b18.html|Original]], [[https://www.swr3.de/musik/poplexikon/lyrics/lo--leduc-079--songtext-deutsche-bersetzung--lyrics-100.html|Hochdeutsch]], [[https://www.youtube.com/watch?v=C8Xv7MKigYo|Youtube]])! 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)?
De gäbs nume no zäh Millione Kombinatione, ja\\ 1. 20 Sekunden -
U weni nächär pro Minute drü vo de Nummere usprobier\\ 1. 6.5 Jahre -
De chönnts maximal nume sächsehalb Jahr lang ga\\ 1. $\frac{10\,000\,000}{365\frac{d}{y} \cdot 24\frac{h}{d} \cdot 60\frac{m}{h} \cdot \frac{3}{m}} \approx 6.342y$ 1. Wir hätten nochmals zwei Dezimalstellen, also 100 Mal mehr Möglichkeiten, damit 634 Jahre. ++++
names = ['Aja', 'Anela', 'Arwen', 'Isra',
'Juno', 'Kaida', 'Loelia', 'Luna',
'Lumiel', 'Lyanna', 'Meyra', 'Miriel',
'Narcissa', 'Nisha', 'Runa', 'Yuna']
numbers = ['0790000000', '0790000001', '00790000002', '0790000003',
'0790000004', '0790000005', '0790000006', '0790000007',
'0790000008', '0790000009', '0790000010', '0790000011',
'0790000012', '0790000013', '0790000014', '0790000015']
- Schreibe eine Python-Funktion `linear_search(l, v)`. Die Funktion soll in der Liste ''l'' nach dem Wert ''v'' suchen. Falls er gefunden wird, soll __die Position (Index)__ des Elements in der Liste //zurückgegeben// werden (*nicht* geprintet!).
- Test: Der Funktionsaufruf `print(linear_search(names, 'Anela'))` soll $1$ ausgeben.
- Nun wissen wir, dass die gesuchte Dame `Lyanna` (_die Geheimnisvolle_) heisst. Nutze nun diese Funktion, um die Telefonnummer von 'Lyanna' zu ermitteln.
**Achtung:** Generell bei solchen Aufgaben gilt: Verwende **keine vordefinierten Suchfunktionen**. Es geht genau darum, dass du diese *selbst* programmierst.
++++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.
++++
def linear_search(l, v):
for i in range(len(l)):
if l[i] == v:
return i
return None
index = linear_search(names, 'Lyanna')
print(numbers[index])
++++
from null79 import names, numbers
Damit das funktioniert, muss die Datei `null79.py` im gleichen Ordner gespeichert sein, wie unser selbstgeschriebener Code.
== Mit WebtigerPython ==
Am einfachsten geht das mit [[https://webtigerpython.ethz.ch/?code=NobwRAdghgtgpmAXGGUCWEB0AHAnmAGjABMoAXKJMAMwCcB7GAAggFcAbdgdgE4m0Y2erTItYcAM4EWrGACM4tCQB0IqjMTgAPJgF4mAFgBMq6PD1j4E4Bu0BdVWTjsItC23mLrtrQ4jZaDDIACmUwABE0OCYAFWc4anoID3g3ADckpjCmAGpLaLzstAlRbLynF1oASjAAXwJwMwRkNk5eHHwiUgoqAGIAQgB6VglaQbkMQbwyAAsk1V6mAFoAKiWmAGN6YgwAc0QmVjJqAA5ltfVBYVEyAThpEsCIXelUWdVVDfYoCQkmAGVsFAlHAAApzCBwABC9HoAGtglVEKomKismAwmEAIJMCRAkFMdjFG4zchMWhwMisWgQP6zaIUtJeODEfiaCC3Mi4JiJNxQJi7NBMiD8CCaLTSAIJNBaFlMADuaHeIrRaP5UuoMswmIxGJVqM01CYAH1jRglabghJnNRJRTNVpdGEAAy8MJIlGqtHW9jUTDG9hwZ6zCwARmdEcjzs9XtxNv9GplFkTWg--qYhpNAaDlp91A96dVFKpNLjvv9geDMzTqszpt2lKVcBguZt0jQBdjqLQRq52DgwQ7_D-EHooiCyMLXdo6GtTAAkmLtABRWgMWihMCLtJQImsnwHMq4sgbjtVGNenv8JgAHiYzsnXcvuX0latNvPU-7Rudt_0aFvQkg3fX1OyfNFi2pEU8wTe0kzyXk3mCN88yqZYmFDdC0GkF0j0eQcOWCN4Zkwdh6F2cNkOA1Cqlo3J0TUMBPyfGdimiRdxVXddNw47QmHoI5-KNGdnjgQ8wHo_CzzTL4fj-QFgWtAAZYlEUfNEdWxXF8WtaRd2wUkFFuDZd3YbkJGuOUiRKJhZjJTQnFoGBzRKNATM4blIJpP4oAvNEmh5YQmDgKANhmAUhSDUVxWkbQNjgbBRF5Jh-WtDZiyYOE4FwQYd3YVhoiBNBaG1XVMXTOszQgC1jRA20gKrB44HSyljSy3AmpashjTygrpE0b5cF0Z0wNjGDjQGqBuX0SbcD87142zKsLErXZlSfca0uLNrsosLbWva-bUU25rtt66J9H27rzqOss_R6-h5WcP59AAcigOA0AE17bvGrZaSSKAORephgDCwK3HBjBjyeXZMB-DY0DQANHsUEy5yvcHR3HaDFoyJ72AkPwNsW4gBLkQMQdeuRiGoXZ2BgfwlDIH6vzu_1Ek4VGlD2yziDq_18eeyTSfJynPwvSrK1bUD1NjLzcfLJa1urdNJYSE1IS0br9MMyk6ukb4SlGr0jdEV8fjIUjucRW6rzN4AllDOxRXZh6CYkOXwIVt3_os6Bgbto03zNtC7yML2WMpKC3aFwmg8JS3HaMF3ob-pJ_aBshPduoto9Lca45UNmffGzmyKepQL3Vo1jQbSEZycY0mgN_gTdVTSIkpRRnOq1z3LMgUg0UchonpfIUpx8VrzoRhbJmaIoB3NBvgpxf2AMqAjKYBReWiK6et3ArSs0tQ2avADdEuxaD_ayPp3zxX7oPm7z6NAC7xOrqdtwe-xooEQFhoxs1VEGVk18la32yrnNUG89bmxhnseGEhEbI1YNgfstB0ZwGAA-R4SCEZI2NOgzB2DMA-AFsaF-R8cHOjsFUYm4FUTsBWsBXWW9KTMS7M9MSMDjoAIQV_ba7V6Khj4cFMUrCIB1S4Uw9h29LongISgohJC0Y_Bwfg54yDUHEIweo605ClxaEodQ_KtD6E5FDIgRhTCAJLAgc_U6B1dp5DEWfJ8ixARElEMAEowIyCIDAanDk9BCTBQAI6sF3EsCQaAABecogiKDyn8egRp-SrRDOklKcgBI40cnlQY7BbosNfGwuBHCyCyK9OApgxFMDxRXsEYIYD0L-JEGhQYhIamqh8BYIIg4mCDG6cQXp_lxAWHkZSGwxjbHPn_EwAApBmGsXZ5QzBXtEVkAA-DCf8vTTMEYtLWOtKlGWCE0cZsYykNWCEc65tSLANKaewYIrJunsEeX04xAzCIARGRmb5EzzA5H0Ec2Z4p5lPkvteFZxBbo-yaGsg0Gt6yNicC2WqeZ2ztzRLceAmAJCBgSpQ2ajyrx9gHEOYoLAxyikCeI1ic5eJaC4sIHiEA8poH3MY8SkkTyDlognD-94Dl9JfHc1CIq9COP9FA3-TLH5uzMQVRFyrxr1xHk3FuHY0weAUDzfQCkQTgiSNCWECIXRuiYqYcQIMTXKVUuGKMEZpAAGYeAAFZ3UnGMNIV6SlcBA2gK9GotQ7BAA&vanilla_python=true|diesem WebtigerPython-Link]] - die Datei ist hier bereits hinterlegt.
== Mit TigerPython ==
Lade die Datei [[https://kantonsschuleromanshorn.sharepoint.com/:u:/s/FSInformatik/EQpO02ZUBldHmbYjEgKka_YBeaBaTHf1IUd-lrtYrdZJkA?download=1|null79.py]] herunter und speichere sie im selben Ordner wie dein Code.
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!
from null79 import names, numbers
index = 42
name = names[index]
telnr = numbers[index]
print("Die Telefonnummer von " + name + " ist " + telnr)
== Aufgabe ==
Verwende deine `linear_search()` Funktion, um die richtige Telefonnummer von Lyanna herauszufinden. Wie lange dauert die Suche?
from null79 import names, numbers
def linear_search(l, v):
for i in range(len(l)):
if l[i] == v:
return i
return None
name = 'Lyanna'
idx = linear_search(names, name)
if idx == None:
print("Du weisch immer no nüt het si gseit")
else:
tel = numbers[idx]
print("Die Telefonnummer von " + name + " ist " + tel)
print("144 hei si gseit!")
print("Wie isch das nume passiert, hei si gseit.")
print("Hueresiech, hei si gseit, ey")
++++
import time
start = time.time()
# do something
elapsed = time.time() - start
print("do something took " + str(elapsed) + "s")
from null79 import names, numbers
import time
def linear_search(l, v):
for i in range(len(l)):
if l[i] == v:
return i
return None
def stopwatch(name):
start = time.time()
index = linear_search(names, name)
elapsed = time.time() - start
print("Lineare Suche für {0} dauerte {1:.1f}s".format(name, elapsed))
stopwatch('Lyanna')
stopwatch('Annina')
++++
idx = linear_search(numbers, '0791234567')
print(names[idx])
++++
s1 = 'Alaska'
s2 = 'Alberta'
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.
def linear_search(l, v, is_sorted=False):
for i in range(len(l)):
if l[i] == v:
return i
if is_sorted and l[i] > v:
return None
return None
++++