Leistungsprogrammierung: O (1 ^ N), O (N ^ 1), O (2 ^ N), O (N ^ 2) in einem

65

Schreiben Sie ein Programm (oder eine Funktion), das / die je nach Ausführung vier häufig auftretende große O- Zeit-Komplexitäten aufweist. In jeder Form nimmt es eine positive ganze Zahl N an, von der Sie annehmen können, dass sie kleiner als 2 31 ist .

  1. Wenn das Programm in seiner ursprünglichen Form ausgeführt wird, sollte es eine konstante Komplexität aufweisen. Das heißt, die Komplexität sollte Θ (1) oder äquivalent Θ (1 ^ N) sein .

  2. Wenn das Programm umgekehrt und ausgeführt wird, sollte es eine lineare Komplexität haben. Das heißt, die Komplexität sollte Θ (N) oder äquivalent Θ (N ^ 1) sein .
    (Dies macht Sinn , da N^1wird 1^Numgekehrt.)

  3. Wenn das Programm verdoppelt , dh auf sich selbst verkettet, und führen Sie es haben sollte exponentielle Komplexität, und zwar 2 N . Das heißt, die Komplexität sollte Θ (2 ^ N) sein .
    (Dies ist sinnvoll, da das 2In 2^Ndas Doppelte des 1In ist 1^N.)

  4. Wenn das Programm verdoppelt und umgekehrt und ausgeführt wird, sollte es eine polynomielle Komplexität aufweisen, insbesondere N 2 . Das heißt, die Komplexität sollte Θ (N ^ 2) sein .
    (Dies macht Sinn , da N^2wird 2^Numgekehrt.)

Diese vier Fälle sind die einzigen, die Sie behandeln müssen.

Beachten Sie, dass ich aus Präzisionsgründen die Big-Theta (Θ) -Notation anstelle von Big-O verwende, da die Laufzeiten Ihrer Programme sowohl oben als auch unten durch die erforderlichen Komplexitäten begrenzt sein müssen. Andernfalls würde nur das Schreiben einer Funktion in O (1) alle vier Punkte erfüllen. Es ist nicht so wichtig, die Nuance hier zu verstehen. Wenn Ihr Programm hauptsächlich k * f (N) Operationen für eine Konstante k ausführt, ist dies wahrscheinlich in Θ (f (N)).

Beispiel

Wenn das Originalprogramm wäre

ABCDE

dann sollte das Laufen eine konstante Zeit in Anspruch nehmen. Das heißt, ob der Eingang N 1 oder 2147483647 (2 31 -1) ist oder ein Wert dazwischen, er sollte ungefähr in der gleichen Zeitspanne enden.

Die umgekehrte Version des Programms

EDCBA

sollte in N. ausgedrückt lineare Zeit in Anspruch nehmen. Das heißt, die Zeit, die zum Beenden benötigt wird, sollte in etwa proportional zu N sein. N = 1 dauert also am wenigsten und N = 2147483647 dauert am meisten.

Die doppelte Version des Programms

ABCDEABCDE

Dies bedeutet, dass die Zeit, die zum Beenden benötigt wird, ungefähr proportional zu 2 N sein sollte . Wenn also N = 1 in ungefähr einer Sekunde endet, würde N = 60 länger als das Alter des Universums brauchen, um zu enden. (Nein, du musst es nicht testen.)

Die doppelte und umgekehrte Version des Programms

EDCBAEDCBA

Die Zeit, die zum Beenden benötigt wird, sollte ungefähr proportional zu N * N sein. Wenn also N = 1 in ungefähr einer Sekunde endet, würde N = 60 ungefähr eine Stunde dauern, um zu beenden.

