Einführung in die Programmiertechnik



Ähnliche Dokumente
Programmiertechnik 1. Unit 8: Programmiersprache C Funktionen und Programmstruktur. Andreas Polze 1

EINI WiMa. Einführung in die Informatik für Naturwissenschaftler und Ingenieure. Vorlesung 2 SWS WS 11/12

Rekursive Funktionen

Unit 8: Programmiersprache C Funk=onen und Programmstruktur. Andreas Polze 1. Ablauf

Speicher und Adressraum

EINI I. Einführung in die Informatik für Naturwissenschaftler und Ingenieure. Vorlesung 2 SWS WS 10/11

Einführung in die Informatik I

Rekursive Funktionen

Programmieren 1 C Überblick

Grundlagen der Programmierung (Vorlesung 15)

Mathematische Rekursion

III.1 Prinzipien der funktionalen Programmierung - 1 -

Informatik für Schüler, Foliensatz 18 Rekursion

Objektorientierte Programmierung (ZQ1u2B)

Gliederung. n Teil I: Einleitung und Grundbegriffe. n Teil II: Imperative und objektorientierte Programmierung

Dr. Lars Hildebrand Fakultät für Informatik Technische Universität Dortmund

Algorithmen & Programmierung. Rekursive Funktionen (1)

EINI LogWing/WiMa. Einführung in die Informatik für Naturwissenschaftler und Ingenieure. Vorlesung 2 SWS WS 17/18

II.3.1 Rekursive Algorithmen - 1 -

Einführung in die Programmiertechnik

2. Algorithmische Methoden 2.1 Rekursion. 18. April 2017

Software Entwicklung 1

2. Algorithmenbegriff

Einführung in die Programmiertechnik

Grundlagen der Programmierung

Teil 14: Rekursive Programmierung. Prof. Dr. Herbert Fischer Fachhochschule Deggendorf Prof. Dr. Manfred Beham Fachhochschule Amberg-Weiden

Inhalt Kapitel 2: Rekursion

Welche Informatik-Kenntnisse bringen Sie mit?

Rekursive Funktionen (1)

Rekursive Funktionen (1)

Einführung in die Programmierung II. 5. Zeiger

Einschub: Anweisungen und Bedingungen für PAP und Struktogramme (1)

Informatik I Für eine feste Zahl. Informatik I Benutzereingaben Eine Funktion factorial Iteration von unten. 18.

Algorithmen implementieren. Implementieren von Algorithmen

Lösungsvorschlag Serie 2 Rekursion

EINI WiMa. Einführung in die Informatik für Naturwissenschaftler und Ingenieure. Vorlesung 2 SWS WS 11/12

Informatik I. Informatik I Iteration vs. Rekursion. Iteration vs. Rekursion Iteration vs. Rekursion. 20. Iteration vs.

Programmierkurs Python I

Rekursive Funktionen und ihre programmtechnische Umsetzung

FHZ. K13 Rekursion. Lernziele. Hochschule Technik+Architektur Luzern Abteilung Informatik, Fach Programmieren. Inhalt

Software Entwicklung 1. Rekursion. Beispiel: Fibonacci-Folge I. Motivation. Annette Bieniusa / Arnd Poetzsch-Heffter

Übung zur Vorlesung Wissenschaftliches Rechnen Sommersemester 2012 Auffrischung zur Programmierung in C++, 1. Teil

Rekursion. Sie wissen wie man Programme rekursiv entwickelt. Sie kennen typische Beispiele von rekursiven Algorithmen

1. Grundkonzepte der logischen Programmierung 2. Syntax von Prolog 3. Rechnen in Prolog. IV.1 Grundkonzepte der logischen Programmierung - 1 -

Kasparov versus Deep Blue. Till Tantau. Institut für Theoretische Informatik Universität zu Lübeck

Verwendung Vereinbarung Wert einer Funktion Aufruf einer Funktion Parameter Rekursion. Programmieren in C

Kapitel 08: Rekursion und Terminierung Software Entwicklung 1

n 1. Grundkonzepte der logischen Programmierung n 2. Syntax von Prolog n 3. Rechnen in Prolog IV.1 Grundkonzepte der logischen Programmierung - 1 -

Beim rekursiven Aufruf einer Funktion wird jeweils ein Duplikat der gesamten Funktion im Speicher abgelegt.

Informatik I: Einführung in die Programmierung. Übungsblatt 3. Abgabe: Freitag, 15. November 2013, 18:00 Uhr

11. Rekursion, Komplexität von Algorithmen

Rekursive Algorithmen

ALPII Objektorientierte Programmierung

