Bauen Sie ein Dreieck ohne Dreiecke

44

Als kleines Kind habe ich sehr gerne mit diesen Spielsachen gespielt:

Bildbeschreibung hier eingeben

Sie wollten wahrscheinlich, dass diese für die Kunst verwendet werden, aber ich habe sie immer für die Mathematik verwendet! Fraktale, Muster usw. Einmal wurde mir diese Herausforderung gestellt:

Bauen Sie ein Dreieck, ohne die grünen Dreiecksplättchen zu verwenden.

Diese Herausforderung hat mich am längsten überrascht, bis ich auf einen wirklich schönen und einfachen Weg gestoßen bin, es mit nur 3 Trapezoiden zu tun:

  /\  
 /_/\ 
/__\_\

Nehmen Sie nun dieses Dreieck und drehen Sie es:

______         
\ \__/         
 \/ /          
  \/ 

Mit diesen beiden Dreiecken können wir größere Dreiecke daraus konstruieren. Hier ist ein Dreieck der Höhe 2:

     /\           
    /_/\          
   /__\_\         
  /\ \__/\        
 /_/\/ /_/\       
/__\_\/__\_\    

Und hier sind Dreiecke der Höhe 3-7:

#3
        /\
       /_/\
      /__\_\
     /\ \__/\
    /_/\/ /_/\
   /__\_\/__\_\
  /\ \__/\ \__/\
 /_/\/ /_/\/ /_/\
/__\_\/__\_\/__\_\

#4
           /\
          /_/\
         /__\_\
        /\ \__/\
       /_/\/ /_/\
      /__\_\/__\_\
     /\ \__/\ \__/\
    /_/\/ /_/\/ /_/\
   /__\_\/__\_\/__\_\
  /\ \__/\ \__/\ \__/\
 /_/\/ /_/\/ /_/\/ /_/\
/__\_\/__\_\/__\_\/__\_\

#5
              /\
             /_/\
            /__\_\
           /\ \__/\
          /_/\/ /_/\
         /__\_\/__\_\
        /\ \__/\ \__/\
       /_/\/ /_/\/ /_/\
      /__\_\/__\_\/__\_\
     /\ \__/\ \__/\ \__/\
    /_/\/ /_/\/ /_/\/ /_/\
   /__\_\/__\_\/__\_\/__\_\
  /\ \__/\ \__/\ \__/\ \__/\
 /_/\/ /_/\/ /_/\/ /_/\/ /_/\
/__\_\/__\_\/__\_\/__\_\/__\_\

#6
                 /\
                /_/\
               /__\_\
              /\ \__/\
             /_/\/ /_/\
            /__\_\/__\_\
           /\ \__/\ \__/\
          /_/\/ /_/\/ /_/\
         /__\_\/__\_\/__\_\
        /\ \__/\ \__/\ \__/\
       /_/\/ /_/\/ /_/\/ /_/\
      /__\_\/__\_\/__\_\/__\_\
     /\ \__/\ \__/\ \__/\ \__/\
    /_/\/ /_/\/ /_/\/ /_/\/ /_/\
   /__\_\/__\_\/__\_\/__\_\/__\_\
  /\ \__/\ \__/\ \__/\ \__/\ \__/\
 /_/\/ /_/\/ /_/\/ /_/\/ /_/\/ /_/\
/__\_\/__\_\/__\_\/__\_\/__\_\/__\_\

#7
                    /\
                   /_/\
                  /__\_\
                 /\ \__/\
                /_/\/ /_/\
               /__\_\/__\_\
              /\ \__/\ \__/\
             /_/\/ /_/\/ /_/\
            /__\_\/__\_\/__\_\
           /\ \__/\ \__/\ \__/\
          /_/\/ /_/\/ /_/\/ /_/\
         /__\_\/__\_\/__\_\/__\_\
        /\ \__/\ \__/\ \__/\ \__/\
       /_/\/ /_/\/ /_/\/ /_/\/ /_/\
      /__\_\/__\_\/__\_\/__\_\/__\_\
     /\ \__/\ \__/\ \__/\ \__/\ \__/\
    /_/\/ /_/\/ /_/\/ /_/\/ /_/\/ /_/\
   /__\_\/__\_\/__\_\/__\_\/__\_\/__\_\
  /\ \__/\ \__/\ \__/\ \__/\ \__/\ \__/\
 /_/\/ /_/\/ /_/\/ /_/\/ /_/\/ /_/\/ /_/\