Einzelheiten

  • Sie müssen zeigen oder argumentieren, dass Ihre Programme in der von Ihnen angegebenen Komplexität ausgeführt werden. Das Eingeben von Zeitdaten ist eine gute Idee, aber versuchen Sie auch zu erklären, warum die Komplexität theoretisch korrekt ist.

  • Es ist in Ordnung, wenn in der Praxis die Zeiten, die Ihre Programme einnehmen, nicht perfekt für ihre Komplexität (oder sogar deterministisch) repräsentativ sind. zB Eingabe N + 1 läuft manchmal schneller als N.

  • Die Umgebung, in der Sie Ihre Programme ausführen, spielt eine Rolle. Sie können grundlegende Annahmen darüber treffen, wie populäre Sprachen niemals absichtlich Zeit in Algorithmen verschwenden. Wenn Sie jedoch beispielsweise wissen, dass Ihre Java-Version die Blasensortierung anstelle eines schnelleren Sortieralgorithmus implementiert , sollten Sie dies berücksichtigen, wenn Sie eine Sortierung durchführen .

  • Bei aller Komplexität wird angenommen, dass es sich um Worst-Case-Szenarien handelt , nicht um Best-Case- oder Average-Case -Szenarien .

  • Die räumliche Komplexität der Programme spielt keine Rolle, nur die zeitliche Komplexität.

  • Die Programme können alles ausgeben. Es kommt nur darauf an, dass sie eine positive ganze Zahl N aufnehmen und die richtigen zeitlichen Komplexitäten aufweisen.

  • Kommentare und mehrzeilige Programme sind erlaubt. (Sie können davon ausgehen, dass dies aus \r\nGründen der \r\nWindows-Kompatibilität umgekehrt ist .)

Big O Erinnerungen

Vom schnellsten zum langsamsten O(1), O(N), O(N^2), O(2^N)(Reihenfolge 1, 2, 4, 3 oben).

Langsamere Begriffe dominieren immer, z O(2^N + N^2 + N) = O(2^N).

O(k*f(N)) = O(f(N))für konstante k. Also O(2) = O(30) = O(1)und O(2*N) = O(0.1*N) = O(N).

Erinnere dich an O(N^2) != O(N^3)und O(2^N) != O(3^N).

Ordentliches großes O-Spickzettel.

Wertung

Dies ist normaler Code Golf. Das kürzeste ursprüngliche Programm (die konstante Zeit eins) in Bytes gewinnt.

Calvins Hobbys
quelle
Hervorragende Frage! Kleiner Punkt: Wir müssen nicht Worst-Case / Best-Case / Average-Case angeben, da die einzige Eingabe, die als Größe N zählt, die Zahl N selbst ist (was übrigens nicht der übliche Begriff der Eingabegröße ist: das wäre Behandle die Eingabe N als Größe log N). Es gibt also nur einen Fall für jedes N, was gleichzeitig der beste, schlechteste und durchschnittliche Fall ist.
ShreevatsaR
5
Es scheint, dass Sie von den üblichen Definitionen der Komplexität abgewichen sind. Wir definieren die zeitliche Komplexität eines Algorithmus immer als Funktion der Größe seiner Eingabe . In dem Fall, in dem die Eingabe eine Zahl ist, ist die Größe der Eingabe der Logarithmus zur Basis 2 dieser Zahl. Das Programm n = input(); for i in xrange(n): passhat also eine exponentielle Komplexität, weil es 2 ** kSchritte ausführt, bei denen k = log_2(n)die Eingabegröße ist. Sie sollten klären, ob dies der Fall ist, da sich dadurch die Anforderungen dramatisch ändern.
wchargin

Antworten:

36

Python 3 , 102 Bytes

try:l=eval(input());k=1#)]0[*k**l(tnirp
except:k=2#2=k:tpecxe
print(k**l*[0])#1=k;))(tupni(lave=l:yrt

Probieren Sie es online!

Dies ist von O (1 ^ n), da dies das Programm tut:

  • bewerten Sie die Eingabe
  • Erstelle das Array [0]
  • Druck es

Rückgängig gemacht:


try:l=eval(input());k=1#)]0[*l**k(tnirp
except:k=2#2=k:tpecxe
print(l**k*[0])#1=k;))(tupni(lave=l:yrt

Probieren Sie es online!

Dies ist von O (n ^ 1), da dies das Programm tut:

  • bewerten Sie die Eingabe
  • Erstelle das Array [0] * Eingabe (0 wird so oft wie die Eingabe wiederholt)
  • Druck es

Verdoppelt:

