First commit

This commit is contained in:
Emma Nora Theuer 2025-04-03 17:13:35 +02:00
parent a767e654e7
commit c1b0bd45e8

31
Programmierkurs.org Normal file
View file

@ -0,0 +1,31 @@
#+title: Programmierkurs
#+AUTHOR: Emma Nora Ada Theuer
* Lernziele
** Algorithmisches Denken
Der wichtigste Teil beim Programmieren lernen ist definitiv die bestimmte Denkweise, die es benötigt: Ein Compiler hat keinen gesunden Menschenverstand. Ein Programm macht immer nur exakt das, was du ihm sagst. Ein ganz wichtiger Aspekt beim Programmieren lernen ist es, gut darin zu werden, solche Dinge tun zu können. Algorithmisches denken besteht im Grunde darin, eine komplexe Aufgabe in kleinere, Idiotensichere Arbeitsschritte zu zerlegen. Dafür können wir uns ein paar Werkezeuge zu Nutze machen:
+ Dekomposition: Du hast eine sehr vielteilige Problemstellung, und weißt nicht, wie du sie am besten angehen sollst? Zerleg sie in kleinere Teile, mit denen du besser umgehen kannst und löse statt dem ganzen Problem auf einmal mehrere einfache Probleme.
- Beispiel: Lineares Gleichungssystem lösen. Das ist eine ziemlich komplexe Aufgabe, aber eine, die sich sehr gut algorithmisch lösen lässt. Der Aufbau lautet normalerweise grob: Matrix auf Zeilenstufen Form bringen -> Rücksubstitution -> Gleichungen mit jeweils einer unbekannten lösen. Dafür brauchst du aber einzele Unterwerkzeuge, zum Beispiel: Zwei Zeilen addieren. Eine Zeile mit einem Skalar multiplizieren. Mithilfe von Dekomposition schreibst du dann einfach zuerst eine Funktion, die eine Zeile mit einem Skalar multipliziert, eine Funktion, die zwei Zahlen addiert usw. Das machst du dann so oft, bis du auf Zeilenstufenform bist. So zerlegst du die große Aufgabe in vergleichsweise einfache Teilaufgaben zerlegst, die einfach zu programmieren sind, wie das addieren von zwei Zeilen. Das Motto hier ist auch "Divide-And-Conquer".
+ Abstraktion: Im Grunde das Gegenteil von Dekomposition. Wenn dir zu viele Details um die Ohren fliegen, kannst du mithilfe von Abstraktion das ganze Problem einmal von außen betrachten, damit du nicht den Faden verlierst, was du grade eigentlich machen willst.
- Beispiel: Entwicklung eines Filesystems. Hierbei kann es schnell passieren, dass du irgendwann keine Ahnung mehr hast, was deine 200 Zeilen lange Datenstruktur eigentlich macht. Und wozu du sie brauchst. Setze es in den Gesamtkontext: Eventuell dient deine Datenstruktur eingentlich nur dazu, Metadaten für Dateien anzuzeigen. Wenn du dann in einem anderen Teil des Dateisystems unterwegs bist, brauchst du nur wissen, dass dir diese Struktur Metadaten anzeigt. Nicht was für interne Enums verwendet werden, um Zugriffsrechte verwalten. Bei der Betrachtung von außen reicht es dir schon zu wissen, dass du diese Information daher bekommen kannst. Nicht /wie/.
+ Mustererkennung: Oft bekommst du bei der Softwareentwicklung Problemstellungen, die anderen Problemen ähneln, die du schon an einer andren Stelle des Programms gelohnt hast. Dann kannst du deine Lösung entweder weiterentwickeln oder wiederverwenden
- Beispiel: Lineares Gleichungssystem lösen. Manchmal ist es bei der Lösung von einem LGS nötig, eine Zeile von einer anderen zu subtrahieren. Mithilfe der Mustererkennung sehen wir: Subtrahieren ist eigentlich das gleiche wie addieren, nur dass wir erst alle Vorzeichen umdrehen. Und wie drehen wir vorzeichen um? Wir multiplizieren mit dem Skalar -1. So wurde unser neues Problem, Zeilen substrahieren, Mithilfe von Mustererkennung und Dekomposition vereinfacht: Statt eine Subtraktionsmethode schreiben zu müssen, benutzen wir einfach die Methoden, die wir sowieso schon fürs addieren und das multiplizieren mit einem Skalar geschrieben haben, und ersparen uns so Zeit und Arbeit.
+ Pseudocode: Wenn du dir erstmal keine Gedanken machen möchtest, wo du welche Semikolons und Klammern setzen willst, und auch erstmal ohne jeden einzelnen Datentyp über das Problem nachdenken willst, ist Pseudocode hilfreich. Du schreibst das Programm quasi in natürlicher Sprache, die Code Strukturen hat. Dann musst du das danach nur noch in Lauffähigen Code übersetzen. Im Sinne dieses Skripts werde ich statt richtigem Pseudocodes einfaches Python schreiben, da dir Struktur sehr ähnlich zu klassischem Pseudocode ist. Im Grunde kannst du bei Pseudocode aber eine beliebe Syntax wählen. Viele Leute schreiben auch gerne Pseudocode, der in seiner Struktur eher Java oder C ähnelt.
- Kurz dazu: Manchmal, wenn das auch schon zu komplex ist, kannst du den Code auch erstmal nur in natürlicher Sprache beschreiben, dann in Pseudocode umwandeln, und dann in einer richtigen Programmiersprache schreiben.
+ Rubber-Duck-Debugging: Eigentlich eine Debugging Technik, wenn irgendwas in deine Code nicht richtig funktioniert, aber du dir nicht bist, warum. Der Name kommt daher, das sich Programmiere dafür wirklich quietscheentchen auf den Tisch gestellt haben, um diese Technik zu benutzen. Ich gehe manchmal aber auch einfach zu meinem Hund und Texte sie dann voll. Das geht auch. Die Technik ist sehr nützlich, wenn du Schwierigkeiten hast, durch deine eigene Logik einen durchblick zu bekommen, und du nicht verstehst warum das was du machst nicht funktioniert. Im Grudne erklärst du deiner Quietscheente im Detail was dein Code machen soll, und wie du es machst. Oft fällt dir schon dabei auf, was genau daran logisch nicht richtig ist. Kann theoretisch auch angewendet werden, um überhaupt zu verstehen, ob man mit seiner Lösung auf dem richtigen Weg ist.
Es gibt noch viele weitere Tools, die wir verwenden können, aber das hier sind einige der vielseitigsten. Im Laufe dieses Plans werden wir sie auch anwenden um Probleme zu lösen.
*** Einige Algorithmen, die wir lernen werden
- Einfache Sortieralgorithmen. Bubble sort und selection sort. Außerdem besprechen wir am Ende einmal Quicksort ganz oberflächlich. Eine richtige Implementierung ist aber extrem anspruchsvoll und in Sprachen wie C überhaupt nicht mehr sinnvoll.
- Numerische Algorithmen. Zum Beispiel zum berechnen der Fibonacci Reihe. Wir schauen uns auch das Kinderspiel "Fizzbuzz" an, und schreiben eine simple Implementierung.
- Einfache Spiele. Zum Beispiel ein TicTacToe Spiel. Einmal in der Mensch-Gegen-Mensch Variante, einmal gegen einen Computer, der zufällige Züge macht.
- ... Und viele weitere, um Konzepte Hands-on zu lernen!
** Grundlegende Datenstrukturen
Wir wissen ja bereits, dass ein Array in C eine festgelegte maximale Größe besitzt. Wie kann es dann sein, dass es in Python Listen gibt, die von außen genauso funktionieren wie arrays, aber keine begrenzte Länge haben und wo immer wieder neue Sachen dazugetan, oder alte Sachen entfernt werden? Hierzu schauen wir uns Linked Lists (verkettete Listen) und Doubly-Linked-Lists (Doppelt verkettete Listen) an, und implementieren solche Strukturen in C und java.