Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.
| Beide Seiten, vorherige Überarbeitung Vorherige Überarbeitung Nächste Überarbeitung | Vorherige Überarbeitung | ||
| gf_informatik:verschluesselung:caesar [2025-03-09 16:47] – [Aufgabe B2] hof | gf_informatik:verschluesselung:caesar [2026-03-12 09:18] (aktuell) – [Aufgabe C2] hof | ||
|---|---|---|---|
| Zeile 4: | Zeile 4: | ||
| {{ : | {{ : | ||
| + | |||
| #### Aufgabe 1: Caesar-Verschlüsselung in Python | #### Aufgabe 1: Caesar-Verschlüsselung in Python | ||
| Zeile 15: | Zeile 16: | ||
| Du kannst über die Buchstaben eines Strings laufen wie über die Elemente einer Liste: | Du kannst über die Buchstaben eines Strings laufen wie über die Elemente einer Liste: | ||
| - | <code python> | + | <html>< |
| + | |||
| + | < | ||
| s = "Hallo KSR" | s = "Hallo KSR" | ||
| for buchstabe in s: | for buchstabe in s: | ||
| print(buchstabe) | print(buchstabe) | ||
| - | </code> | + | </bottom-editor></ |
| Einen String in Grossbuchstaben umwandeln: | Einen String in Grossbuchstaben umwandeln: | ||
| - | <code python> | + | <html>< |
| print(" | print(" | ||
| - | >>> HALLO KSR | + | </ |
| - | </code> | + | |
| Alle Grossbuchstaben können in `string.ascii_uppercase` abgefragt werden. Mit [[https:// | Alle Grossbuchstaben können in `string.ascii_uppercase` abgefragt werden. Mit [[https:// | ||
| - | <code python> | + | <html>< |
| import string | import string | ||
| for buchstabe in " | for buchstabe in " | ||
| print(string.ascii_uppercase.find(buchstabe)) | print(string.ascii_uppercase.find(buchstabe)) | ||
| + | </ | ||
| - | >>> | + | Der Modulo-Operator `%` gibt uns den Rest der Ganzzahl-Division zurück. Das ist praktisch, um den Index wieder bei `A` starten zu lassen, wenn er grösser als `Z` wird: |
| - | 7 | + | |
| - | 0 | + | |
| - | 11 | + | |
| - | 11 | + | |
| - | 14 | + | |
| - | </ | + | |
| - | Der Modulo-Operator `%` gibt uns den Rest der Ganzzahl-Division zurück. Das ist praktisch, um den Index wieder bei `A` starten zu lassen, wenn er grösser als `Z` wird: | + | <html>< |
| - | <code python> | + | |
| import string | import string | ||
| Zeile 54: | Zeile 50: | ||
| ciphertext = string.ascii_uppercase[index] | ciphertext = string.ascii_uppercase[index] | ||
| print(ciphertext) | print(ciphertext) | ||
| - | + | </ | |
| - | >>> C | + | |
| - | </code> | + | |
| <nodisp 2> | <nodisp 2> | ||
| ++++Lösung: | ++++Lösung: | ||
| - | <code python caesar.py> | + | <html>< |
| - | import string | + | def caesar(klartext, n): |
| - | + | | |
| - | def caesar(text, key): | + | decrypted_text = '' |
| - | | + | # Jeden Grossbuchstaben b im Klartext durchgehen. for-Schleife |
| - | for letter | + | for b in klartext.upper(): |
| - | | + | # Mit jedem Buchstaben: |
| - | if index != -1: | + | # - Position im Alphabet finden alphabet.find |
| - | | + | |
| - | | + | # |
| - | letter = string.ascii_uppercase[index] | + | |
| - | | + | # |
| - | return | + | p = p % len(alphabet) |
| + | | ||
| + | return | ||
| key = 17 | key = 17 | ||
| Zeile 78: | Zeile 74: | ||
| print(encrypted) | print(encrypted) | ||
| print(caesar(encrypted, | print(caesar(encrypted, | ||
| - | </code> | + | </bottom-editor></ |
| ++++ | ++++ | ||
| </ | </ | ||
| + | |||
| #### Aufgabe 2 | #### Aufgabe 2 | ||
| Zeile 134: | Zeile 131: | ||
| ++++ | ++++ | ||
| - | < | + | < |
| ++++Mehr Tipps| | ++++Mehr Tipps| | ||
| - | <code python> | + | <html>< |
| def decrypt(ciphertext, | def decrypt(ciphertext, | ||
| # oder string.ascii_uppercase | # oder string.ascii_uppercase | ||
| Zeile 155: | Zeile 152: | ||
| key = " | key = " | ||
| print(decrypt(ciphertext, | print(decrypt(ciphertext, | ||
| - | </code> | + | </bottom-editor></ |
| ++++ | ++++ | ||
| </ | </ | ||
| Zeile 161: | Zeile 158: | ||
| <nodisp 2> | <nodisp 2> | ||
| ++++Lösung| | ++++Lösung| | ||
| - | <code python> | + | <html>< |
| def decrypt(ciphertext, | def decrypt(ciphertext, | ||
| # oder string.ascii_uppercase | # oder string.ascii_uppercase | ||
| Zeile 179: | Zeile 176: | ||
| key = " | key = " | ||
| print(decrypt(ciphertext, | print(decrypt(ciphertext, | ||
| - | </code> | + | </bottom-editor></ |
| ++++ | ++++ | ||
| </ | </ | ||
| Zeile 265: | Zeile 262: | ||
| return text | return text | ||
| | | ||
| - | |||
| def count_letters(text): | def count_letters(text): | ||
| """ | """ | ||
| Zeile 296: | Zeile 292: | ||
| # Print the letter with width 2 | # Print the letter with width 2 | ||
| # Print the frequency with width 6 and precision 2, in percent format. | # Print the frequency with width 6 and precision 2, in percent format. | ||
| - | print(" | + | print(f"{letter:2}{percent: |
| print_percentages(count_letters(faust)) | print_percentages(count_letters(faust)) | ||
| Zeile 306: | Zeile 302: | ||
| ##### Option 2: Häufigkeitsanalyse von ganzem Buch (anspruchsvoll) | ##### Option 2: Häufigkeitsanalyse von ganzem Buch (anspruchsvoll) | ||
| - | Wie in Option 1, nur soll anstelle eines einzelnen Strings ein ganzes Buch eingelesen und analysiert werden. Auf [[https:// | + | Wie in Option 1, nur soll anstelle eines einzelnen Strings ein ganzes Buch eingelesen und analysiert werden. Auf [[https:// |
| - | <code python> | + | Damit das auch im Browser funktioniert, |
| - | import urllib2 | + | * Erste 5000 Zeichen von Faust: [[https:// |
| + | * Gesamter Faust 1 (ca. 220KB): [[https:// | ||
| + | * Manns "Tod in Venedig" | ||
| - | data = urllib2.urlopen(<Pfad zu File als String>) | + | <html>< |
| - | line_first = ... # erste Zeile des Texts | + | from pyodide.http import pyfetch |
| - | line_last | + | url = ' |
| - | for line in data: | + | response |
| - | | + | faust = await response.text() |
| - | if line_first <= count <= line_last: | + | |
| - | print(line) # Achtung: keine gute Idee, wenn File sehr viele Zeilen beinhaltet! Baue z.B. Counter ein, damit nach z.B. 100 Ausgaben abbricht | + | |
| - | </ | + | |
| - | Beachte, dass du noch die erste und letzte Zeilennummer im Buch angeben musst: Der Text am Anfang und Ende des Files gehört nicht zum Buch und soll ignoriert werden. | + | print(faust[:116]) |
| + | </ | ||
| Kontrolle: am häufigsten vorkommen sollte $E$ (gut $15\%$), gefolgt von $N$ (ca. $10\%$) und $S$. Die letzten Ränge machen typischerweise $Y$, $Q$ und $X$ unter sich aus. | Kontrolle: am häufigsten vorkommen sollte $E$ (gut $15\%$), gefolgt von $N$ (ca. $10\%$) und $S$. Die letzten Ränge machen typischerweise $Y$, $Q$ und $X$ unter sich aus. | ||
| Zeile 326: | Zeile 322: | ||
| <nodisp 2> | <nodisp 2> | ||
| ++++Lösung mit Gutenberg| | ++++Lösung mit Gutenberg| | ||
| - | <code python> | + | <html><bottom-editor> |
| - | # Rest as above. | + | import string |
| - | # Trick: urlopen() returns a file-like object, which iterates over lines of text | + | |
| - | # itertools.chain.from_iterable() will create an iterator that takes those lines | + | |
| - | # and iterates over each of them (creating an iterator over the characters of the | + | |
| - | # entire book). | + | |
| - | # Caution: this solution will not properly decode UTF-8 characters. | + | def normalize(text): |
| + | """ | ||
| + | text = text.lower() | ||
| + | text = text.replace(' | ||
| + | text = text.replace(' | ||
| + | text = text.replace(' | ||
| + | return text | ||
| + | |||
| + | def count_letters(text): | ||
| + | """ | ||
| + | | ||
| + | alphabet = string.ascii_lowercase | ||
| + | counts = [0] * len(alphabet) | ||
| + | total = 0 | ||
| + | |||
| + | # 2: Count occurrences | ||
| + | for letter in text: | ||
| + | letter = normalize(letter) | ||
| + | index = alphabet.find(letter) | ||
| + | # find() returns negative numbers if not found | ||
| + | # (punctuation etc.) -> ignore these. | ||
| + | if index >= 0: | ||
| + | counts[index] = counts[index] + 1 | ||
| + | total = total + 1 | ||
| + | |||
| + | # 3: Divide by total to get relative frequencies. | ||
| + | for i in range(len(counts)): | ||
| + | counts[i] = counts[i] / total | ||
| + | |||
| + | return counts | ||
| - | import urllib2 | + | def print_percentages(counts): |
| - | import | + | """ |
| + | for i in range(len(counts)): | ||
| + | letter = string.ascii_lowercase[i] | ||
| + | percent = counts[i] | ||
| + | # Print the letter with width 2 | ||
| + | # Print the frequency with width 6 and precision 2, in percent format. | ||
| + | print(f" | ||
| + | |||
| + | from pyodide.http | ||
| + | url = ' | ||
| + | response = await pyfetch(url) | ||
| + | faust = await response.text() | ||
| + | print_percentages(count_letters(faust)) | ||
| + | |||
| + | </ | ||
| - | faust = urllib2.urlopen(' | ||
| - | print_percentages(count_letters(itertools.chain.from_iterable(faust))) | ||
| - | </ | ||
| ++++ | ++++ | ||
| </ | </ | ||