/__\_\/__\_\/__\_\/__\_\/__\_\/__\_\/__\_\

Die Herausforderung

Schreiben Sie ein Programm oder eine Funktion, die eine Zahl n annimmt und ein dreieckloses Dreieck der Höhe n ausgibt . Es ist zulässig, in jeder Zeile Leerzeichen nachzustellen, und es kann auch bis zu einer nachgestellten oder führenden neuen Zeile angegeben werden. IO kann in jedem vernünftigen Format vorliegen. Es ist garantiert, dass die Eingabe eine positive Ganzzahl ist, sodass Sie sich nicht um negative Zahlen, Dezimalzahlen, Nicht-Zahlen usw. kümmern müssen.

Kürzeste Antwort in Bytes gewinnt!

DJMcMayhem
quelle
Versuchen Sie, mehr Trapezoide aus den Trapezoiden zu machen. Längen 2 und 3 sind definitiv möglich (und im weiteren Sinne alle Zahlen der Form 2 ^ a * 3 ^ b) (Woher weiß ich das? Als Kind habe ich mit der gleichen Art von Blöcken gespielt.)
CalculatorFeline
1
@CatsAreFluffy Nun, da Sie Trapez aus Dreiecken machen können, können Sie daraus schließen, dass Sie Trapezoide aus Trapezoiden machen können. Wenn Sie sich die Dreiecke der Höhe 3 und 7 ansehen, sehen Sie dasselbe Muster, das sich mit großen Trapezoiden wiederholt.
DJMcMayhem
Diese Herausforderung ist wirklich cool. Ich fand es toll, herauszufinden, wie man das in Retina macht.
mbomb007
@ mbomb007 Freut mich zu hören, dass es Ihnen gefallen hat! = D Genau deshalb schreibe ich Herausforderungen.
DJMcMayhem
2
Diese Herausforderung passt perfekt auf den Bildschirm mit der mobilen App. War das beabsichtigt? :)
Doddy

Antworten:

15

CJam, 47

ri_"/__\_\/_/\/ /\ \__"6/f**eeW%{_S.*s\~,\-<N}/

Erläuterung:

ri_       read the input, convert to integer and duplicate
"…"       push that string, containing the repeating pattern
           (3 lines in reverse order, concatenated)
6/        split into (3) lines of 6 characters
f*        multiply (repeat) each line n times
*         repeat the array of 3 lines n times
           at this point we have an array of 3*n strings with 6*n characters each
ee        enumerate the array (obtaining an array of [index string] pairs)
W%        reverse the array
           (so the lines are in correct order and indices in reverse order)
{…}/      for each [index string] pair
  _       duplicate the pair
  S.*     vectorized-multiply with " "
           this effectively replaces the index with a string of <index> spaces
  s       convert the pair to string, effectively concatenating the spaces
           with the string
  \       swap with the other copy of the [index string] pair
  ~,      dump the index and string on the stack and get the string length
  \-      subtract the index from it - this is the desired line length
  <       cut the concatenated string to that length
  N       add a newline

Probieren Sie es online aus

aditsu
quelle
17

Rubin, 79

->n{1.upto(n*=3){|i|puts (' '*(n-i)).ljust(n+i,'/__\_\/\ \__/_/\/ '[i%3*6,6])}}

A. (-4 Byte, -1 +1) geändert von 0-indiziert ( .times) zu 1-indiziert ( 1.upto)

B. (-5 Bytes) geändert von einem Array aus drei Zeichenfolgen mit 6 Zeichen zur Auswahl einer 6-Zeichen-Teilzeichenfolge aus einer Zeichenfolge mit 18 Zeichen.

C. (-1 Byte) m=n*3->n*=3

D. (-5 Bytes) reduzierte alle fünf doppelten Backslashes zu einfachen Backslashes (teilweise möglich durch Neuordnung des für Punkt A erforderlichen Strings)

Ruby, 94

->n{(m=n*3).times{|i|puts (' '*(m-i-1)).ljust(m+i+1,[ '/\\ \\__','/_/\\/ ','/__\\_\\'][i%3])}}