try:l=eval(input());k=1#)]0[*k**l(tnirp
except:k=2#2=k:tpecxe
print(k**l*[0])#1=k;))(tupni(lave=l:yrt
try:l=eval(input());k=1#)]0[*k**l(tnirp
except:k=2#2=k:tpecxe
print(k**l*[0])#1=k;))(tupni(lave=l:yrt

Probieren Sie es online!

Dies ist von O (2 ^ n), da dies das Programm tut:

  • bewerten Sie die Eingabe
  • Erstelle das Array [0]
  • Druck es
  • versuchen Sie die Eingabe auszuwerten
  • Scheitern
  • erstelle das Array [0] * (2 ^ Eingabe) (0 wird so oft wiederholt wie 2 ^ Eingabe)
  • Druck es

Verdoppelt und umgekehrt:


try:l=eval(input());k=1#)]0[*l**k(tnirp
except:k=2#2=k:tpecxe
print(l**k*[0])#1=k;))(tupni(lave=l:yrt
try:l=eval(input());k=1#)]0[*l**k(tnirp
except:k=2#2=k:tpecxe
print(l**k*[0])#1=k;))(tupni(lave=l:yrt

Probieren Sie es online!

Dies ist von O (n ^ 2), da dies das Programm tut:

  • bewerten Sie die Eingabe
  • Erstelle das Array [0] * Eingabe (0 wird so oft wie die Eingabe wiederholt)
  • Druck es
  • versuchen Sie die Eingabe auszuwerten
  • Scheitern
  • erstelle das Array [0] * (Eingabe ^ 2) (0 wird so oft wiederholt wie die Eingabe im Quadrat)
  • Druck es
Undichte Nonne
quelle
Warum bleibt es bei mehreren Anrufen nicht hängen und wartet auf Benutzerinteraktion input()?
Jonathan Allan
1
Es ist eine Lücke, dass "Ende der Übertragung" am Ende der Übertragung übertragen wird?
Undichte Nonne
1
Kannst du es erklären?
Brain Guider
1
Betreff: Das Argument "Ende der Datei", Sie betrachten die Dinge rückwärts. Wenn Sie ein Terminal verwenden, hängen die Eingabeaufforderungen, weil etwas damit verbunden ist. ctrl-D kann gesendet werden, um explizit keine Eingabe zu senden. Wenn die Eingabe mit einer leeren Datei verbunden ist (wie TIO, wenn Sie das Eingabefeld leer lassen), oder wenn sie mit einer Datei verbunden ist, in der alle Eingaben gelesen wurden, muss die Eingabeaufforderung nichts tun. Es weiß bereits, dass es keine Eingabe gibt. Unter UNIX / Linux sind "Dateiende" und "Keine Eingabe verfügbar" bei regulären Dateien nicht zu unterscheiden.
3
Ist der erste Fall kder Eingang und leiner, so dass Sie immer noch rechnen 1**k, richtig? Was sollte O(log(k))Zeit in Anspruch nehmen , obwohl Sie und ich und jeder im Voraus wissen, dass es eins ist?
Richard Rast
18

Perl 5, 82 73 71 + 1 (für -n Flag) = 72 Bytes

Ich bin mir sicher, dass ich dies (viel) mehr Golf spielen kann, aber es ist Schlafenszeit, ich habe genug Zeit mit dem Debuggen verbracht und ich bin trotzdem stolz auf das, was ich bisher habe.

#x$=_$;
$x.=q;#say for(1..2**$_)#)_$..1(rof _$=+x$;;
eval $x;$x=~s/#//;

Das Programm selbst verwendet die Eingabe nicht und wertet nur einen String aus, der mit einem Kommentar beginnt, und ersetzt ihn dann durch einen einzelnen String, sodass dies eindeutig in konstanter Zeit erfolgt. Es ist im Grunde gleichbedeutend mit:

$x="#";
eval $x;
$x=~s/#//;

Verdoppelt:

#x$=_$;
$x.=q;#say for(1..2**$_)#)_$..1(rof _$=+x$;;
eval $x;$x=~s/#//;
#x$=_$;
$x.=q;#say for(1..2**$_)#)_$..1(rof _$=+x$;;
eval $x;$x=~s/#//;

