Algorithmische Grundlagen - Sommersemester 2016 – VL03

Werbung
Algorithmische Grundlagen
Sommersemester 2016 – VL03
Martin Mundhenk
Uni Jena, Institut für Informatik
17. April 2016
1.3 Arrays
Die bisher benutzten Daten waren recht einfach – Zahlen, Texte oder
Wahrheitswerte.
Eine Datenstruktur dient der Organisation von Daten zur Verarbeitung
mit einem Computer-Programm.
Eine einfache Datenstruktur sind Arrays, mit denen man z.B. beliebig
lange Folgen von Zahlen verarbeiten kann.
Das erlaubt uns Programme zu schreiben, die viel größere Mengen von
Daten verarbeiten als bisher.
1.3.1
Beispiel für ein eindimensionales Array
Die einfachste Vorstellung eines Arrays ist
eine Zuordnung von Werten zu Indizes.
a = [’Gallia’, ’omnis’, ’div’, ’est’] erzeugt ein Array a[] mit
Index
zugeordneter Wert
0
1
2
3
’Gallia’
’omnis’
’div’
’est’
a[2] hat den String ’div’ als Wert.
a[3] = a[2] + ’isa’ ändert den Wert von a[3] zu ’divisa’
Array a[]
Index
zugeordneter Wert
0
1
2
3
’Gallia’
’omnis’
’div’
’divisa’
Die Länge von a[] ist 4 und ist das Ergebnis von len(a).
1.3.2
Beispiel für ein zweidimensionales Array
a = [ [’b’, ’b’, ’c’], [’d’, ’e’, ’f’, ’g’], [’h’, 1], [2]]
erster Index
zweiter Index
Wert
0
1
2
3
0
1
2
0
1
2
3
0
1
0
’b’
’b’
’c’
’d’
’e’
’f’
’g’
’h’
1
2
a[1][2] hat den str-Wert ’f’.
Die Länge des zweidimensionalen Arrays a[][] ist 4, d.h.
len(a) hat den Wert 4.
a[0][] hat das Array [’b’, ’b’, ’c’] als Wert.
Die Länge von a[0][] ist 3, d.h. len(a[0]) hat den Wert 3.
1.3.3
Berechnung des Durchschnitts der Werte eines Arrays
#---------------------------------------------------------# durchschnitt.py
#---------------------------------------------------------import stdio
# Berechne den Durchschnitt der Werte,
# die im Array werte[] gespeichert sind.
werte = [17, 4, 23, 999, 46, 24, 1, 1, 13, 18]
summe = 0
for i in range(len(werte)):
stdio.writeln('i: ' + str(i) + '
summe = summe + werte[i]
#-----------------------# python durchschnitt.py
# i: 0 summe: 0
# i: 1 summe: 17
# i: 2 summe: 21
# i: 3 summe: 44
# i: 4 summe: 1043
# i: 5 summe: 1089
# i: 6 summe: 1113
# i: 7 summe: 1114
# i: 8 summe: 1115
# i: 9 summe: 1128
# 114.6
summe: ' + str(summe))
stdio.writeln(str(float(summe)/len(werte)))
werte[] ist ein Array der Länge 10.
Die Elemente von werte sind mit werte[0], werte[1],werte[2],. . . , werte[9] ansprechbar.
len(werte) ist die Länge des Arrays werte.
Man kann das auch kompakter aufschreiben
#---------------------------------------------------------# durchschnitt.py
#---------------------------------------------------------import stdio
# Berechne den Durchschnitt der Werte,
# die im Array werte[] gespeichert sind.
werte = [17, 4, 23, 999, 46, 24, 1, 1, 13, 18]
summe = 0
for i in werte:
stdio.writeln('i: ' + str(i) + '
summe += i
summe: ' + str(summe))
stdio.writeln(str(float(summe)/len(werte)))
#-----------------------# python durchschnitt.py
# i: 17 summe: 1146
# i: 4 summe: 1163
# i: 23 summe: 1167
# i: 999 summe: 1190
# i: 46 summe: 2189
# i: 24 summe: 2235
# i: 1 summe: 2259
# i: 1 summe: 2260
# i: 13 summe: 2261
# i: 18 summe: 2274
# 114.6
Das Gleiche für ein zweidimensionales Array . . .
#-------------------------------------------------------# ddurchschnitt.py
# Berechnet den Durchschnitt aller Werte
# eines 2-dimensionalen Arrays.
#-------------------------------------------------------import stdio
werte = [ [17, 4], [23, 999, 46], [24, 1, 1, 13], [18] ]
summe = 0
anzahl = 0
for z in range(len(werte)):
for s in range(len(werte[z])):
stdio.writeln('z: ' + str(z) + ' s: ' + str(s) +
' summe: ' + str(summe))
summe = summe + werte[z][s]
anzahl = anzahl + 1
stdio.writeln(str(float(summe)/anzahl))
#------------------------# python ddurchschnitt.py
# z: 0 s: 0 summe: 0
# z: 0 s: 1 summe: 17
# z: 1 s: 0 summe: 21
# z: 1 s: 1 summe: 44
# z: 1 s: 2 summe: 1043
# z: 2 s: 0 summe: 1089
# z: 2 s: 1 summe: 1113
# z: 2 s: 2 summe: 1114
# z: 2 s: 3 summe: 1115
# z: 3 s: 0 summe: 1128
# 114.6
. . . und nochmal kompakter aufgeschrieben
#--------------------------------------------------------#--------------------------# ddurchschnitt-k.py
# python ddurchschnitt-k.py
# Berechnet den Durchschnitt der durchschnittlichen
# [17, 4] 0
# Zeilensummen eines 2-dimensionalen Arrays.
#
s: 17 zeilens.: 0
#--------------------------------------------------------#
s: 4 zeilens.: 17
import stdio
# [23, 999, 46] 10.5
#
s: 23 zeilens.: 0
werte = [ [17, 4], [23, 999, 46], [24, 1, 1, 13], [18] ] #
s: 999 zeilens.: 23
#
s: 46 zeilen.: 1022
durchschnittsumme = 0
# [24, 1, 1, 13] 366.5
#
s: 24 zeilens.: 0
for z in werte:
#
s: 1 zeilens.: 24
stdio.writeln(str(z) + ' ' + str(durchschnittsumme)) #
s: 1 zeilens.: 25
zeilensumme = 0
#
s: 13 zeilens.: 26
for s in z:
# [18] 376.25
stdio.writeln(' ' + ' s: ' + str(s) +
#
s: 18 zeilens.: 0
' zeilens.: ' + str(zeilensumme))
# 98.5625
zeilensumme += s
durchschnittsumme += float(zeilensumme)/len(z)
stdio.writeln(str(durchschnittsumme/len(werte)))
#-------------------------------------------------------# array-kopieren.py
#-------------------------------------------------------import stdio, stdarray
a = [1, 2, 3, 4, 5]
# Kopiere Array a ins Array b.
# Dazu wird zuerst ein Array der Länge 0 erzeugt.
b = []
for i in range(len(a)):
stdio.writeln('Laenge von b: ' + str(len(b)))
b += [a[i]]
# hänge Wert a[i] an das Array b an
#-------------------------# python array-kopieren.py
# Laenge von b: 0
# Laenge von b: 1
# Laenge von b: 2
# Laenge von b: 3
# Laenge von b: 4
# [1, 2, 3, 4, 5]
# Laenge von c: 5
# Laenge von c: 5
# Laenge von c: 5
# Laenge von c: 5
# Laenge von c: 5
# [1, 2, 3, 4, 5]
stdio.writeln(b)
# Kopiere Array a ins Array c.
# Dazu wird zuerst ein Array der Länge len(a) erzeugt.
c = stdarray.create1D(len(a),0)
for i in range(len(a)):
stdio.writeln('Laenge von c: ' + str(len(c)))
c[i] = a[i]
stdio.writeln(c)
1.3.8
Lesen vieler Eingaben von der Konsole
#-------------------------------------------------------------------------# durchschnitt-eingabe.py
#-------------------------------------------------------------------------import stdio, sys
# Berechne den Durchschnitt der Werte, die über die Konsole eingegeben werden.
# Sie stehen im Array sys.argv[] unter den Indizes 1,2,...,len(sys.arg)-1
summe = 0
for i in range(1,len(sys.argv)):
summe = summe + int(sys.argv[i])
# for i in sys.argv[1:]
#
summe = summe + int(i)
stdio.writeln(str(float(summe)/(len(sys.argv)-1)))
#-------------------------------------------------------------------------# python durchschnitt-eingabe.py 1 2 3 4 5 6 7 8 9 10
# 5.5
1.3.9
# Es wird ausprobiert, wielange man mit einem Würfel mit n Zahlen
# würfeln muss, bis man alle n Zahlen gewürfelt hat.
n = int(sys.argv[1])
# gewuerfelt ist ein Array mit n Einträgen.
# Eintrag i gibt an, ob Zahl i bereits gewuerfelt wurde.
gewuerfelt = stdarray.create1D(n,False)
runden = 100000
wurfzaehler = 0
# Das Experiment wird runden mal ausgeführt.
for i in range(runden):
# Solange nicht jede Zahl einmal gewürfelt wurde, wird weitergewürfelt.
while not min(gewuerfelt):
wurf = random.randrange(0,n)
wurfzaehler += 1
gewuerfelt[wurf] = True
# Nachdem alle Zahlen gewürfelt wurden, wird alles wieder zurückgesetzt.
for i in range(len(gewuerfelt)): gewuerfelt[i] = False
stdio.writeln('Um ' + str(n) + ' Zahlen zu wuerfeln braucht man im Mittel '
+ str(wurfzaehler/runden+1) + ' Wuerfe.')
1.3.10
# Es wird ausprobiert, wie oft man mit einem Würfel mit n Zahlen würfeln muss,
# bis man eine Zahl zum zweiten Mal wirft. (Geburtstagsparadoxon)
n = int(sys.argv[1])
gewuerfelt = stdarray.create1D(n,False)
wurfzaehler = 0
# Der Versuch wird runden mal wiederholt.
runden = 10000
for i in range(runden):
# Es werden Zahlen aus 0..n-1 gewuerfelt.
# Sobald eine Zahl zum zweiten Mal gewürfelt wird, ist das Experiment beendet.
for j in range(n): gewuerfelt[j] = False
for j in range(n):
z = random.randrange(0,n)
wurfzaehler += 1
if gewuerfelt[z]: break
else: gewuerfelt[z] = True
stdio.writeln('Um mit einem ' + str(n) + '-Wuerfel eine Zahl doppelt zu wuerfeln, '
+'braucht man im Mittel ' + str(float(versuchszaehler)/runden) + ' Versuche.')
#---------------------------------------------------------------------------------------------# python geburtstagsparadoxon.py 6
# Um mit einem 6-Wuerfel eine Zahl doppelt zu wuerfeln, braucht man im Mittel 3.759 Versuche.
#
# python geburtstagsparadoxon.py 365
# Um mit einem 365-Wuerfel eine Zahl doppelt zu wuerfeln, braucht man im Mittel 24.5187 Versuche.
1.3.11
#------------------------------------------------------------------------# minsort.py
# Sortieren mittels Minimum-Suche.
# Die zu sortierenden Strings werden von der Kommandozeile gelesen.
#------------------------------------------------------------------------import stdio, sys
m = sys.argv[1:]
for i in range(len(m)-1):
# Bestimme den Index des kleinsten Elements im Indexbereich i..len(m)
min = i
for j in range(i+1,len(m)):
if m[min] > m[j]: min = j
# Tausche das kleinste Element im Indexbereich i..len(m)
# mit dem Element mit Index i.
t = m[min]
m[min] = m[i]
m[i] = t
stdio.writeln(m)
#--------------------------------------------------------------------------# python minsort.py Gallia est omnis divisa in partes tres .
# ['.', 'Gallia', 'divisa', 'est', 'in', 'omnis', 'partes', 'tres']
1.3.12
#--------------------------------------------------------------# magicsquare.py
# Überprüfe, ob das eigegebene Zahlenquadrat ein
# magisches Quadrat ist.
# Dazu müssen alle Zeilen, Spalten und Diagonalen
# die gleiche Summe haben.
#--------------------------------------------------------------import stdio, sys
ms = [ [16, 3, 2, 13], [5, 10, 11, 9], [9, 6, 7, 12], [4, 15, 14, 1] ]
# Prüfe, ob das Array ein Quadrat ist.
laenge = len(ms)
for s in range(laenge):
if len(ms[s]) != laenge: stdio.writeln('Das ist kein Quadrat!')
# Berechne die Mastersumme: das ist die Summe der ersten Zeile.
mastersumme = 0
for s in range(laenge): mastersumme += ms[0][s]
# Vergleiche sie mit den Summen der anderen Zeilen.
for z in range(1,laenge):
zeilensumme = 0
for s in range(len(ms[z])): zeilensumme += ms[z][s]
if zeilensumme != mastersumme: stdio.writeln('Zeile ' + str(z) + ' stimmt nicht!')
1.3.13
# Vergleiche die Mastersumme mit den Summen der Spalten.
for s in range(0,laenge):
spaltensumme = 0
for z in range(laenge): spaltensumme += ms[z][s]
if spaltensumme != mastersumme: stdio.writeln('Spalte ' + str(s) + ' stimmt nicht!')
# Vergleiche die Mastersumme mit den Summen der Diagonalen.
diagonalsumme1 = 0
diagonalsumme2 = 0
for d in range(0,laenge):
diagonalsumme1 += ms[d][d]
diagonalsumme2 += ms[d][laenge-1-d]
if diagonalsumme1 != mastersumme or diagonalsumme2 != mastersumme:
stdio.writeln('Eine Diagonale stimmt nicht!')
#--------------------------------------------------------------------------------------# python magicsquare.py
# Zeile 1 stimmt nicht!
# Spalte 3 stimmt nicht!
1.3.14
Zusammenfassung
Wir wissen grundlegend,
wie man Arrays erzeugt und auf ihre Elemente zugreift.
Erzeugen von Arrays:
[1, 2, 3, [4, 5], 6]
Angabe des gesamten Arrays
b += [15]
Anhängen eines Elements an ein Array
stdarray.create1D(n, val)
Array der Länge n, jedes Element hat Wert val
stdarray.create2D(n, m, val)
n-mal-m Array, jedes Element hat Wert val
a[i:j]
aus Array a[] wird ein neues Array
[a[i], a[i+1], ..., a[j-1]] erzeugt,
i hat Default 0 und j hat Default len(a)
Zugriff auf Elemente von Arrays:
a[i]
das i-te Element von a[]
(indizierter Zugriff)
a[i] = x
ersetze das i-te Element von a[] durch x
(indizierte Zuweisung)
for v in a:
weise v jedes Element von a[] zu
(Durchlaufen)
a[i:j]
ein neues Array [a[i], a[i+1], ..., a[j-1]],
i hat Default 0 und j hat Default len(a)
(Slicing)
Funktionen zum Arbeiten mit Arrays:
len(a)
die Anzahl der Elemente von a[]
sum(a)
die Summe der Elemente von a[]
min(a)
ein kleinstes Element von a[]
max(a)
ein größtes Element von a[]
(sie müssen summierbar sein)
(sie müssen vergleichbar sein)
(sie müssen vergleichbar sein)
Herunterladen