Programmierung mit C Algorithmen

Datenstrukturen. Mariano Zelke. Sommersemester 2012

Heap vs. Stack vs. statisch. 6 Speicherorganisation. Beispiel Statische Variablen. Statische Variablen

Vorkurs Informatik WiSe 16/17

Übung zur Vorlesung Wissenschaftliches Rechnen Sommersemester 2012 Auffrischung zur Programmierung in C++, 1. Teil

1 Berechnung von Summen (ca = 10 Punkte)

Heap vs. Stack vs. statisch. 6 Speicherorganisation. Beispiel Statische Variablen. Statische Variablen

Einführung in die Programmierung mit VBA

EINI LW. Einführung in die Informatik für Naturwissenschaftler und Ingenieure. Vorlesung 2 SWS WS 11/12

Datenstrukturen und Algorithmen

Vorkurs Informatik WiSe 17/18

Fallstudie: Nim Spiel

CS1005 Objektorientierte Programmierung

Informatik I: Einführung in die Programmierung

4.4 Imperative Algorithmen Prozeduren

Vorlesung Programmieren

Einführung in die Informatik I

Dr. Lars Hildebrand Fakultät für Informatik Technische Universität Dortmund

Systemnahe Programmierung in C (SPiC)

1. Der Begriff Informatik 2. Syntax und Semantik von Programmiersprachen - 1 -

1. Der Begriff Informatik 2. Syntax und Semantik von Programmiersprachen - 1 -

Informatik I. Jan-Georg Smaus. Iteration vs. Rekursion. Iterativer Algorithmus Beweis der Korrektheit Python- Programm Zusammenfassung

6 Speicherorganisation

6. Funktionen, Parameterübergabe

Methoden. Gerd Bohlender. Einstieg in die Informatik mit Java, Vorlesung vom

11. Rekursion. 1, falls n 1. n (n 1)!, andernfalls. Mathematische Rekursion. Rekursion in Java: Genauso! Unendliche Rekursion. n!

9. Rekursion. 1 falls n 1 n (n 1)!, andernfalls. Experiment: Die Türme von Hanoi. Links Mitte Rechts. Mathematische Rekursion

Einführung in die Programmierung I. 5. Prozeduren. Stefan Zimmer

Collatz-Folge. falls a i ungerade.

6 Speicherorganisation

Java: Eine kurze Einführung an Beispielen

Induktion und Rekursion

Programmiersprachen: Klassifizierung und Methoden. Programmier-Paradigmen. Grundlagen der Programmierung 2 (1.C) - 1 -

Programmierung in Python

12. Rekursion. 1, falls n 1. n (n 1)!, andernfalls. Lernziele. Mathematische Rekursion. Rekursion in Java: Genauso! n! =

Prof. Dr. Margarita Esponda

Algorithmen und Programmierung II

1. Teilklausur. Name:... Vorname:... Matrikel-Nummer:...

Funktionale Programmiersprachen

15. Rekursion. Rekursive Funktionen, Korrektheit, Terminierung, Aufrufstapel, Bau eines Taschenrechners, BNF, Parsen

Transkript:

Einführung in die Programmiertechnik Unterprogramme

Unterprogramme Zerlegung eines Algorithmus in kleinere Teile Zur Verbesserung der Lesbarkeit Zur mehrfachen Verwendung im gleichen Programm (Vermeidung von Codedopplungen) Zur Wiederverwendung in anderen Programmen (Bibliothek) Python: Funktionsdefinitionen def funktionsname(parameter): funktionskörper Variablen, die innerhalb der Funktion belegt werden, sind nur bis zum Ende der Funktion gültig Lokale Variablen Sollen Variablen den Wert auch außerhalb der Funktion behalten, so müssen sie mit global deklariert werden global zahl_der_streichhoelzer Deklaration optional, falls globale Variable nur gelesen wird 2

3 Unterprogramme: Ein Beispiel import sys def Sterne(k): for i in range(k): sys.stdout.write( * ) for zeile in range(5): Sterne(zeile) sys.stdout.write( \n )

4 Prozedurale Abstraktion Zerlegung des Programms in Teilschritte mithilfe von Prozeduren: prozedurale Abstraktion Unterprogramme, die wie Anweisungen verwendet werden Prozeduren liefern kein Ergebnis

# Zeichne einen Weihnachtsbaum import sys def Sterne(zeichen, anzahl): "Sterne(zeichen, anzahl) gibt anzahl zeichen auf sys.stdout" for i in range(anzahl): sys.stdout.write(zeichen) # Zeichne zuerst die Krone H = 5 for zeile in range(h): Sterne(" ", H - zeile - 1) Sterne("*", 2*zeile+1) sys.stdout.write("\n") # jetzt noch der Stamm for zeile in range(3): Sterne(" ", H - 1) sys.stdout.write("*\n") 5