Erläuterung

Die Grundeinheit ist eine 3x6-Raute wie folgt (letztes Zeichen in jeder Zeile aus Gründen der Klarheit dupliziert :)

    /\ \__/
   /_/\/ / 
  /__\_\/

Alles, was wir tun müssen, ist ein geeignetes Fenster dieses Musters anzuzeigen. Mit Ruby's ljustkönnen Sie mit einer beliebigen Zeichenfolge auffüllen, nicht nur mit Leerzeichen. Normalerweise ljustwird eine Zeichenfolge mit druckbaren Zeichen aufgefüllt, indem am Ende Leerzeichen hinzugefügt werden. In diesem Fall wird die Zeichenfolge umgekehrt aufgefüllt, indem am Ende druckbare Zeichen hinzugefügt werden.

im Testprogramm ungolfed

f=->n{
  (m=n*3).times{|i|                  #for each line of the triangle
    puts (' '*(m-i-1)).              #print m-i-1 spaces, 
      ljust(m+i+1,[ '/\\ \\__',      #left justified and padded to total length m+i+1
                   '/_/\\/ ',        #by one of these three strings
                  '/__\\_\\'][i%3])
  }
}

f[gets.to_i]
Level River St
quelle
@ mbomb007 Es ist das erste Mal, dass ich diese Beschwerde hatte. Als Ingenieur bin ich es gewohnt, Änderungen an allem vorzunehmen. Dies ist eine relativ einfache Herausforderung und die Verbesserungen sind ziemlich trivial. Deshalb habe ich die Änderungsbuchstaben gelöscht. Ich denke, es ist gut oder zumindest gut, den ursprünglichen Code beizubehalten schadet nicht, da es einfacher zu folgen ist als die aktuelle Version.
Level River St
3
Die Codegröße identifiziert normalerweise eine Revision eindeutig, der Revisionsverlauf ist jedoch auch für alle Personen verfügbar, die den Bearbeitungsverlauf anzeigen.
mbomb007
9

Netzhaut , 150 122 118 Bytes

Die Ausgabe für diese Herausforderung sieht übrigens fantastisch aus!

Die Eingabe ist unär. Die Ausgabe enthält einen nachfolgenden Zeilenvorschub. Der Code verwendet die ISO 8859-1-Codierung. Beachten Sie das Leerzeichen in der vorletzten Zeile.

(?=_\\¶.*1)
_\/__\
(?=/_/\\¶.*1)
/_/\/ 
(^|__)(?=/\\¶.*1)
$1/\ \__
ms}`(.*1*)1
/\¶/_/\¶/__\_\¶$1
m`^(?=(.*¶)*.)
$#1$* 

Probieren Sie es online aus

Erläuterung

Wenn Sie eine ausführlichere Erklärung wünschen, können Sie mich im Chat kommentieren oder eine Nachricht senden.

(?=_\\¶.*1)                     # Matches the start of the 3rd line of every triangle
/__\_\                          #   and prepends another layer if needed
(?=/_/\\¶.*1)                   # 2nd line of each triangle
/_/\/ 
(^|__)(?=/\\¶.*1)               # 1st line of each triangle
$1/\ \__
ms}`(.*1*)1                 # This and above in a multi-single-line loop.
/\¶/_/\¶/__\_\¶$1               #   This stage adds a flattened triangle on top
m`^(?=(.*¶)*.)                  # Prepend a space for every line following -1
$#1$* 

Vielen Dank an Martin für 32 Bytes Golf.

mbomb007
quelle
6

Tarmos ASCII-Drucksprache, 46 Byte. (nicht konkurrierend)