Das Bit, das tatsächlich exponentielle Zeit benötigt, ist die zweite Auswertung: Es wertet den Befehl aus say for(1..2**$_), der alle Zahlen von 1 bis 2 ^ N auflistet, was eindeutig exponentielle Zeit benötigt.

Rückgängig gemacht:

;//#/s~=x$;x$ lave
;;$x+=$_ for(1..$_)#)_$**2..1(rof yas#;q=.x$
;$_=$x#

Dies berechnet (naiv) die Summe der Eingabe, die eindeutig eine lineare Zeit benötigt (da jede Addition in konstanter Zeit erfolgt). Der Code, der tatsächlich ausgeführt wird, entspricht:

$x+=$_ for(1..$_);
$_=$x;

Die letzte Zeile ist nur so, dass bei Wiederholung dieser Befehle quadratische Zeit benötigt wird.

Umgekehrt und verdoppelt:

;//#/s~=x$;x$ lave
;;$x+=$_ for(1..$_)#)_$**2..1(rof yas#;q=.x$
;$_=$x#
;//#/s~=x$;x$ lave
;;$x+=$_ for(1..$_)#)_$**2..1(rof yas#;q=.x$
;$_=$x#

Dies nimmt nun die Summe der Summe der Eingabe (und fügt sie der Summe der Eingabe hinzu, aber was auch immer). Da es N^2Hinzufügungen in der Reihenfolge ausführt, dauert dies quadratisch. Es ist im Grunde gleichbedeutend mit:

$x=0;
$x+=$_ for(1..$_);
$_=$x;
$x+=$_ for(1..$_);
$_=$x;

In der zweiten Zeile wird die Summe der Eingaben ermittelt, wobei NAdditionen ausgeführt werden, während in der vierten Zeile summation(N)Additionen ausgeführt werden O(N^2).

Chris
quelle
Toll! Das in einer Mainstream-Sprache zu machen, wäre schwierig gewesen! Das hat meine Zustimmung!
Arjun
Gut gemacht, das ist ziemlich nett. Sie meinten wahrscheinlich $x.=q;##say...stattdessen $x.=q;#say...(mit zwei #statt 1). (Das würde erklären, warum Sie 76 Bytes statt 75 gezählt haben). Außerdem sollten Sie -nin Ihrem bytecount flag zählen, da Ihr Programm ohne dieses Flag nicht viel anfängt.
Dada
@Dada Ich habe versehentlich die evalund die s///Befehle vertauscht . Wenn du das evalerste machst, brauchst du nur das eine #. Guter Fang!
Chris
@ Chris Richtig, es funktioniert in der Tat. Vielleicht können Sie das Letzte weglassen #: $x=~s/#//;Umgekehrtes Produzieren ;//#/s~=x$, was in Ihrem Kontext nichts bewirkt, wie es bei einem führenden Produkt der Fall wäre #. (Ich habe es aber nicht getestet). Egal, haben Sie eine +1!
Dada
@Dada Schöner Fang noch einmal!
Chris
17

Eigentlich 20 Bytes

";(1╖╜ⁿr"ƒ"rⁿ@╜╖1(;"

Probieren Sie es online!

Eingang: 5

Ausgabe:

rⁿ@╜╖1(;
[0]
5

Rückgängig gemacht:

";(1╖╜@ⁿr"ƒ"rⁿ╜╖1(;"

Probieren Sie es online!

Ausgabe:

rⁿ╜╖1(;
[0, 1, 2, 3, 4]
5

Verdoppelt:

";(1╖╜ⁿr"ƒ"rⁿ@╜╖1(;"";(1╖╜ⁿr"ƒ"rⁿ@╜╖1(;"

Probieren Sie es online!

Ausgabe:

rⁿ@╜╖1(;
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
rⁿ@╜╖1(;
rⁿ@╜╖1(;
[0]

Verdoppelt und umgekehrt:

";(1╖╜@ⁿr"ƒ"rⁿ╜╖1(;"";(1╖╜@ⁿr"ƒ"rⁿ╜╖1(;"

Probieren Sie es online!

Ausgabe:

rⁿ╜╖1(;
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
rⁿ╜╖1(;
rⁿ╜╖1(;
[0, 1, 2, 3, 4]

Hauptidee

Eigentlich ist eine Stack-basierte Sprache.

  • abcist ein Programm mit O (1 n ) -Komplexität, und sein Doppel hat O (2 n ) -Komplexität.
  • defist ein Programm mit O (n 1 ) -Komplexität, und sein Doppel hat O (n 2 ) -Komplexität.

Dann ist meine Vorlage "abc"ƒ"fed", wo ƒausgewertet wird. Auf diese Weise "fed"wird nicht ausgewertet.

Erstellung eines individuellen Programms

Der Pseudocode der ersten Komponente ;(1╖╜ⁿr:

register += 1 # register is default 0
print(range(register**input))

Der Pseudocode der zweiten Komponente ;(1╖╜ⁿ@r:

register += 1 # register is default 0
print(range(input**register))
Undichte Nonne
quelle
Ich hätte nie gedacht, dass das überhaupt möglich ist! Großartige Arbeit, Sir! +1
Arjun
@ Arjun Vielen Dank für Ihre Wertschätzung.
Undichte Nonne
Dies ist hervorragend und stellt sich der Herausforderung, indem keine IMO-Kommentare verwendet werden. Genial!
ShreevatsaR
1
Nun, das hat tatsächlich Kommentare ... die Zeichenfolgen sind nicht bewertet und sind NOPs ...
Leaky Nun
4

Gelee , 20 Bytes

Teilweise inspiriert von Leaky Nuns Actually-Lösung .

Die führenden und nachfolgenden Zeilenumbrüche sind signifikant.

Normal:


⁵Ŀ⁵
R
R²
2*R
‘
⁵Ŀ⁵

Probieren Sie es online!

Eingang: 5

Ausgabe:

610

Rückgängig gemacht:


⁵Ŀ⁵
‘
R*2
²R
R
⁵Ŀ⁵

Probieren Sie es online!

Eingang: 5

Ausgabe:

[1, 2, 3, 4, 5]10

Verdoppelt


⁵Ŀ⁵
R
R²
2*R
‘
⁵Ŀ⁵

⁵Ŀ⁵
R
R²
2*R
‘
⁵Ŀ⁵

Probieren Sie es online!

Eingang: 5

Ausgabe:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]10

Verdoppelt und umgekehrt


⁵Ŀ⁵
‘
R*2
²R
R
⁵Ŀ⁵

⁵Ŀ⁵
‘
R*2
²R
R
⁵Ŀ⁵

Probieren Sie es online!

Eingang: 5

Ausgabe:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]10

Erläuterung

Der Schlüssel hier ist in Ŀ, was bedeutet, "ruft den Link am Index n als Monade auf". Die Links werden beginnend mit 1 von oben nach unten indiziert, mit Ausnahme des Hauptlinks (des untersten Links). Ŀist ebenfalls modular aufgebaut. Wenn Sie also versuchen, die Verbindungsnummer 7 von 5 Verbindungen anzurufen, rufen Sie tatsächlich die Verbindungsnummer 2 an.

Der in diesem Programm aufgerufene Link ist immer der Link mit Index 10 ( ), unabhängig von der Programmversion. Welcher Link sich jedoch auf Index 10 befindet, hängt von der Version ab.

Das , das nach jedem angezeigt wird, Ŀist dort, also bricht es nicht, wenn es aufgehoben wird. Das Programm wird beim Parsen fehlschlagen, wenn es vorher keine Nummer gibt Ŀ. Ein After zu haben, ist ein fehl am Platz, der direkt zum Ausgang geht.

In der Originalversion wird der Link aufgerufen, der n + 1 berechnet.

In der umgekehrten Version wird der Link aufgerufen R, der den Bereich 1 .. n generiert.

Die doppelte Version ruft den Link auf 2*R, der 2 n berechnet und den Bereich 1 .. 2 n generiert .

Die doppelte und umgekehrte Version ruft den Link auf ²R, der n 2 berechnet und den Bereich 1 .. n 2 generiert .

Geschäfts-Katze
quelle
4

Befunge-98 , 50 Bytes

Normal

\+]#:\-1vk  !:;#
@k!:-1 .: ;#]#$ <;
[*:>@ 
&$< ^&;

Dies ist bei weitem das einfachste Programm der 4 - die einzigen Befehle, die ausgeführt werden, sind die folgenden:

\+]
  !
  : @
&$< ^&;

Dieses Programm führt einige irrelevante Aktionen aus, bevor Sie einen "Rechts abbiegen" -Befehl ( ]) und einen Pfeil drücken . Dann drückt es 2 "Eingabe" -Befehle. Da die Eingabe nur eine Zahl enthält und TIO &s behandelt , wird das Programm nach 60 Sekunden beendet. Wenn es 2 Eingänge gibt (und weil ich das kann, ohne Bytes hinzuzufügen), würde die IP in die Funktion "Programm beenden" hochfahren.

Probieren Sie es online!

Rückgängig gemacht

;&^ <$&
 @>:*[
;< $#]#; :. 1-:!k@
#;:!  kv1-\:#]+\

Dieser ist etwas komplizierter. Die relevanten Befehle lauten wie folgt:

;&^  $
  >:*[
;< $#]#; :. 1-:!k@
  :

das ist äquivalent zu

;&^                   Takes input and sends the IP up. the ; is a no-op
  :                   Duplicates the input.
  >:*[                Duplicates and multiplies, so that the stack is [N, N^2
     $                Drops the top of the stack, so that the top is N
     ]#;              Turns right, into the loop
         :.           Prints, because we have space and it's nice to do
            1-        Subtracts 1 from N
              :!k@    If (N=0), end the program. This is repeated until N=0
;< $#]#;              This bit is skipped on a loop because of the ;s, which comment out things

Der wichtige Teil hier ist das :. 1-:!k@Bit. Dies ist nützlich, da wir die gewünschte Komplexität erhalten können, solange wir die richtige Komplexität auf den Stapel schieben, bevor wir sie in einer niedrigeren Zeitkomplexität ausführen. Dies wird in den verbleibenden 2 Programmen auf diese Weise verwendet.

Probieren Sie es online!

Verdoppelt

\+]#:\-1vk  !:;#
@k!:-1 .: ;#]#$ <;
[*:>@ 
&$< ^&;\+]#:\-1vk  !:;#
@k!:-1 .: ;#]#$ <;
[*:>@ 
&$< ^&;

Und die relevanten Befehle sind:

\+]
  !
  :
&$< ^&;\+]#:\-1vk  !:;#
@k!:-1 .: ;#]#$ <;

Dieses Programm besteht aus 2 Schleifen. Erstens folgt es dem gleichen Pfad wie das normale Programm, das 1 und N auf den Stapel legt, aber anstatt auf den zweiten zu &wechseln, springt die IP über einen Kommentar in eine Schleife, die Folgendes überträgt 2^N:

        vk!:    If N is 0, go to the next loop.
      -1        Subtract 1 from N
 +  :\          Pulls the 1 up to the top of the stack and doubles it
  ]#            A no-op
\               Pulls N-1 to the top again

Die anderen Bits in Zeile 4 werden mit ;s übersprungen

Nachdem (2 ^ N) auf den Stapel geschoben wurde, bewegen wir uns eine Zeile nach unten in die oben erwähnte Druckschleife. Aufgrund der ersten Schleife ist die Zeitkomplexität Θ (N + 2 ^ N), dies reduziert sich jedoch auf Θ (2 ^ N).

Probieren Sie es online!

Verdoppelt und umgekehrt

;&^ <$&
 @>:*[
;< $#]#; :. 1-:!k@
#;:!  kv1-\:#]+\;&^ <$&
 @>:*[
;< $#]#; :. 1-:!k@
#;:!  kv1-\:#]+\

Die relevanten Befehle:

;&^

;< $#]#; :. 1-:!k@

 @>:*[

  :

Dies funktioniert fast identisch mit dem umgekehrten Programm, aber das Programm N^2wird nicht aus dem Stapel entfernt, da die erste Zeile der zweiten Kopie des Programms an die letzte Zeile der ersten angefügt wird, was bedeutet, dass der Befehl drop ( $) niemals ausgeführt wird , so gehen wir in die Druckschleife mit N^2auf der Oberseite des Stapels.

Probieren Sie es online!

MilderMilquetoast
quelle