Funktionale Abstraktion Funktionen: Unterprogramme, die Werte liefern Verwendbar als Ausdrücke i.d.r. keine Seiteneffekte Python: return-anweisung bestimmt Funktionsergebnis Konvention: möglichst nur eine return-anweisung am Ende der Funktion def ggt(x, y): while x<>0 and y<>0: if x > y: x = x%y else: y = y%x return x+y 6

Top-Down-Entwurf Annahme: Spezifikation gegeben Ansonsten: Zunächst Problemanalyse Beginn der Entwicklung: Programmgerüst Verlagerung von Teilfunktionen in leere Unterprogramme Prozedurrümpfe (stubs): abstrakte Operationen Python: Leeranweisung pass def anmelden(vorname, nachname): pass Schrittweises Ausfüllen des Gerüsts: Verfeinerung iterativer Prozess: in jedem Schritt werden u.u. neue Prozedurrümpfe eingeführt 7

8 Top-Down-Entwurf: Ein Beispiel NIM-Spiel (Nim Game): Das Spiel beginnt mit drei Reihen von Streichhölzern. Zwei Spieler ziehen abwechselnd. Ein Zug besteht darin, eine Reihe auszuwählen und aus dieser Reihe beliebig viele jedoch mindestens ein Streichholz wegzunehmen. Wer das letzte Streichholz nimmt, gewinnt. Aufgabe: Gesucht ist ein Programm, das dieses Spiel spielt

NIM-Spiel: Programmgerüst (v1) init() fertig = False spieler = 1 while not fertig: zeige_spiel() mache_zug() if spiel_ende(): fertig = True else: spielerwechsel() gratuliere_dem_sieger() 9

NIM-Spiel: Programmgerüst (v2) reihe1 = reihe2 = reihe3 = 0 def init(): global reihe1, reihe2, reihe3 reihe1, reihe2, reihe3 = 4, 7, 3 def zeige_spiel(): pass def mache_zug(): pass def spiel_ende() return True def spieler_wechsel(): pass def gratuliere_dem_sieger(): pass #... weiter wie auf letzter Folie init()... 10

11 Top-Down-Entwurf: Verfeinerung Aufgabenstellung unterspezifiziert; deshalb mehrere mögliche Verfeinerungen 1. Vervollständigung der Routinen, so dass ein Demospiel vorführbar ist 2. Einbau einer Strategie, um den bestmöglichen Zug zu ermitteln 3. Erweiterung der Nutzerinteraktion Initiale Abfrage der Streichholzzahlen Integration des Nutzers als einer der Spieler 4. graphische Ausgabe statt textueller

Top-Down-Entwurf: Vervollständigung zu Demo- Programm def init(): global reihe1, reihe2, reihe3, zugnummer reihe1, reihe2, reihe3 = 4, 7, 3 zugnummer = 0 def zeige_spiel(): "Ausgabe des Spielfelds auf die Standardausgabe" print "Zugnummer", zugnummer print "Reihe 1", reihe1 print "Reihe 2", reihe2 print "Reihe 3", reihe3 def spiel_ende(): # Das Spiel ist fertig, wenn keine Streichhölzer mehr übrig sind return reihe1+reihe2+reihe3 == 0 12

def spieler_wechsel(): global spieler # Aus Spieler 1 wird Spieler 2 und umgekehrt spieler = 3-spieler def gratuliere_dem_sieger(): # gewonnen hat, wer den letzten Zug gemacht hat; # dieser Wert ist noch in Variable spieler gespeichert print "Gewonnen hat der Spieler", spieler print "Herzlichen Glückwunsch" 13

14 NIM-Spiel: Der bestmögliche Zug Spieler sollte versuchen, dem Gegner ein Spielfeld vorzulegen, bei dem reihe1 xor reihe2 xor reihe3 = 0 nach gegnerischem Zug kann dann nicht mehr reihe1 xor reihe2 xor reihe3 = 0 gelten Spieler kann nach eigenem Zug diesen Zustand immer wieder herstellen nach letztem Zug gilt reihe1 xor reihe2 xor reihe3 = 0

def mache_zug(): global zugnummer, reihe1, reihe2, reihe3 zugnummer += 1 if reihe1 > (reihe2 ^ reihe3): reihe1 = reihe2 ^ reihe3 elif reihe2 > (reihe1 ^ reihe3): reihe2 = reihe1 ^ reihe3 elif reihe3 > (reihe1 ^ reihe2): reihe3 = reihe1 ^ reihe3 else: verlegenheitszug() 15