1  /\| /_/\|/__\_\2 \__|/ 0n{n-a-1{~}1a{2#1}$}

Wenn ich nur auf so seltsame Programmiersprachen wie CJam schaue, wird mir schwindlig, wie komplex, unnatürlich und kryptisch Sprache sein kann, dass ich "mutig dahin gehen wollte, wo noch kein Mensch war" und meine eigene Sprache erfinden wollte. Als Ergebnis habe ich meine eigene Sprache für das Drucken von ASCII-Mustern erstellt.

Die Grundidee ist, dass Sie zuerst das Muster definieren und dann drucken können - mit der gleichen Art von Zeichen '1' oder '2' oder einer beliebigen Zahl - Sie können Ihr eigenes Druckmuster definieren.

Sobald das Muster definiert ist (beginnt mit der Nummer bis zum Ende der Nummer), werden die nächsten Nummern zum Drucken des Musters verwendet.

Zum Beispiel

1  /\| /_/\|/__\_\01

Ausgaben wie diese:

  /\
 /_/\
/__\_\

Definiert Muster 1 und druckt es dann sofort aus. Muster ist definiert alles getrennt mit '|' Charakter. 0 am Ende - wirkt wie eine Musterbeendigung.

Sonderzeichen wie '$' sind als Zeilenvorschub reserviert, und '~' ist für den halben Abstand eines bestimmten Musters reserviert.

1  /\| /_/\|/__\_\01$~11$~1~11

Gibt folgenden Text aus:

  /\
 /_/\
/__\_\
     /\
    /_/\
   /__\_\
        /\
       /_/\
      /__\_\

Weiter geht's mit For-Loops. Diese muss gut sichtbar sein - also habe ich {} Klammern für for-Schleifen beibehalten, aber Variablennamen werden automatisch benannt - die erste Klammer verwendet 'a' Variable, die zweite 'b' und so weiter. Die Iteration erfolgt immer von 0 bis zu einer bestimmten Zahl - und diese Zahl wird vor {} Klammern definiert.

'n' ist eine reservierte Variable für die gesamte Funktionseingabe.

Also Code:

1  /\| /_/\|/__\_\0n{1$}

Will Ausgänge (mit n == 4):

  /\
 /_/\
/__\_\
  /\
 /_/\
/__\_\
  /\
 /_/\
/__\_\
  /\
 /_/\
/__\_\

Und '#' ist ein spezieller Modifikator für das Trimmen von Blei-Leerzeichen.

Und schließlich die ganze Lösung:

DrawPatterns.cs:

using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.CSharp;

class DrawPatterns
{
//Command line parameters - for example like this: "1  /\| /_/\|/__\_\2 \__|/ 0n{n-a-1{~}1a{2#1}$}" 3
    static Dictionary<char, String[]> patterns = new Dictionary<char,string[]>();

    static string Tabs(int n)
    {
        if( n < 0 ) n = 0;

        String r = "";

        for( int i = 0; i < n ; i++ )
            r += "    ";

        return r;
    }

    static int[] left = new int[10];
    static int top = Console.CursorTop;
    static int lastTop = Console.CursorTop;

    static public void DoPrint(char c, char modifier = ' ')
    {
        if (c == '$')
        {
            for (int i = 0; i < left.Length; i++)
                left[i] = 0;
            top = lastTop + 1;
            return;
        }

        if (!patterns.ContainsKey(c))
            return;

        if (modifier == '½' || modifier == '~')
        {
            int maxSize = patterns[c].Select(x => x.Length).Max();
            for( int i = 0; i < left.Length; i++ )
                left[i] += maxSize / 2;
            return;
        }

        int iLine = 0;
        foreach (var l in patterns[c])
        {
            Console.SetCursorPosition(left[iLine], top + iLine);
            if( top + iLine > lastTop ) 
                lastTop = top + iLine;

            String s = l;
            if (modifier == '#')
                s = s.TrimStart(' ');

            Console.WriteLine(s);
            left[iLine] += s.Length;
            iLine++;
        }
    }

    static void Main(string[] _args)
    {
        List<String> args = _args.ToList();
        String todo = "";
        String code = "";
        char nextVar = 'a';
        String lf = "\r\n";
        int align = 1;
        char lastModifier = ' ';
        int nextArg = 1;
        Dictionary<String, String> argValues = new Dictionary<string,string>();
        bool bDebug = false;

        if (args.Count != 0 && args[0].ToLower() == "-d")
        {
            bDebug = true;
            args.RemoveAt(0);
        }

        if (args.Count == 0)
        {
            Console.WriteLine("Usage: DrawPatterns.cs [options] \"script\" <arguments to script>");
            Console.WriteLine("[options] allowed:");
            Console.WriteLine("-d - debug");
            return;
        }

        String prog = args[0];

        for( int i = 0; i < prog.Length; i++ )
        {
            char c = prog[i];

            // Define pattern.
            if (c >= '0' && c <= '9' && !patterns.ContainsKey(c))
            {
                String p = Regex.Match(prog.Substring(i + 1), "[^0-9]*").Groups[0].Value;
                patterns[c] = p.Split('|');
                i += p.Length;
                if( prog[i + 1] == '0' ) i++;
                continue;
            }

            String procRemain = prog.Substring(i);
            // modifier specified, but pattern number is not provided - use first pattern.
            if( lastModifier != ' ' && ( c < '0' || c > '9' ) )
            {
                code += Tabs(align);
                code += "print('1' , '" + lastModifier + "');" + lf;
                lastModifier = ' ';
            }

            switch ( c )
            {
                case '{':
                    code += Tabs(align);
                    code += "for ( int " + nextVar + " = 0; " + nextVar + " < " + todo + " ; " + nextVar + "++ )" + lf;

                    //  Check for all variable names if they can be used in program.
                    foreach ( var m in Regex.Matches(todo, "[a-zA-Z_][a-zA-Z0-9_]*", RegexOptions.Singleline) )
                    {
                        String varName = m.ToString();

                        if( varName.Length == 1 && varName[0] <= nextVar )
                            // Already declared as a loop.
                            continue;

                        if( argValues.ContainsKey(varName ) )
                            continue;

                        if( nextArg >= args.Count )
                        {
                            Console.WriteLine("Insufficient parameters provided to script - argument '" + varName + "' value is needed");
                            return;
                        }

                        argValues[varName] = args[nextArg];
                        nextArg++;
                    }


                    code += Tabs(align);
                    code += "{" + lf;
                    nextVar++;
                    todo = "";
                    align++;
                    break;

                case '}':
                    align--;
                    code += Tabs(align);
                    code += "}" + lf;
                    break;

                default:
                    if (((c >= '0' && c <= '9') || c == '<' || c == '$') && todo == "")
                    {
                        code += Tabs(align);
                        code += "print('" + c + "' , '" + lastModifier + "');" + lf;
                        lastModifier = ' ';
                        continue;
                    }

                    if (c == '½' || c == '~' || c == '#')
                    {
                        lastModifier = c;
                        continue;
                    }

                    if( c == '\r' || c == '\n' )
                        continue;

                    todo += c;
                    break;
            }

        } //for

        String code2 = "";
        code2 += "using System;" + lf;
        code2 += "public class ExecClass { static void Exec( Action<char, char> print";

        object[] invokeArgs = new object[ argValues.Count+1];
        invokeArgs[0] = new Action<char, char>(DoPrint);
        int iValueIndex = 1;

        foreach ( var kv in argValues )
        {
            code2 += ",";
            code2 += "int " + kv.Key;
            invokeArgs[iValueIndex] = Int32.Parse(kv.Value);
            iValueIndex++;
        }

        code2 += ") {" + lf;
        code2 += code;
        code2 += "} };";

        if( bDebug )
        {
            int line = 1;
            String lineNumberedCode =Regex.Replace(code2, "^(.*)$", 
                delegate(Match m) { return (line++).ToString("d2") + ": " + m.Value; },
                RegexOptions.Multiline
            );
            Console.WriteLine(lineNumberedCode);
            Console.WriteLine();
            Console.WriteLine();
        }

        left[0] = Console.CursorLeft;
        for( int i = 1; i < left.Length; i++ )
            left[i] = left[0];
        top = Console.CursorTop;

        try
        {
            var compileResult = new CSharpCodeProvider().CompileAssemblyFromSource( new CompilerParameters() { GenerateExecutable = false, GenerateInMemory = true }, code2);
            if (compileResult.Errors.HasErrors)
            {
                foreach (CompilerError ce in compileResult.Errors)
                {
                    if (ce.IsWarning) continue;
                    Console.WriteLine("{0}({1},{2}: error {3}: {4}", ce.FileName, ce.Line, ce.Column, ce.ErrorNumber, ce.ErrorText);
                }
                return;
            }

            var method = compileResult.CompiledAssembly.GetType("ExecClass").GetMethod("Exec", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
            method.Invoke(null, invokeArgs);

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

        Console.SetCursorPosition(1, lastTop);
        Console.WriteLine();
        Console.WriteLine();
    } //Main
}

Mit folgenden Befehlszeilenargumenten: -d "1 / \ | / _ / \ | / ___ \ 2 __ | / 0n {na-1 {½} 1a {2 # 1} $}" 3

Will gibt Folgendes aus:

01: using System;
02: public class ExecClass { static void Exec( Action<char, char> print,int n) {
03:     for ( int a = 0; a < n ; a++ )
04:     {
05:         for ( int b = 0; b < n-a-1 ; b++ )
06:         {
07:             print('1' , '~');
08:         }
09:         print('1' , ' ');
10:         for ( int c = 0; c < a ; c++ )
11:         {
12:             print('2' , ' ');
13:             print('1' , '#');
14:         }
15:         print('$' , ' ');
16:     }
17: } };


        /\
       /_/\
      /__\_\
     /\ \__/\
    /_/\/ /_/\
   /__\_\/__\_\
  /\ \__/\ \__/\
 /_/\/ /_/\/ /_/\
/__\_\/__\_\/__\_\
TarmoPikaro
quelle
1
Das ist wirklich großartig! Sie sollten das auf Github setzen und die Leute ermutigen, es zu benutzen!
DJMcMayhem
3
Willkommen bei Programming Puzzles und Code Golf! Es ist sehr schön, dass Sie Ihre eigene Programmiersprache erfunden haben, aber ist die neueste Version, in der sie ausgeführt werden kann, der Herausforderung voraus?
Adnan
Hast du nicht richtig verstanden, was sagst du?
TarmoPikaro
Nun, wenn die Sprache selbst neuer als die Herausforderung ist, ist es üblich, sie als nicht konkurrierend zu kennzeichnen (ziemlich logisch;)). Dies könnte ein relevanter Beitrag sein.
Adnan
Die Sprache hängt von der Problemdomäne ab, und ich wusste nicht, dass ein solches Problem besteht, bevor ich es hier gelesen habe. Ich schätze, ich könnte die Sprache früher codieren, wenn ich bereits auf ein ähnliches Problem gestoßen bin. :) Wie auch immer, als ich diese Seite gelesen habe, habe ich verstanden, dass CJam hier eine ganz "normale" Sprache ist. :)
TarmoPikaro
5

JavaScript (ES6), 119 Byte

n=>`,/\\ \\__,/_/\\/ ,/__\\_\\`[r=`repeat`](n).split`,`.map((s,i)=>` `[r](n*3-i)+s[r](n).slice(0,i*2)).slice(1).join`\n`

Wobei \ndas wörtliche Zeilenumbruchzeichen darstellt. Wenn eine führende Zeile mit n*3Leerzeichen und eine neue Zeile zulässig ist, .slice(1)kann diese entfernt werden, um 9 Byte zu sparen.

Neil
quelle
2

Python 2, 142 Bytes

def f(n,m):return f(n-1,m+3)+[' '*(m+x)+(y*n)[x*2:]for x,y in((2,' \\__/\\'),(1,'/ /_/\\'),(0,'/__\\_\\'))]if n else[]
print '\n'.join(f(n,0))

Das Prinzip ist anderen Antworten sehr ähnlich: Nehmen Sie drei sich wiederholende Zeichenfolgen und legen Sie sie so übereinander, dass Sie nur einige davon abschneiden müssen, um das Dreieck zu erhalten. Füllen Sie sie dann links auf.

wvxvw
quelle
2

C ++, 395 Bytes

Zum ersten Mal Code Golf mit einer Größe von 395 Bytes in C ++. In meinem Fall fühlt es sich ein bisschen wie ein Wettbewerb um die Verschleierung an: D

#include <iostream>
#include <cstring>
#define A for (int k=0;k<((s-(i+1))*3+(2-j));k++) cout<<" ";
using namespace std; string t[3]={"/\\","/_/\\","/__\\_\\"};string r[2]={" \\__","/ "};int tr=3;int main(int,char**argv){int s=atoi(argv[1]);for(int i=0;i<s;i++){for(int j=0;j<tr;j++){A for(int l=1;l<=2*(i+1)-1;l++){if((l%2)==0&&(j<2)){cout<<r[j];}else if ((l%2)==1)cout<<t[j];}A cout<<endl;}}}
John HK
quelle