Ein Programm, das Programme druckt


13

Herausforderung

Ihr Ziel ist es, ein Programm zu schreiben, das ein anderes Programm druckt. Dieses gedruckte Programm sollte ein anderes Programm drucken, und das neue Programm sollte bis zum Ende ein anderes Programm drucken.

Regeln

  1. Jedes Programm muss kleiner als 256 Bytes sein. (Wenn dies geändert werden muss, hinterlassen Sie einen Kommentar)
  2. Das letzte Programm muss ein leeres Programm sein.
  3. Es muss eine endliche Anzahl von Programmen geben, damit das Programm kein Quine sein kann.
  4. Die Programme müssen alle in derselben Sprache ausgeführt werden.
  5. Es ist keine Eingabe erlaubt.
  6. Das Gewinnerprogramm ist das Programm, das so viele Programme wie möglich druckt und sich selbst zählt.

Viel Glück!


Die maximale Punktzahl ist 2^2048oder 3.2317e616.
Orlp

Um den Vergleich großer Punktzahlen zu vereinfachen, geben Sie bitte eine Annäherung an Ihre Punktzahl in der Form an, a*10^bin der 1<=a<10und beine natürliche Zahl ist.
Fehler

2
Eigentlich war meine vorherige Rechnung falsch. Angenommen, das Programm muss in Bytes angegeben werden, dann ist die maximal mögliche Punktzahl <Zahl zu lang für Kommentar> oder 1.2673e614.
Orlp

Antworten:


20

CJam, 4,56 × 10 526 Programme

2D#2b{"\256b_(256b:c'\s`_:(er`":T~{;38'ÿ*`{:T~{;63'ÿ*`{:T~{;88'ÿ*`{:T~{;114'ÿ*`{:T~{;140'ÿ*`{:T~{;166'ÿ*`{:T~{;192'ÿ*`{:T~{;219'ÿ*`{Q?\"_~"}s(\T}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}_~

Genaues Ergebnis: 254 219 + 254 192 + 254 166 + 254 140 + 254 114 + 254 88 + 254 63 + 254 38 + 254 13 + 3

Alle Programme müssen mit der ISO-8859-1-Codierung gespeichert werden, um die Dateigrößenbeschränkung einzuhalten.

Vielen Dank an @ChrisDrost, der auf einen Fehler hingewiesen und den Ansatz zum Verschachteln vorgeschlagen hat.

Probieren Sie es online im CJam-Interpreter aus .

254 219 + 2 ≈ 4,56 × 10 526 Programme

Der Linienanteil der Punktzahl kann durch das folgende, viel einfachere Programm 1 erreicht werden .