Datenfluss zwischen Haupt- und Unterprogramm Änderung von globalen Variablen: Seiteneffekt Variablenänderung nicht in Funktionsergebnis sichtbar Abhängigkeiten zwischen Prozeduren werden unüberschaubar Kapselung: Zahl der Prozeduren, die auf gemeinsame Variablen zugreifen, sollte klein sein information hiding im Beispiel: eine Prozedur def nimm_von_reihe(reihe, zahl):... würde das eigentliche Wegnehmen von der Strategie trennen Objektorientierte Programmierung: Kapselung von Werten in Objekten im Beispiel: Spielfeld als Klasse, mit Lese- und Schreiboperationen für die Reihen (Alternativ: Spielstand ) 16

Rekursion Beschreibung einer mathematischen Funktion oft durch Fallunterscheidung; ein Fall bezieht sich wieder auf die Funktion Beispiel: Fakultät fac(n) = n! fac(0) = 1 fac(n) = n fac(n-1), falls n > 0 Ableitung einer Berechnungsvorschrift: sequentielles durchtesten der Fälle def fac(n): if n == 0: return 1 if n > 0: # Test auf n>0 ist hier redundant return n * fac(n-1) 17

Verarbeitung der Rekursion fac(4) = 4*fac(3) = 4 * 6 = 24 fac(3) = 3*fac(2) = 3* 2 = 6 fac(2) = 2*fac(1) = 2 * 1 = 2 fac(1) = 1*fac(0) = 1 * 1 = 1 fac(0) = 1 18

Formulierung von Rekursion Zerlegung des Problems in Teilprobleme: ein Teilproblem ist gleichartig dem Originalproblem Beispiel: fac(n-1) ist im Prinzip genauso wie fac(n) Teilproblem muss leichter lösbar sein als Originalproblem anderes Teilproblem kombiniert die Lösung des ersten Teilproblems mit weiterem Rechenschritt zur Gesamtlösung: Beispiel: fac(n) = n*fac(n-1) (Multiplikation der Teillösung mit n) Rekursionsabbruch: einfachstes Teilproblem wird nicht weiter zerlegt; Lösung wird direkt bestimmt Teile-und-herrsche-Prinzip Vereinfachung des Problems durch Zerlegung engl.: divide-and-conquer lat.: divide-et-impera Historisch falsch: Teile werden nicht gegeneinander ausgespielt 19

Rekursive Prozeduren Umkehrung der Berechnungsreihenfolge durch Rekursion Beispiel: erzeuge Binärdarstellung einer Zahl 1. Versuch: Ziffern werden in falscher Reihenfolge ausgegeben while n > 0: print n%2, n /= 2 rekursive Lösung: gib zuerst die höherwertigen Bits aus, danach das letzte: def writebin(n): if (n < 2): print n, else: writebin(n/2) print n%2, 20

21 Die Türme von Hanoi Auf einem Stapel liegen N Scheiben verschiedener Durchmesser; der Durchmesser nimmt von unten nach oben schrittweise ab. Der Turm steht auf einem Platz A und soll zu einem Platz C bewegt werden, wobei ein Platz B als Zwischenlager benutzt werden kann. Dabei müssen 2 Regeln eingehalten werden: Es darf immer nur eine Scheibe bewegt werden Es darf nie eine größere auf einer kleineren Scheibe liegen

Die Türme von Hanoi (2) Lösungsstrategie: induktive Lösung Verschieben einer Scheibe: Scheibe von Platz 1 (z.b. A) auf Platz 2 (z.b. C) Verschieben von K Scheiben: Verschiebe K-1 Scheiben von Platz 1 auf Hilfsplatz H (etwa: B), verschiebe K-te Scheibe von Platz 1 auf Platz 2, verschiebe K-1 Scheiben von H auf Platz 1 Rekursive Sicht: Angenommen, wir können bereits K-1 Scheiben verschieben, dann wissen wir auch, wie wir K Scheiben verschieben Wir wissen, wie wir eine Scheibe verschieben (Rekursionsende) Problem: Keine feste Zuordnung von symbolischen Plätzen (1, 2, H) zu tatsächlichen Plätzen (A, B, C) Lösung: symbolische Plätze sind Variablen/Parameter, tatsächliche Plätze die Werte von dieser Variablen 22

