Dieses HTML-Dokument ist ein Arbeitsblatt zur Cantormenge und ihren
Varianten. Sie können es als HTML-Dokument lesen. Tatsächlich können Sie
es aber auch mit Ihrem Computer bearbeiten. Das Arbeitsblatt ist keine
Einführung in Programmierung. Stattdessen werden Programme
bereitgestellt, mit denen Sie Cantormengen erzeugen können. Sie können
diese Programme nach Belieben abändern und so auf dem Computer mit
Cantormengen experimentieren.
Wir arbeiten mit dem frei erhältlichen Statistik-Programm RStudio und der
Programmiersprache R.
Sie können dieses HTML-Dokument im RMD-Format abspeichern, siehe die
Schaltfläche Code rechts oben. Sie können das RMD-Dokument dann
in RStudio öffnen, und Sie können die bereitgestellten Programme auf
Ihrem Computer ausführen.
Die Cantormenge
Man erhält die Cantormenge \(C\subset
[0,1]\) als Schnitt \(C=\bigcap_{n\in\mathbb N_0}C_n\)
absteigender Mengen \([0,1]=C_0\supset C_1
\supset C_2 \supset \ldots\) Bei der Konstruktion von \(C_{n+1}\) entfernt man aus jedem Intervall
in \(C_n\) jeweils ein offenes
Intervall, das mittlere Drittel.
Auf dem Computer kann man die Konstruktion von \(C_n\) wie folgt codieren. Sie können den
folgenden Code einlesen, indem Sie auf das Pfeilsymbol klicken.
U=c(1,0,1)
erzeuge = function(n) if (n==0) return(1) else return( U %x% erzeuge(n-1))
Der Aufruf erzeuge(n) liefert eine 01-Punktmenge, welche
\(C_n\) entspricht. Der Ausdruck
U beschreibt die Unterteilung des Einheitsintervalls.
erzeuge(2)
[1] 1 0 1 0 0 0 1 0 1
Mit dem R-Befehl plot können Sie diese Punktmenge graphisch
darstellen. Das Argument type=“h” ergibt eine Darstellung als
Histogramm mit Balken der Höhe \(0\)
oder \(1\). Die Menge \(C_n\) entspricht einem horizontalen Schnitt
im folgenden Bild.
n=5; plot(erzeuge(n), type="h")

Der Cantor-Staub
Die obige Konstruktion kann man auf zweidimensionale Punktmengen
erweitern. Man startet mit dem Einheitsquadrat und unterteilt es in 9
kleinere Quadrate. Dann entfernt man die 5 mittleren Quadrate. Mit
dieser Konstruktion fährt man fort und erhält so den Cantor-Staub.
U = array(c(1,0,1, 0,0,0, 1,0,1), dim=c(3,3))
n=1; erzeuge(n)
[,1] [,2] [,3]
[1,] 1 0 1
[2,] 0 0 0
[3,] 1 0 1
Die Unterteilung wird durch eine \(01\)-Matrix dargestellt. Man kann solche
Matrizen mit dem Befehl image visualisieren.
for (n in 1:4) image(erzeuge(n))




Der Sierpinski-Teppich
Eine Variante der obigen Konstruktion besteht darin, dass man von den
9 kleinen Quadraten lediglich das mittlere Quadrat entfernt. Die
zugehörige Punktmenge nennt man den Sierpinski-Teppich.
U= array(c(1,1,1, 1,0,1, 1,1,1), dim=c(3,3))
for (n in 1:4) image(erzeuge(n))




zufällige Sierpinksi-Teppiche
Man kann die obigen Konstruktionen randomisieren. Zum Beispiel kann
man per Münzwurf entscheiden, ob man für ein Quadrat die
Sierpinski-Konstruktion durchführt, oder ob man stattdessen alle 9
Teilquadrate entfernt.
Auf dem Computer kann man hierzu folgendes Programm schreiben.
# ersetze "x" durch "0" mit Wkeit p
x0 = function(x) sample(c(0,x),1,prob=c(p,1-p))
# loesche Eintraege des Arrays A mit Wkeit p
loesche = function(A) array(sapply(A,x0), dim=dim(A))
# erzeuge eine zufaellige Cantor-Menge
erzeuge_zu = function(n) if (n==0) return(1) else return( loesche(U %x% erzeuge_zu(n-1)))
Die Funktion zu implementiert den Münzwurf auf dem Computer.
Für eine Matrix aus Nullen und Einsen werden alle Einträge mit
Zufallszahlen \(0\) oder \(1\) aus einem Münzwurf multipliziert.
Hierbei tritt \(0\) mit
Wahrscheinlichkeit \(p\) auf, und \(1\) tritt mit Wahrscheinlichkeit \(1-p\) auf.
Die Funktion rp setzt einen Wert \(x\) mit Wahrscheinlichkeit \(p\) auf \(0\).
Hier ist ein zufälliger Sierpinski-Teppich.
p=0.1
# U= array(c(1,0,1 ,0,0,0, 1,0,1), dim=c(3,3)) # Cantor-Staub
U= array(c(1,1,1, 1,0,1, 1,1,1), dim=c(3,3)) # Sierpinski-Teppich
image(erzeuge_zu(2))