"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"
{\256b_(256b:c'\s`_:(er`Q?\"_~"}_~

Das Ausführen dieses Programms erzeugt das Programm

"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ"
{\256b_(256b:c'\s`_:(er`Q?\"_~"}_~

und nach 254 219 - 1 weiteren Iterationen das Programm

{\256b_(256b:c'\s`_:(er`Q?\"_~"}_~

Dieses letzte nicht leere Programm wird mit einem Fehler 2 beendet und gibt nichts aus (das leere Programm).

Wie es funktioniert

Angenommen, die Zeichenfolge befindet sich bereits auf dem Stapel.

{      e# Push a code block.
  \    e# Swap the string on top of the code block.
       e# This will cause a runtime error if there is no string on the stack.
  256b e# Convert the string (treated as a base-256 number) to integer (I).
  _(   e# Copy the integer and decrement the copy.
  256b e# Convert the integer into the array of its base-256 digits.
  :c   e# Cast each base-256 digit to character. Converts from array to string.
  '\s  e# Push a string that contains a single backslash.
  `    e# Push its string representation, i.e., the array ['" '\ '\ '"].
  _:(  e# Push a copy and decrement each character. Pushes ['! '[ '[ '!].
  er   e# Perform transliteration to replace "s with !s and \s with [s.
       e# This skips characters that require escaping.
  `    e# Push its string representation, i.e., surround it with double quotes.
  Q    e# Push an empty string.
  ?    e# Select the first string if I is non-zero, the empty string otherwise.
  \    e# Swap the selected string with the code block.
  "_~" e# Push that string on the stack.
}      e#
_~     e# Push a copy of the code block and execute it.
       e# The stack now contains the modified string, the original code block
       e# and the string "_~", producing an almost exact copy of the source.

254 192 ≈ 5,35 × 10 461 weitere Programme

Hier wird es ein bisschen verrückt.

Das erste Programm ist stark komprimierbar. Durch ein ähnliches Programm schreiben , das anstelle des leeren Programm, schließlich das erste Programm aus dem obigen Abschnitt erzeugt, können wir die Punktzahl durch verbessern 254 192 Programme 3 .

Das Programm

"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"
{"\256b_(256b:c'\s`_:(er`":T~{;219'ÿ*`{Q?\"_~"}s(\T}?\"_~"}_~

ist dem ersten Programm des vorherigen Abschnitts ähnlich, und das Ausführen des ersteren und seiner Ausgabe für 254 192 Iterationen erzeugt das letztere.

Angenommen, die Zeichenfolge befindet sich bereits auf dem Stapel:

{                           e# Push a code block.
  "\256b_(256b:c'\s`_:(er`" e# Push that string on the stack.
                            e# The characters inside it behave exactly as
                            e# they did in the previous section.
  :T~                       e# Save the string in T and evaluate it.
  {                         e# If the integer I is non-zero, keep the generated
                            e# string; else:
    ;                       e#   Pop the code block from the stack.
    219'ÿ*`                 e#   Push a string of 219 ÿ's (with double quotes).
    {Q?\"_~"}               e#   Push that block on the stack.
    s                       e#   Push its string representation.
    (\                      e#   Shift out the { and swap it with the tail.
    T                       e#   Push T.
  }?                        e#
  \                         e# Swap the selected string with the code block
                            e# or T with the tail of the code block.
  "_~"                      e# Push that string on the stack.
}                           e#
_~                          e# Push a copy of the code block and execute it.

Moar-Programme

Das erste Programm des vorherigen Abschnitts ist immer noch stark komprimierbar, daher können wir eine ähnliche Methode anwenden und ein Programm schreiben, das nach 254 166 Iterationen das oben genannte Programm erzeugt.

Wenn Sie diese Technik immer und immer wieder wiederholen, bis das Limit von 255 Byte erreicht ist, können Sie insgesamt 254 166 + 254 140 + 254 114 + 254 88 + 254 63 + 254 38 + 254 13 + 1 ≈ 1,59 × 10 399 Programme hinzufügen diejenigen der vorherigen Abschnitte.


1 Neue Zeile zur Verdeutlichung hinzugefügt.
2 Per Konsens über Meta ist dies standardmäßig erlaubt.
3 oder 0,000000000000000000000000000000000000000000000000000000000000000012%



5

JavaScript, 1000 Programme

x=999;
q=";alert(x=999?`q=${JSON.stringify(q)+q}`.split(x).join(x-1):``)";
alert(
    x ? `x=999;q=${JSON.stringify(q)+q}`.split(x).join(x-1) // basically .replaceAll(x, x-1)
      : ``
)

Ob dies zutrifft, hängt davon ab, wie genau die dritte Regel verstanden wird.


Es ist technisch gesehen kein Quine, da es eine modifizierte Version seines eigenen Quellcodes anstelle einer identischen Kopie ausgibt. Offensichtlich werden quineartige Techniken verwendet. Ich denke, wir brauchen eine Klärung von @TheTurtle.
JohnE

5
@JohnE und Ypnypn Das ist etwas, wie ich es mir vorgestellt habe. Das funktioniert.
Die Schildkröte

6
Sie sind immer noch weit unter der Codelängenbeschränkung. Warum ändern Sie 999 nicht in etwas Größeres?
DankMemes

4

Ruby, 1,628 × 10 ^ 237 Programme

a=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;_="a=%#x-1;_=%p;puts _%%[a,_]if a";puts _%[a,_]if a

Gleicher Ansatz wie meine Perl-Antwort, aber da Ruby bereits mit großen Ints umgeht, ist es einfacher, sie als Hex zu speichern.


Ruby, 9,277 × 10 ^ 90 Programme

a=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;b=0xf;(b<1)&&(a-=1)&&b=eval('0x'+'f'*(74-("%x"%a).length));_="a=%#x;b=%#x;(b<1)&&(a-=1)&&b=eval('0x'+'f'*(74-('%%x'%%a).length));_=%p;puts _%%[a,b-1,_]if a";puts _%[a,b-1,_]if a

Dieser Versuch ist also eine etwas andere Variante des vorherigen quine-ähnlichen, aber wegen all der zusätzlichen Funktionen erhalte ich die Nummer nicht annähernd so hoch wie die andere ... War interessant, einen anderen Ansatz zu versuchen!


4

Python 2, 9.7 * 10 ^ 229-Programme

O=0
if len(hex(O))<191:print"O=0x%x"%(O+1)+open(__file__).read()[-68:]

Schön, dachte nicht an Saitenwiederholung!
Dom Hastings

2

C, 2,2 · 10 & supmin; ¹ & sup7; Programme

#define S(s)char*q=#s,n[]="#####################################################################################################";i;s
S(main(){while(n[i]==91)n[i++]=35;i==101?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})

Es ist nicht perfekt, aber ziemlich gut. Ich meine, es ist genau 255bytes lang und erzeugt Programme mit der gleichen Länge. Sie könnten wahrscheinlich noch ein bisschen herumtüfteln, um noch mehr Programme zu bekommen, aber ich werde es so lassen, wie es jetzt ist.

Das Programm basiert auf einer einfachen C-Quine. Zusätzlich gibt es einen einfachen Zählalgorithmus, der alle möglichen Werte des char-Arrays zählt n. Wir haben so viele Programme wie Permutationen des Strings n.

Der Zeichenbereich ist auf einen Bereich von #(= 35) bis [= (91) begrenzt. Das liegt daran, dass ich keine will "oder \in der Schnur, weil sie geflüchtet werden müssen.

Die Programmerzeugung endet , wenn alle Werte in der char Array nsind [. Dann gibt es ein einfaches Dummy-Programm aus main(){}, das selbst nichts ausgibt.

#define  S(s) char *q = #s; /* have the source as a string */ \
char n[] = "#####################################################################################################"; \ 
int i; \
s /* the source itself */
S(main() {
    while(n[i]=='[') /* clear out highest value, so next array element be incremented */
        n[i++]='#'; 
    i==101 /* end of array reached? output dummy program */
        ? q = "main(){}"
        : n[i]++; /* count one up in the whole array */
    printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)", n, q);
})

Als Demonstration soll , dass es funktioniert ich die Grenzen nur geändert, so dass nur Zeichen zwischen ASCII-Code einfach 35und 36verwendet wurde und nur 4 Array - Elemente.

Die resultierenden Programme sind

% echo > delim; find -iname 'program_*.c' | xargs -n1 cat delim

#define S(s)char*q=#s,n[]="####";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$###";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="#$##";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$$##";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="##$#";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$#$#";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="#$$#";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$$$#";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="###$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$##$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="#$#$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$$#$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="##$$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$#$$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="#$$$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$$$$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="####";i;s
S(main(){})

Dies gibt 2^4 + 1 = 17verschiedene Programme aus.

Das obige Programm gibt also ((91-35)+1)^101 + 1 = 57^101 + 1 ~= 2.2 * 10^177verschiedene Programme aus. Ich bin mir nicht ganz sicher, ob dies zählt oder ob meine Berechnung überhaupt korrekt ist


1
Könnten Sie bitte hinzufügen, dass dies etwa ist 2.2 * 10^177(für diejenigen, die vergleichen möchten)?
Fehler

Ich wusste nicht, wie ich das berechnen sollte, aber ich habe es aufgenommen ;-)
MarcDefiant


1

Perl, 1 × 10 ^ 163

Ansonsten ist dies eine ziemlich einfache Quine, die auf so wenig Zeichen wie möglich geschrumpft ist und nur ausgeführt wird, während der Zähler nicht läuft 0.

use bigint;$i=9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999||die;$_=<<'e';eval
print"use bigint;\$i=$i-1||die;\$_=<<'e';eval
${_}e
"
e

1

Common Lisp, 10 113 -1

(LET ((X
       99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999))
  (WHEN #1=(PLUSP X)
    #2=(SETF *PRINT-CIRCLE* T)
    #3=(PRINT (LIST 'LET `((X ,(1- X))) (LIST 'WHEN '#1# '#2# '#3#)))))
  • Es gibt 113 Neunen.
  • Das nächste Programm hat 112 Neunen, gefolgt von einer 8
  • Das nächste Programm hat 112 Neunen, gefolgt von einer 7
  • ...

Die Anzahl der Neunen ist durch die maximale Codegröße von 256 begrenzt, wobei die vom Drucker eingegebenen Leerzeichen berücksichtigt werden .


1

Perl, 1,4 · 10 & supmin; ² & sup5 ;.

use bignum;open$F,__FILE__;$_=<$F>;s/0x\w+/($&-1)->as_hex/e;0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff&&print

Ähnliche Annäherung an Python; gleiches Ergebnis!


0

> <> , 65534 (?) Programme

Ich habe neben 65533 ein Fragezeichen eingefügt, da ich noch nicht überprüft habe, ob 65533 gedruckt werden kann (obwohl ich Grund zu der Annahme habe, dass dies der Fall sein sollte). Sobald ich etwas mehr Zeit habe, werde ich einen Weg finden, es zu testen.

":?!;1-r00gol?!;a0.�

Sie können es hier online ausprobieren .

Das Wesentliche dieses Programms ist, dass es die Ausgabe des Zeichens ganz am Ende ändert und dann vor dem Drucken seinen numerischen Wert dekrementiert. Ich habe 65534-Programme, weil der ASCII-Wert des Zeichens am Ende des Codes 65533 ist. Wenn wir also das erste Programm zählen, haben wir 65534 (wenn Sie das leere Programm 65535 zählen, denke ich). Das letzte "zurückgegebene" Programm ist nichts; es endet einfach, wenn der Zeichenwert 0 ist.

Ich bin mir ziemlich sicher, dass es in der Lage sein wird, ein Zeichen für alle Iterationen zu drucken: Ich konnte keine definitive Quelle für die Anzahl der Zeichen finden, die gedruckt werden können> <>, aber es gibt numerisch Zeichen direkt unter 65533.

Lassen Sie mich wissen, wenn bei dieser Implementierung Probleme auftreten. Ich bin mir ein wenig unsicher, ob mein Eintrag gültig ist.


Erläuterung

Ich habe schamlos die Idee gestohlen, ein einfaches Anführungszeichen zu verwenden, um ein Pseudo-Quine aus dem> <> Wiki zu erstellen, und einen Kommentar, den ich hier einmal gesehen habe.

":?!;1-r00gol?!;a0.�
"                     begins string parsing
 :?!;                 terminates program if final character is 0, numerically
     1-               decrements final character by 1
       r              reverses stack
        00g           grabs quotation mark (fancy way of putting " ")
           ol?!;      prints and terminates if stack is empty
                a0.   jumps back to o to loop 

Es analysiert alles nach dem Anführungszeichen als Zeichen und dekrementiert dann das letzte. Von dort dreht es den Stapel einfach um (um in der richtigen Reihenfolge zu drucken), schiebt ein Anführungszeichen auf den Stapel und druckt dann, bis der Stapel leer ist.


0

Python, 1 × 10 ^ 194 Programme

n=99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
if n:print open(__file__).read().replace(str(n),str(n-1))

Dies muss von einer Datei ausgeführt werden, nicht von einer interaktiven Antwort. Es ist keine Quine.

Vielen Dank an @The Turtle, der mir geholfen hat, 3 Bytes zu sparen. Das ist mehr Platz für neun!
Vielen Dank an @poke, der mir geholfen hat, 2 Bytes zu sparen. Das ist mehr Platz für neun!


@ Cheese Lover Das if n!=0ist überflüssig. Du kannst einfach schreiben if n.
Die Schildkröte

Sie können auch zwei Leerzeichen loswerden; nach dem if n:und zwischen den replaceArgumenten.
Poke

0

Bash, 52 Programme

Völlig uninspiriert und (hoffentlich) solide auf dem letzten Platz.

echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.