Die Türme von Hanoi (3) def ziehe_scheibe(nummer, von, nach): print "Scheibe", nummer, " wird von", von, "nach", nach, "verschoben" def hanoi(n, platz1, hilfsplatz, platz2): if N == 1: ziehe_scheibe(n, platz1, platz2) else: hanoi(n-1, platz1, platz2, hilfsplatz) ziehe_scheibe(n, platz1, platz2) hanoi(n-1, hilfsplatz, platz1, platz2) hanoi(4, "A", "B", "C") 23

Backtracking Weitere Verwendung rekursiver Prozeduren: Spielstrategien Annahme: Spiel mit vollständiger Information (alle Konsequenzen eines Zugs sind vorhersehbar), z.b. Schach, Go,... Idee: In Gedanken wird das Spiel zuende gespielt und versucht, jeweils den optimalen Zug zu ziehen im aktuellen Spielstand werden in Gedanken der Reihe nach alle möglichen Züge ausprobiert mehrere mögliche Ergebnisse: egal welchen Zug man spielt, man gewinnt immer Ergebnis: Man wird gewinnen, ein beliebiger Zug ist geeignet egal welchen Zug man spielt, man verliert immer Ergebnis: entsprechend Bei manchen Zügen wird man gewinnen, bei manchen verlieren Ergebnis: man wähle einen Zug, bei dem man gewinnen wird, und verbuche das als man wird gewinnen Algorithmus sucht der Reihe nach alle Varianten ab, bis er einen Zug gefunden hat, der zum Sieg führen wird anderenfalls nimmt man den Zug in Gedanken zurück, und probiert einen anderen: Backtracking 24

Wechselseitige Rekursion in der Definition der Funktion f wird die Funktion g aufgerufen, und in der Definition von g wird f aufgerufen Konsequenz: Verwendung im Programm textuell vor Definition Python, Java: Reihenfolge der Definitionen irrelevant C, Pascal: Vorwärtsdeklarationen Beispiel def gerade(n): if n == 0: return True return ungerade(n-1) def ungerade(n): if n == 0: return False return gerade(n-1) 25

26 Allgemeine Rekursion Definition der Funktion greift mehrfach auf dieselbe Funktion zurück Beispiel: Fibonacci-Funktion Modell zur Populationsentwicklung z.b. bei Kaninchen

27 Endrekursion Eine Funktionsdefinition ist endrekursiv (tail recursive), falls sie die Form hat Beispiel: fac(n) = { g(x), f(r(x)), falls P (x) sonst.

Endrekursion (2) Falls dem rekursiven Aufruf noch eine Berechnung folgt, liegt keine Endrekursion vor: Bei Endrekursion kann der ursprüngliche Aufruf gänzlich ersetzt werden: gerade 1 (4) = gerade 1 (2) = gerade 1 (0) = (0=0) = True aber: gerade 2 (4) = gerade 2 (3) = gerade 2 (2) = gerade 2 (1) = gerade 2 (0) = True =... = True Endrekursive Definition kann leicht in iterative Definition übertragen werden In manchen Programmiersprache (z.b. LISP, Scheme) passiert das automatisch 28

29 Lineare Rekursion Verallgemeinerung der Endrekursion für h(x,y)=y ergibt sich Endrekursion fac(n) = { g(x), h(x, f(r(x))), falls P (x) sonst f(x) = h(x, f(r(x))) = h(x, h(r(x), f(r 2 (x)))) = h(x, h(r(x), h(r 2 (x), f(r 3 (x))))) =...

Lineare Rekursion (2) im Allgemeinen Berechnung nur durch Stack s möglich Berechnung von r n (x), Speichern auf Stack, Auslesen in umgekehrter Reihenfolge (LIFO: Last-In-First-Out) while not P(x): push(x, s) x = r(x) f = g(x) while not empty(s): x = top(s) pop(s) f = h(x,f) 30

Lineare Rekursion (3) Lineare Rekursion lässt sich u.u. in Endrekursion umformulieren (siehe Gumm, Sommer, S. 168): Beispiel: Fakultät fac(n)=n! fac(n) = { 1, falls n = 0 n fac(n 1), Ersetzbar durch fac(n) = facaux(n, 1) sonst zusätzlicher Parameter übernimmt Rolle des Akkumulators 31

Transformation von Fibonacci-Zahlen Akkumulatorverfahren u.u. erweiterbar auf allgemeine Rekursion Beispiel: fib(n) = fibaux(n,1,1) mit def fibaux(n, acc1, acc2): if n == 0: return acc1 return fibaux(n-1, acc2, acc1+acc2) Iterative Definition: Auflösen der Endrekursion: def fib(n): acc1 = acc2 = 1 while n > 0: n, acc1, acc2 = n-1, acc2, acc1+acc2 return acc1 32