Für kleine Wahrscheinlichkeiten ergeben sich Punktmengen, die dem
Sierpinski-Teppich sehr ähnlich sind. Für große Wahrscheinlichkeiten
zerfällt der Sierpinski-Teppich. Man kann sich nun die Frage stellen, ab
welcher Wahrscheinlicheit der Sierpinski-Teppich zerfällt. Diese Frage
kann man experimentell untersuchen. Man kann sie auch mathematisch
präzisieren und mit Methoden der Stochastik untersuchen. Der zufällige
Sierpinski-Teppich ist ein einfaches Modell für sogenannte
Perkolation.
Der Menger-Schwamm
Man kann die Konstruktion der Cantor-Menge und des
Sierpinski-Teppichs auf drei Dimensionen verallgemeinern. Dies führt auf
den sogenannten Menger-Schwamm.
U=array(c(1,1,1,1,0,1,1,1,1, 1,0,1,0,0,0,1,0,1, 1,1,1,1,0,1,1,1,1), dim=c(3,3,3))
Menger=erzeuge(2)
Die graphische Darstellung in drei Dimensionen erfolgt in einem
eigenen Fenster. Dieses Fenster kann nicht im HTML-Dokument dargestellt
werden, sondern setzt das Programm RStudio voraus.
Die graphische Darstellung kann mit dem R-Paket rgl wie
folgt programmiert werden. Das Paket befindet sich nicht im Grundumfang
von R, sondern muss zunächst mit install.packages(“rgl”)
installiert werden.
# Paket rgl installieren (Befehl auskommentiert)
# install.packages("rgl")
# Paket rgl einlesen
library(rgl)
# Funktion fuer graphische Ausgabe definieren
zeige3d=function(A){
# get the coordinates of the "1" entries
co3d = which(A == 1, arr.ind = TRUE, useNames=FALSE)
# determine number of "1" entries
n=dim(co3d)[1]
# convert to points in 3d by adding "0" in missing dimensions
# get dimension of array
d=length(dim(A))
# add one 0-column if not three-dimensional:
if (d<3) co3d=cbind(co3d, rep(0,n))
# add another 0-column if one-dimensional:
if (d==1) co3d=cbind(co3d, rep(0,n))
# open new plot window
open3d()
# draw cubes at every "1" position
for (i in 1:n) {
# get coordinates
pt=2*co3d[i,]
# plot cube at position pt
shade3d( translate3d( cube3d(col = "green"), pt[1], pt[2], pt[3]) )
}
}
Mit der Funktion zeige3d lässt sich nun der Menger-Schwamm
leicht darstellen.
# U=array(c(1,0,1), dim=3) # Cantormenge
# U= array(c(1,0,1,0,0,0,1,0,1), dim=c(3,3)) # Cantor-Staub 2d
# U= array(c(1,1,1,1,0,1,1,1,1), dim=c(3,3)) # Sierpinski-Teppich
# U=array(c(1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,1), dim=c(3,3,3)) # Cantor-Staub 3d
U=array(c(1,1,1,1,0,1,1,1,1,1,0,1,0,0,0,1,0,1,1,1,1,1,0,1,1,1,1), dim=c(3,3,3)) # Menger-Schwamm
M=erzeuge(2)
zeige3d(M)
Sie können mit der Funktion zeige3d auch die Cantormenge und
den Sierpinski-Teppich darstellen. Verwenden Sie hierfür im obigen
Programmcode einfach die entsprechende Unterteilung U.
zufällige Fraktale in 3d
Sie können für alle obigen Unterteilungen U zufällige
Punktmengen dreidimensional darstellen. Wählen Sie wie oben einfach eine
Wahrscheinlichkeit \(p\) und verwenden
Sie die Funktion erzeuge_zu.
# U = array(c(1,0,1), dim=3) # Cantormenge
# U = array(c(1,0,1,0,0,0,1,0,1), dim=c(3,3)) # Cantor-Staub
U = array(c(1,1,1,1,0,1,1,1,1), dim=c(3,3)) # Sierpinski-Teppich
# U=array(c(1,1,1,1,0,1,1,1,1,1,0,1,0,0,0,1,0,1,1,1,1,1,0,1,1,1,1), dim=c(3,3,3)) # Menger-Schwamm
p=0.1; zeige3d(erzeuge_zu(2))
Sierpinski-Dreieck und Tetraeder
Ähnlich zum Sierpinski-Teppich kann man ein gleichseitiges Dreieck in
4 gleichseitige Dreiecke unterteilen und dann das mittlere Dreieck
entfernen. Wiederholt man diese Konstruktion, ergibt sich das
Sierpinski-Dreieck. Dies ist etwas aufwendiger zu programmieren als der
Sierpinski-Teppich. Eine Alternative besteht darin, eine ähnliche
Konstruktion mit einer Unterteilung eines Quadrats in 16 Teilquadrate
durchzuführen.
U= array(c(1,0,0,0,1,1,0,0,1,0,1,0,1,1,1,1), dim=c(4,4)) # Sierpinski-Dreieck
zeige3d(erzeuge(1))
Auch dieses Verfahren kann man auf drei Dimensionen übertragen. Es
ergibt sich der Sierpinski-Tetraeder.
U1=c(1,0,0,0,1,1,0,0,1,0,1,0,1,1,1,1)
U2=c(0,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0)
U3=c(0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0)
U4=c(0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0)
U= array(c(U1, U2, U3, U4), dim=c(4,4,4)) # Sierpinski-Tetraeder
zeige3d(erzeuge(1))
LS0tDQp0aXRsZTogIkV4cGVyaW1lbnRlIG1pdCBDYW50b3JtZW5nZW4iDQphdXRob3I6ICJDaHJpc3RvcGggUmljaGFyZCwgRkFVIEVybGFuZ2VuLU7DvHJuYmVyZywgMTguMDcuMjAyNSINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCkRpZXNlcyBIVE1MLURva3VtZW50IGlzdCBlaW4gQXJiZWl0c2JsYXR0IHp1ciBDYW50b3JtZW5nZSB1bmQgaWhyZW4gVmFyaWFudGVuLiBTaWUga8O2bm5lbiBlcyBhbHMgSFRNTC1Eb2t1bWVudCBsZXNlbi4gVGF0c8OkY2hsaWNoIGvDtm5uZW4gU2llIGVzIGFiZXIgYXVjaCBtaXQgSWhyZW0gQ29tcHV0ZXIgYmVhcmJlaXRlbi4gRGFzIEFyYmVpdHNibGF0dCBpc3Qga2VpbmUgRWluZsO8aHJ1bmcgaW4gUHJvZ3JhbW1pZXJ1bmcuIFN0YXR0ZGVzc2VuIHdlcmRlbiBQcm9ncmFtbWUgYmVyZWl0Z2VzdGVsbHQsIG1pdCBkZW5lbiBTaWUgQ2FudG9ybWVuZ2VuIGVyemV1Z2VuIGvDtm5uZW4uIFNpZSBrw7ZubmVuIGRpZXNlIFByb2dyYW1tZSBuYWNoIEJlbGllYmVuIGFiw6RuZGVybiB1bmQgc28gYXVmIGRlbSBDb21wdXRlciBtaXQgQ2FudG9ybWVuZ2VuIGV4cGVyaW1lbnRpZXJlbi4NCg0KV2lyIGFyYmVpdGVuIG1pdCBkZW0gZnJlaSBlcmjDpGx0bGljaGVuIFN0YXRpc3Rpay1Qcm9ncmFtbSBbUlN0dWRpb10oaHR0cHM6Ly9wb3NpdC5jby9kb3dubG9hZC9yc3R1ZGlvLWRlc2t0b3AvKSB1bmQgZGVyIFByb2dyYW1taWVyc3ByYWNoZSBSLg0KDQpTaWUga8O2bm5lbiBkaWVzZXMgSFRNTC1Eb2t1bWVudCBpbSBSTUQtRm9ybWF0IGFic3BlaWNoZXJuLCBzaWVoZSBkaWUgU2NoYWx0ZmzDpGNoZSAqQ29kZSogcmVjaHRzIG9iZW4uIFNpZSBrw7ZubmVuIGRhcyBSTUQtRG9rdW1lbnQgZGFubiBpbiBSU3R1ZGlvIMO2ZmZuZW4sIHVuZCBTaWUga8O2bm5lbiBkaWUgYmVyZWl0Z2VzdGVsbHRlbiBQcm9ncmFtbWUgYXVmIElocmVtIENvbXB1dGVyIGF1c2bDvGhyZW4uDQoNCiMgRGllIENhbnRvcm1lbmdlDQoNCk1hbiBlcmjDpGx0IGRpZSBDYW50b3JtZW5nZSAkQ1xzdWJzZXQgWzAsMV0kIGFscyBTY2huaXR0ICRDPVxiaWdjYXBfe25caW5cbWF0aGJiIE5fMH1DX24kIGFic3RlaWdlbmRlciBNZW5nZW4gJFswLDFdPUNfMFxzdXBzZXQgQ18xIFxzdXBzZXQgQ18yIFxzdXBzZXQgXGxkb3RzJCBCZWkgZGVyIEtvbnN0cnVrdGlvbiB2b24gJENfe24rMX0kIGVudGZlcm50IG1hbiBhdXMgamVkZW0gSW50ZXJ2YWxsIGluICRDX24kIGpld2VpbHMgZWluIG9mZmVuZXMgSW50ZXJ2YWxsLCBkYXMgbWl0dGxlcmUgRHJpdHRlbC4NCg0KQXVmIGRlbSBDb21wdXRlciBrYW5uIG1hbiBkaWUgS29uc3RydWt0aW9uIHZvbiAkQ19uJCB3aWUgZm9sZ3QgY29kaWVyZW4uIFNpZSBrw7ZubmVuIGRlbiBmb2xnZW5kZW4gQ29kZSBlaW5sZXNlbiwgaW5kZW0gU2llIGF1ZiBkYXMgUGZlaWxzeW1ib2wga2xpY2tlbi4NCg0KYGBge3J9DQpVPWMoMSwwLDEpDQplcnpldWdlID0gZnVuY3Rpb24obikgaWYgKG49PTApIHJldHVybigxKSBlbHNlIHJldHVybiggVSAleCUgZXJ6ZXVnZShuLTEpKQ0KYGBgDQoNCkRlciBBdWZydWYgKmVyemV1Z2UobikqIGxpZWZlcnQgZWluZSAwMS1QdW5rdG1lbmdlLCB3ZWxjaGUgJENfbiQgZW50c3ByaWNodC4gRGVyIEF1c2RydWNrICpVKiBiZXNjaHJlaWJ0IGRpZSBVbnRlcnRlaWx1bmcgZGVzIEVpbmhlaXRzaW50ZXJ2YWxscy4NCg0KYGBge3J9DQplcnpldWdlKDIpDQpgYGANCg0KTWl0IGRlbSBSLUJlZmVobCAqcGxvdCoga8O2bm5lbiBTaWUgZGllc2UgUHVua3RtZW5nZSBncmFwaGlzY2ggZGFyc3RlbGxlbi4gRGFzIEFyZ3VtZW50ICp0eXBlPSJoIiogZXJnaWJ0IGVpbmUgRGFyc3RlbGx1bmcgYWxzIEhpc3RvZ3JhbW0gbWl0IEJhbGtlbiBkZXIgSMO2aGUgJDAkIG9kZXIgJDEkLiBEaWUgTWVuZ2UgJENfbiQgZW50c3ByaWNodCBlaW5lbSBob3Jpem9udGFsZW4gU2Nobml0dCBpbSBmb2xnZW5kZW4gQmlsZC4NCg0KYGBge3J9DQpuPTU7IHBsb3QoZXJ6ZXVnZShuKSwgdHlwZT0iaCIpDQpgYGANCg0KIyBEZXIgQ2FudG9yLVN0YXViDQoNCkRpZSBvYmlnZSBLb25zdHJ1a3Rpb24ga2FubiBtYW4gYXVmIHp3ZWlkaW1lbnNpb25hbGUgUHVua3RtZW5nZW4gZXJ3ZWl0ZXJuLiBNYW4gc3RhcnRldCBtaXQgZGVtIEVpbmhlaXRzcXVhZHJhdCB1bmQgdW50ZXJ0ZWlsdCBlcyBpbiA5IGtsZWluZXJlIFF1YWRyYXRlLiBEYW5uIGVudGZlcm50IG1hbiBkaWUgNSBtaXR0bGVyZW4gUXVhZHJhdGUuIE1pdCBkaWVzZXIgS29uc3RydWt0aW9uIGbDpGhydCBtYW4gZm9ydCB1bmQgZXJow6RsdCBzbyBkZW4gQ2FudG9yLVN0YXViLg0KDQpgYGB7cn0NClUgPSBhcnJheShjKDEsMCwxLCAwLDAsMCwgMSwwLDEpLCBkaW09YygzLDMpKQ0Kbj0xOyBlcnpldWdlKG4pDQpgYGANCg0KRGllIFVudGVydGVpbHVuZyB3aXJkIGR1cmNoIGVpbmUgJDAxJC1NYXRyaXggZGFyZ2VzdGVsbHQuIE1hbiBrYW5uIHNvbGNoZSBNYXRyaXplbiBtaXQgZGVtIEJlZmVobCAqaW1hZ2UqIHZpc3VhbGlzaWVyZW4uDQoNCmBgYHtyfQ0KZm9yIChuIGluIDE6NCkgaW1hZ2UoZXJ6ZXVnZShuKSkNCmBgYA0KDQojIERlciBTaWVycGluc2tpLVRlcHBpY2gNCg0KRWluZSBWYXJpYW50ZSBkZXIgb2JpZ2VuIEtvbnN0cnVrdGlvbiBiZXN0ZWh0IGRhcmluLCBkYXNzIG1hbiB2b24gZGVuIDkga2xlaW5lbiBRdWFkcmF0ZW4gbGVkaWdsaWNoIGRhcyBtaXR0bGVyZSBRdWFkcmF0IGVudGZlcm50LiBEaWUgenVnZWjDtnJpZ2UgUHVua3RtZW5nZSBuZW5udCBtYW4gZGVuIFNpZXJwaW5za2ktVGVwcGljaC4NCg0KYGBge3J9DQpVPSBhcnJheShjKDEsMSwxLCAxLDAsMSwgMSwxLDEpLCBkaW09YygzLDMpKQ0KZm9yIChuIGluIDE6NCkgaW1hZ2UoZXJ6ZXVnZShuKSkNCmBgYA0KDQojIHp1ZsOkbGxpZ2UgU2llcnBpbmtzaS1UZXBwaWNoZQ0KDQpNYW4ga2FubiBkaWUgb2JpZ2VuIEtvbnN0cnVrdGlvbmVuIHJhbmRvbWlzaWVyZW4uIFp1bSBCZWlzcGllbCBrYW5uIG1hbiBwZXIgTcO8bnp3dXJmIGVudHNjaGVpZGVuLCBvYiBtYW4gZsO8ciBlaW4gUXVhZHJhdCBkaWUgU2llcnBpbnNraS1Lb25zdHJ1a3Rpb24gZHVyY2hmw7xocnQsIG9kZXIgb2IgbWFuIHN0YXR0ZGVzc2VuIGFsbGUgOSBUZWlscXVhZHJhdGUgZW50ZmVybnQuDQoNCkF1ZiBkZW0gQ29tcHV0ZXIga2FubiBtYW4gaGllcnp1IGZvbGdlbmRlcyBQcm9ncmFtbSBzY2hyZWliZW4uDQoNCmBgYHtyfQ0KIyBlcnNldHplICJ4IiBkdXJjaCAiMCIgbWl0IFdrZWl0IHANCngwID0gZnVuY3Rpb24oeCkgc2FtcGxlKGMoMCx4KSwxLHByb2I9YyhwLDEtcCkpDQojIGxvZXNjaGUgRWludHJhZWdlIGRlcyBBcnJheXMgQSBtaXQgV2tlaXQgcA0KbG9lc2NoZSA9IGZ1bmN0aW9uKEEpIGFycmF5KHNhcHBseShBLHgwKSwgZGltPWRpbShBKSkNCiMgZXJ6ZXVnZSBlaW5lIHp1ZmFlbGxpZ2UgQ2FudG9yLU1lbmdlDQplcnpldWdlX3p1ID0gZnVuY3Rpb24obikgaWYgKG49PTApIHJldHVybigxKSBlbHNlIHJldHVybiggbG9lc2NoZShVICV4JSBlcnpldWdlX3p1KG4tMSkpKQ0KYGBgDQoNCkRpZSBGdW5rdGlvbiAqenUqIGltcGxlbWVudGllcnQgZGVuIE3DvG56d3VyZiBhdWYgZGVtIENvbXB1dGVyLiBGw7xyIGVpbmUgTWF0cml4IGF1cyBOdWxsZW4gdW5kIEVpbnNlbiB3ZXJkZW4gYWxsZSBFaW50csOkZ2UgbWl0IFp1ZmFsbHN6YWhsZW4gJDAkIG9kZXIgJDEkIGF1cyBlaW5lbSBNw7xuend1cmYgbXVsdGlwbGl6aWVydC4gSGllcmJlaSB0cml0dCAkMCQgbWl0IFdhaHJzY2hlaW5saWNoa2VpdCAkcCQgYXVmLCB1bmQgJDEkIHRyaXR0IG1pdCBXYWhyc2NoZWlubGljaGtlaXQgJDEtcCQgYXVmLg0KDQpEaWUgRnVua3Rpb24gKnJwKiBzZXR6dCBlaW5lbiBXZXJ0ICR4JCBtaXQgV2FocnNjaGVpbmxpY2hrZWl0ICRwJCBhdWYgJDAkLg0KDQpIaWVyIGlzdCBlaW4genVmw6RsbGlnZXIgU2llcnBpbnNraS1UZXBwaWNoLg0KDQpgYGB7cn0NCnA9MC4xDQojIFU9IGFycmF5KGMoMSwwLDEgLDAsMCwwLCAxLDAsMSksIGRpbT1jKDMsMykpICMgQ2FudG9yLVN0YXViDQpVPSBhcnJheShjKDEsMSwxLCAxLDAsMSwgMSwxLDEpLCBkaW09YygzLDMpKSAjIFNpZXJwaW5za2ktVGVwcGljaA0KaW1hZ2UoZXJ6ZXVnZV96dSgyKSkNCmBgYA0KDQpGw7xyIGtsZWluZSBXYWhyc2NoZWlubGljaGtlaXRlbiBlcmdlYmVuIHNpY2ggUHVua3RtZW5nZW4sIGRpZSBkZW0gU2llcnBpbnNraS1UZXBwaWNoIHNlaHIgw6RobmxpY2ggc2luZC4gRsO8ciBncm/Dn2UgV2FocnNjaGVpbmxpY2hrZWl0ZW4gemVyZsOkbGx0IGRlciBTaWVycGluc2tpLVRlcHBpY2guIE1hbiBrYW5uIHNpY2ggbnVuIGRpZSBGcmFnZSBzdGVsbGVuLCBhYiB3ZWxjaGVyIFdhaHJzY2hlaW5saWNoZWl0IGRlciBTaWVycGluc2tpLVRlcHBpY2ggemVyZsOkbGx0LiBEaWVzZSBGcmFnZSBrYW5uIG1hbiBleHBlcmltZW50ZWxsIHVudGVyc3VjaGVuLiBNYW4ga2FubiBzaWUgYXVjaCBtYXRoZW1hdGlzY2ggcHLDpHppc2llcmVuIHVuZCBtaXQgTWV0aG9kZW4gZGVyIFN0b2NoYXN0aWsgdW50ZXJzdWNoZW4uIERlciB6dWbDpGxsaWdlIFNpZXJwaW5za2ktVGVwcGljaCBpc3QgZWluIGVpbmZhY2hlcyBNb2RlbGwgZsO8ciBzb2dlbmFubnRlIFBlcmtvbGF0aW9uLg0KDQojIERlciBNZW5nZXItU2Nod2FtbQ0KDQpNYW4ga2FubiBkaWUgS29uc3RydWt0aW9uIGRlciBDYW50b3ItTWVuZ2UgdW5kIGRlcyBTaWVycGluc2tpLVRlcHBpY2hzIGF1ZiBkcmVpIERpbWVuc2lvbmVuIHZlcmFsbGdlbWVpbmVybi4gRGllcyBmw7xocnQgYXVmIGRlbiBzb2dlbmFubnRlbiBNZW5nZXItU2Nod2FtbS4NCg0KYGBge3J9DQpVPWFycmF5KGMoMSwxLDEsMSwwLDEsMSwxLDEsIDEsMCwxLDAsMCwwLDEsMCwxLCAxLDEsMSwxLDAsMSwxLDEsMSksIGRpbT1jKDMsMywzKSkNCg0KTWVuZ2VyPWVyemV1Z2UoMikNCmBgYA0KDQpEaWUgZ3JhcGhpc2NoZSBEYXJzdGVsbHVuZyBpbiBkcmVpIERpbWVuc2lvbmVuIGVyZm9sZ3QgaW4gZWluZW0gZWlnZW5lbiBGZW5zdGVyLiBEaWVzZXMgRmVuc3RlciBrYW5uIG5pY2h0IGltIEhUTUwtRG9rdW1lbnQgZGFyZ2VzdGVsbHQgd2VyZGVuLCBzb25kZXJuIHNldHp0IGRhcyBQcm9ncmFtbSBSU3R1ZGlvIHZvcmF1cy4NCg0KRGllIGdyYXBoaXNjaGUgRGFyc3RlbGx1bmcga2FubiBtaXQgZGVtIFItUGFrZXQgKnJnbCogd2llIGZvbGd0IHByb2dyYW1taWVydCB3ZXJkZW4uIERhcyBQYWtldCBiZWZpbmRldCBzaWNoIG5pY2h0IGltIEdydW5kdW1mYW5nIHZvbiBSLCBzb25kZXJuIG11c3MgenVuw6RjaHN0IG1pdCAqaW5zdGFsbC5wYWNrYWdlcygicmdsIikqIGluc3RhbGxpZXJ0IHdlcmRlbi4NCg0KYGBge3J9DQojIFBha2V0IHJnbCBpbnN0YWxsaWVyZW4gKEJlZmVobCBhdXNrb21tZW50aWVydCkNCiMgaW5zdGFsbC5wYWNrYWdlcygicmdsIikNCiMgUGFrZXQgcmdsIGVpbmxlc2VuDQpsaWJyYXJ5KHJnbCkNCiMgRnVua3Rpb24gZnVlciBncmFwaGlzY2hlIEF1c2dhYmUgZGVmaW5pZXJlbg0KemVpZ2UzZD1mdW5jdGlvbihBKXsNCiAgIyBnZXQgdGhlIGNvb3JkaW5hdGVzIG9mIHRoZSAiMSIgZW50cmllcw0KICBjbzNkID0gd2hpY2goQSA9PSAxLCBhcnIuaW5kID0gVFJVRSwgdXNlTmFtZXM9RkFMU0UpDQogICMgZGV0ZXJtaW5lIG51bWJlciBvZiAiMSIgZW50cmllcw0KICBuPWRpbShjbzNkKVsxXQ0KICAjIGNvbnZlcnQgdG8gcG9pbnRzIGluIDNkIGJ5IGFkZGluZyAiMCIgaW4gbWlzc2luZyBkaW1lbnNpb25zDQogICMgZ2V0IGRpbWVuc2lvbiBvZiBhcnJheQ0KICBkPWxlbmd0aChkaW0oQSkpDQogICMgYWRkIG9uZSAwLWNvbHVtbiBpZiBub3QgdGhyZWUtZGltZW5zaW9uYWw6DQogIGlmIChkPDMpIGNvM2Q9Y2JpbmQoY28zZCwgcmVwKDAsbikpDQogICMgYWRkIGFub3RoZXIgMC1jb2x1bW4gaWYgb25lLWRpbWVuc2lvbmFsOg0KICBpZiAoZD09MSkgY28zZD1jYmluZChjbzNkLCByZXAoMCxuKSkNCiAgIyBvcGVuIG5ldyBwbG90IHdpbmRvdw0KICBvcGVuM2QoKQ0KICAjIGRyYXcgY3ViZXMgYXQgZXZlcnkgIjEiIHBvc2l0aW9uDQogIGZvciAoaSBpbiAxOm4pIHsNCiAgICAjIGdldCBjb29yZGluYXRlcw0KICAgIHB0PTIqY28zZFtpLF0NCiAgICAjIHBsb3QgY3ViZSBhdCBwb3NpdGlvbiBwdA0KICAgIHNoYWRlM2QoIHRyYW5zbGF0ZTNkKCBjdWJlM2QoY29sID0gImdyZWVuIiksIHB0WzFdLCBwdFsyXSwgcHRbM10pICkNCiAgfQ0KfQ0KYGBgDQoNCk1pdCBkZXIgRnVua3Rpb24gKnplaWdlM2QqIGzDpHNzdCBzaWNoIG51biBkZXIgTWVuZ2VyLVNjaHdhbW0gbGVpY2h0IGRhcnN0ZWxsZW4uDQoNCmBgYHtyfQ0KIyBVPWFycmF5KGMoMSwwLDEpLCBkaW09MykgIyBDYW50b3JtZW5nZQ0KIyBVPSBhcnJheShjKDEsMCwxLDAsMCwwLDEsMCwxKSwgZGltPWMoMywzKSkgIyBDYW50b3ItU3RhdWIgMmQNCiMgVT0gYXJyYXkoYygxLDEsMSwxLDAsMSwxLDEsMSksIGRpbT1jKDMsMykpICMgU2llcnBpbnNraS1UZXBwaWNoDQojIFU9YXJyYXkoYygxLDAsMSwwLDAsMCwxLDAsMSwwLDAsMCwwLDAsMCwwLDAsMCwxLDAsMSwwLDAsMCwxLDAsMSksIGRpbT1jKDMsMywzKSkgIyBDYW50b3ItU3RhdWIgM2QNClU9YXJyYXkoYygxLDEsMSwxLDAsMSwxLDEsMSwxLDAsMSwwLDAsMCwxLDAsMSwxLDEsMSwxLDAsMSwxLDEsMSksIGRpbT1jKDMsMywzKSkgIyBNZW5nZXItU2Nod2FtbQ0KTT1lcnpldWdlKDIpDQp6ZWlnZTNkKE0pDQpgYGANCg0KU2llIGvDtm5uZW4gbWl0IGRlciBGdW5rdGlvbiAqemVpZ2UzZCogYXVjaCBkaWUgQ2FudG9ybWVuZ2UgdW5kIGRlbiBTaWVycGluc2tpLVRlcHBpY2ggZGFyc3RlbGxlbi4gVmVyd2VuZGVuIFNpZSBoaWVyZsO8ciBpbSBvYmlnZW4gUHJvZ3JhbW1jb2RlIGVpbmZhY2ggZGllIGVudHNwcmVjaGVuZGUgVW50ZXJ0ZWlsdW5nICpVKi4NCg0KIyB6dWbDpGxsaWdlIEZyYWt0YWxlIGluIDNkDQoNClNpZSBrw7ZubmVuIGbDvHIgYWxsZSBvYmlnZW4gVW50ZXJ0ZWlsdW5nZW4gKlUqIHp1ZsOkbGxpZ2UgUHVua3RtZW5nZW4gZHJlaWRpbWVuc2lvbmFsIGRhcnN0ZWxsZW4uIFfDpGhsZW4gU2llIHdpZSBvYmVuIGVpbmZhY2ggZWluZSBXYWhyc2NoZWlubGljaGtlaXQgJHAkIHVuZCB2ZXJ3ZW5kZW4gU2llIGRpZSBGdW5rdGlvbiAqZXJ6ZXVnZV96dSouDQoNCmBgYHtyfQ0KIyBVID0gYXJyYXkoYygxLDAsMSksIGRpbT0zKSAjIENhbnRvcm1lbmdlDQojIFUgPSBhcnJheShjKDEsMCwxLDAsMCwwLDEsMCwxKSwgZGltPWMoMywzKSkgIyBDYW50b3ItU3RhdWINClUgPSBhcnJheShjKDEsMSwxLDEsMCwxLDEsMSwxKSwgZGltPWMoMywzKSkgIyBTaWVycGluc2tpLVRlcHBpY2gNCiMgVT1hcnJheShjKDEsMSwxLDEsMCwxLDEsMSwxLDEsMCwxLDAsMCwwLDEsMCwxLDEsMSwxLDEsMCwxLDEsMSwxKSwgZGltPWMoMywzLDMpKSAjIE1lbmdlci1TY2h3YW1tDQpwPTAuMTsgemVpZ2UzZChlcnpldWdlX3p1KDIpKQ0KYGBgDQoNCiMgU2llcnBpbnNraS1EcmVpZWNrIHVuZCBUZXRyYWVkZXINCg0Kw4RobmxpY2ggenVtIFNpZXJwaW5za2ktVGVwcGljaCBrYW5uIG1hbiBlaW4gZ2xlaWNoc2VpdGlnZXMgRHJlaWVjayBpbiA0IGdsZWljaHNlaXRpZ2UgRHJlaWVja2UgdW50ZXJ0ZWlsZW4gdW5kIGRhbm4gZGFzIG1pdHRsZXJlIERyZWllY2sgZW50ZmVybmVuLiBXaWVkZXJob2x0IG1hbiBkaWVzZSBLb25zdHJ1a3Rpb24sIGVyZ2lidCBzaWNoIGRhcyBTaWVycGluc2tpLURyZWllY2suIERpZXMgaXN0IGV0d2FzIGF1ZndlbmRpZ2VyIHp1IHByb2dyYW1taWVyZW4gYWxzIGRlciBTaWVycGluc2tpLVRlcHBpY2guIEVpbmUgQWx0ZXJuYXRpdmUgYmVzdGVodCBkYXJpbiwgZWluZSDDpGhubGljaGUgS29uc3RydWt0aW9uIG1pdCBlaW5lciBVbnRlcnRlaWx1bmcgZWluZXMgUXVhZHJhdHMgaW4gMTYgVGVpbHF1YWRyYXRlIGR1cmNoenVmw7xocmVuLg0KDQpgYGB7cn0NClU9IGFycmF5KGMoMSwwLDAsMCwxLDEsMCwwLDEsMCwxLDAsMSwxLDEsMSksIGRpbT1jKDQsNCkpICMgU2llcnBpbnNraS1EcmVpZWNrDQp6ZWlnZTNkKGVyemV1Z2UoMSkpDQpgYGANCg0KQXVjaCBkaWVzZXMgVmVyZmFocmVuIGthbm4gbWFuIGF1ZiBkcmVpIERpbWVuc2lvbmVuIMO8YmVydHJhZ2VuLiBFcyBlcmdpYnQgc2ljaCBkZXIgU2llcnBpbnNraS1UZXRyYWVkZXIuDQoNCmBgYHtyfQ0KVTE9YygxLDAsMCwwLDEsMSwwLDAsMSwwLDEsMCwxLDEsMSwxKQ0KVTI9YygwLDAsMCwwLDEsMCwwLDAsMCwwLDAsMCwxLDAsMSwwKQ0KVTM9YygwLDAsMCwwLDAsMCwwLDAsMSwwLDAsMCwxLDEsMCwwKQ0KVTQ9YygwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwxLDAsMCwwKQ0KVT0gYXJyYXkoYyhVMSwgVTIsIFUzLCBVNCksIGRpbT1jKDQsNCw0KSkgIyBTaWVycGluc2tpLVRldHJhZWRlcg0KemVpZ2UzZChlcnpldWdlKDEpKQ0KYGBgDQo=