Zeichnen Sie konzentrische ASCII-Sechsecke


15

Schreiben Sie das kürzestmögliche Programm, das eine Reihe eindeutiger positiver Ganzzahlen aufnimmt und eine ASCII-Darstellung konzentrischer Sechsecke mit diesen Seitenlängen aus Schrägstrichen, Unterstrichen, Leerzeichen und Zeilenumbrüchen ausgibt.

Das kürzeste Programm in Bytes, das von https://mothereff.in/byte-counter gezählt wird, gewinnt.

Beispiele

(Sie sehen mit weniger Zeilenabstand besser aus.)

Wenn die Eingabe 1die Ausgabe ist, sollte das Sechseck mit der Seitenlänge 1 sein:

 __ 
/  \
\__/

Beachten Sie, dass am oberen und unteren Rand des Sechsecks zwei Unterstriche verwendet werden, um die Proportionen zu verbessern.

Im Allgemeinen enthält das Sechskant der Größe N N Schrägstriche an jeder abgewinkelten Seite und 2 * N Unterstriche an der Ober- und Unterseite.

Wenn die Eingabe 1 2die Ausgabe ist, sollten die konzentrischen Sechsecke mit den Seitenlängen 1 und 2 sein:

  ____
 / __ \
/ /  \ \
\ \__/ /
 \____/

Wenn der Eingang 1 3der Ausgang ist, sollte sein:

   ______
  /      \
 /   __   \
/   /  \   \
\   \__/   /
 \        /
  \______/

Wenn der Eingang 1 3 2der Ausgang ist, sollte sein:

   ______
  / ____ \
 / / __ \ \
/ / /  \ \ \
\ \ \__/ / /
 \ \____/ /
  \______/

etc.

E / A-Regeln

Die Eingabe muss entweder über die Befehlszeile oder über stdin erfolgen, kann jedoch in einem beliebigen Format erfolgen, das für Sie am bequemsten ist.

Zum Beispiel könnten Sie jede Nummer als Befehlszeilenargument geben: > myprogram 1 3 2, oder Sie können den Benutzer zur Eingabe der Zahlen als vorformatierte Liste aufgefordert: [1, 3, 2].

Die Ausgabe muss auf stdout oder das nächsthöhere Sprachäquivalent erfolgen.

Zusätzliche Regeln

  • Die Eingabe besteht immer aus einer Reihe eindeutiger positiver Ganzzahlen, nicht unbedingt in beliebiger Reihenfolge .
  • Die Ausgabe muss ...
    • keine Zeichen außer /\ _und Zeilenumbrüche enthalten.
    • haben keine nachgestellten oder unnötigen führenden Leerzeichen.
    • Enthält keine überflüssigen führenden Zeilenumbrüche, kann aber einen optionalen nachgestellten Zeilenumbruch enthalten.
  • Wenn nichts eingegeben wird, wird nichts ausgegeben (außer möglicherweise einer neuen Zeile).
  • Wenn dies hilft, können Sie davon ausgehen, dass die Eingabe-Ganzzahlen kleiner als 2 16 sind .

Bezieht sich das 1auf das innerste oder äußerste Sechseck?
NinjaBearMonkey

@hsl Die 1(oder eine beliebige Zahl) bezieht sich auf das Sechseck mit einer Seitenlänge von 1. (Mit der Einschränkung, dass 1 Schrägstrich = 2 Unterstriche ist.) Bezieht 1sich also immer auf das innerste Sechseck.
Calvins Hobbys

Antworten:


4

CJam, 148 116 109 Bytes

Das hat viel länger gedauert als ich erwartet hatte. Ursprünglich wollte ich nur den oberen linken Quadranten iterativ erstellen, wie bei den Diamantherausforderungen, und dann den Rest durch Spiegeln erhalten. Aber ich habe nicht bemerkt, dass die Unterstriche nicht der Spiegelsymmetrie zwischen der oberen und unteren Hälfte entsprechen. Also musste ich das meiste wiederholen, um die rechte Hälfte iterativ zu erzeugen und dann nur einmal (nach links) zu spiegeln.

S]2[l~]:(f#:+2bW%{_,2/~:T;{IT):T1<'\'/?S?S++}%__,2/=,2/I'_S?*_S+a@+\I'/S?S++a+}fI{)T)2*2$,-*1$W%"\/"_W%er@N}/

Teste es hier.

Ein Fibonacci-ähnliches Beispiel:

8 3 1 5 2
        ________________
       /                \
      /                  \
     /     __________     \
    /     /          \     \
   /     /   ______   \     \
  /     /   / ____ \   \     \
 /     /   / / __ \ \   \     \
/     /   / / /  \ \ \   \     \
\     \   \ \ \__/ / /   /     /
 \     \   \ \____/ /   /     /
  \     \   \______/   /     /
   \     \            /     /
    \     \__________/     /
     \                    /
      \                  /
       \________________/

Erläuterung:

Wie oben angegeben, beginne ich mit der iterativen Erstellung der rechten Hälfte. Das heißt, anfangs habe ich nur ein einzelnes Feld im Raster, und dann umgebe ich für jeden möglichen Ring das vorhandene Feld entweder in Feldern oder in einem neuen Halbsechseck.

Sobald dies erledigt ist, spiegele ich jede Zeile nach links und fülle sie mit führenden Leerzeichen auf, um eine korrekte Ausrichtung zu gewährleisten. Hier ist eine Aufschlüsselung des Codes:

"Prepare the input and the grid:";
S]2[l~]:(f#:+2bW%
S]                "Push string with a space and wrap it in an array. This is the grid.";
  2               "Push a 2 for future use.";
   [l~]           "Read and evaluate the input, wrap it in an array.";
       :(         "Decrement each number by 1.";
         f#       "Map each number i to 2^i.";
           :+     "Sum them all up.";
             2b   "Get the base two representation.";
               W% "Reverse the array.":
"At this point, the stack has the proto-grid at the bottom, and an array of 1s and
 0s on top, which indicates for each hexagon if it's present or not.";

"Next is a for loop, which runs the block for each of those 0s and 1s, storing the
 actual value in I. This block adds the next semi-hexagon or spaces.";
{ ... }fI

"First, append two characters to all existing lines:";
_,2/~:T;{IT):T1<'\'/?S?S++}%
_                            "Duplicate the previous grid.";
 ,2/                         "Get its length, integer-divide by 2.";
    ~:T;                     "Get the bitwise complement and store it in T. Discard it.";
        {                 }% "Map this block onto each line of the grid.";
         I                   "Push the current hexagon flag for future use.";
          T):T               "Push T, increment, store the new value.";
              1<'\'/?        "If T is less than 1, push \, else push /.";
                     S?      "If the current flag is 0, replace by a space.";
                       S++   "Append a space and add it to the current line.";

"So for hexagons this appends '\ ' to the top half and '/ ' to the bottom half.
 For empty rings, it appends '  ' to all lines.";

"Now add a new line to the top and the bottom:"    
__,2/=,2/I'_S?*_S+a@+\I'/S?S++a+
__                               "Get two copies of the grid.";
  ,2/                            "Get its length, integer-divide by 2.";
     =                           "Get that line - this is always the middle line.";
      ,2/                        "Get ITS length, integer'divide by 2.";
         I'_S?*                  "Get a string of that many _ or spaces depending on the 
                                  current flag.";
               _S+               "Duplicate and a space.";
                  a@+            "Wrap in an array, pull up the grid, and prepend the line.";
                     \           "Swap with the other copy.";
                      I'/S?      "Choose between / and a space depending on the flag.";
                           S++   "Append a space, and add both characters to the line.";
                              a+ "Wrap in an array, and append line to the grid.";

"This is all. Rinse and repeat for all rings. The result will look something like this:

_____ 
     \ 
___   \ 
__ \   \ 
_ \ \   \ 
 \ \ \   \ 
_/ / /   / 
__/ /   / 
___/   / 
      / 
_____/ 

Note that there are still trailing spaces.";

"Finish up all lines. These will not be joined together any more, but simply left
 on the stack in pieces to printed out back-to-back at the end of the program.
 The following runs the given block for each line:";
{ ... } /

"This generates the necessary indentation, then mirrors the lines and puts them
 in the right order:"
)T)2*2$,-*\_W%"\/"_W%er\N
)                         "Slice off that trailing space, but leave it on the stack.";
 T                        "Remember T? That still has something like the the size of
                           the grid from the last iteration. In fact it's N-1, where
                           N is the largest visible hexagon. We can use that to figure
                           out how many spaces we need.";
  )2*                     "Increment and double.";
     2$                   "Copy the current line.";
       ,-                 "Subtract its length from 2*N.";
         *                "Repeat the space that often. This is our indentation.";
          \_              "Swap with the line and duplicate.";
            W%            "Reverse the line.";
              "\/"_W%er   "Replace slashes with backslashes and vice versa.";
                       \  "Swap with the original line.";
                        N "Push a line break.";

5

Python - 251, 240, 239, 228

l=input()+[0];m=max(l);A=abs;R=range
for j in R(2*m+1):print''.join([[' \\'[(A(j-i+m-1)/2.in l)*(2*m-i)/(j-m-.5)>1],'/'][(A(3*m-i-j)/2.in l)*(i-m-j+.5)/(j-.5-m)>0],'_'][(A(m-j)in l)*(A(2*m-i-.5)<A(m-j))]for i in R(4*m)).rstrip()

Alternativer Ansatz (251):

l=input()+[0]
l.sort()
m=max(l)
M=2*m
s=[[' ']*m*4for j in' '*(M+1)]
for i in l:
 I=2*i;s[m-i][M-i:M+i]=s[m+i][M-i:M+i]='_'*I
 for k in range(i):K=k+1;s[m-k][M-I+k]=s[m+K][M+I-K]='/';s[m-k][M+I-K]=s[m+K][M-I+k]='\\'
for t in s:print''.join(t).rstrip()

3

APL (222 Byte in UTF-8)

(und 133 Zeichen)

Da bei dieser Frage speziell die Anzahl der Bytes in der UTF8-Darstellung abgefragt wird , musste ich sie tatsächlich ein wenig entgolfen , damit sie länger ist, aber die UTF8-Darstellung kürzer. (Insbesondere ist das Zeichen des Pendleroperators drei Bytes, während ()es nur zwei Bytes sind, so dass die Optimierung nicht mehr funktioniert und die Zuweisung auch sehr teuer wird.)

{⎕←(~⌽∧\⌽⍵=' ')/⍵}¨↓⊃{⍵{⍺=' ':⍵⋄⍺}¨K↑(-.5×(K←⍴⍵)+⍴⍺)↑⍺}/{Z⍪⌽⊖Z←↑(⊂(⍵/' '),(2×⍵)/'-'),⍵{((-⍵)↑'/'),((2 4-.×⍵⍺)/' '),'\'}¨⌽⍳⍵}¨N[⍋N←,⎕]

Vorherige Version, die kürzer in Zeichen ist (124), aber mehr Bytes verwendet, wenn sie in UTF-8 dargestellt wird (230, was den zweiten Platz bedeuten würde):

M←' '⋄{⎕←⍵/⍨~⌽∧\⌽⍵=M}¨↓⊃{⍵{⍺=M:⍵⋄⍺}¨K↑⍺↑⍨-.5×(K←⍴⍵)+⍴⍺}/{Z⍪⊖⌽Z←↑(⊂(⍵/M),'-'/⍨2×⍵),⍵{('/'↑⍨-⍵),'\',⍨M/⍨2 4-.×⍵⍺}¨⌽⍳⍵}¨N[⍋N←,⎕]

Prüfung:

      {⎕←(~⌽∧\⌽⍵=' ')/⍵}¨↓⊃{⍵{⍺=' ':⍵⋄⍺}¨K↑(-.5×(K←⍴⍵)+⍴⍺)↑⍺}/{Z⍪⌽⊖Z←↑(⊂(⍵/' '),(2×⍵)/'-'),⍵{((-⍵)↑'/'),((2 4-.×⍵⍺)/' '),'\'}¨⌽⍳⍵}¨N[⍋N←,⎕]
⎕:
      3 1 5 2
     ----------
    /          \
   /   ------   \
  /   / ---- \   \
 /   / / -- \ \   \
/   / / /  \ \ \   \
\   \ \ \  / / /   /
 \   \ \ -- / /   /
  \   \ ---- /   /
   \   ------   /
    \          /
     ----------

Dies scheint nicht den Spezifikationen für die Ober- und Unterseite zu entsprechen (sie sollten Unterstriche und keine Bindestriche sein) und folglich um eine Zeile für die Unterseite versetzt sein.
Martin Ender

1

Perl 5, 352 (349 Bytes + 3 für anEFlags)

Dies könnte wahrscheinlich viel mehr golfen werden ..

@b=sort{$a>$b}@F;map{$_<$j||($j=$_)}@b;$k=++$j;for(;$j--;){$z=$"x$j;for($e=$k;--$e>$j;){$z.=$e~~@b?'/ ':'  '} $z.=($j~~@b?'_':$")x(2*$j);$z.=$_~~@b?' \\':'  'for($j+1..$k-1);say$z}for(0..$k-2){$z=$"x$_;for($e=$k;--$e>$_;){$z.=($e-$k+1?$":'').($e~~@b?'\\':$")}$z.=(($_+1)~~@b?'_':$")x(2*$_+2);$z.=($_~~@b?'/':$").($_-$k+1?$":'')for($_+1..$k-1);say$z}

Ungolfed:

# sort list of side lengths 
@b=sort{$a>$b}@F; 
# set $k and $j to max side length + 1
map{$_<$j||($j=$_)}@b;$k=++$j;
for(;$j--;){
  $z=$"x$j;
  for($e=$k;--$e>$j;){$z.=$e~~@b?'/ ':'  '}
  $z.=($j~~@b?'_':$")x(2*$j);
  $z.=$_~~@b?' \\':'  'for($j+1..$k-1);
  say$z
}
for(0..$k-2){
  $z=$"x$_;
  for($e=$k;--$e>$_;){$z.=($e-$k+1?$":'').($e~~@b?'\\':$")}
  $z.=(($_+1)~~@b?'_':$")x(2*$_+2);
  $z.=($_~~@b?'/':$").($_-$k+1?$":'')for($_+1..$k-1);
  say$z 
}

Beispiel ( 1 5 3 14):

              ____________________________
             /                            \
            /                              \
           /                                \
          /                                  \
         /                                    \
        /                                      \
       /                                        \
      /                                          \
     /                 __________                 \
    /                 /          \                 \
   /                 /   ______   \                 \
  /                 /   /      \   \                 \
 /                 /   /   __   \   \                 \
/                 /   /   /  \   \   \                 \
\                 \   \   \__/   /   /                 /
 \                 \   \        /   /                 /
  \                 \   \______/   /                 /
   \                 \            /                 /
    \                 \__________/                 /
     \                                            /
      \                                          /
       \                                        /
        \                                      /
         \                                    /
          \                                  /
           \                                /
            \                              /
             \____________________________/

1

C # - 388 316 Bytes

Bearbeiten: Es wurde geändert, wie das Drucken nachgestellter Leerzeichen vermieden wird, und einige LINQ-Befehle eingefügt

Einfaches Programm, das Befehlszeilenargumente akzeptiert. Es durchläuft jedes mögliche Zeichen in jeder Zeile eines Rechtecks, das durch die maximale Sechseckdimension definiert ist, und hängt es an die aktuelle Zeile an, bevor die Zeilen abgeschnitten und nacheinander gedruckt werden (es erzeugt die optionale nachgestellte neue Zeile).

Golf Code:

using System.Linq;class P{static void Main(string[]A){var I=A.Select(int.Parse);int m=I.Max(),i,j,y,x;for(j=m+1;j-->-m;){var r="";for(i=-2*m-1;++i<2*m-(y=j<0?-j-1:j);)r+="/\\_- "[(x=i<0?-i-1:i)>y&(x+=y)%2>0&x/2<m&&I.Contains(x/2+1)?(i^j)&1:x-y<(y=j<0?-j:j)&y<=m&I.Contains(y)?j<0?2:3:4];System.Console.WriteLine(r);}}}

Ungolfed-Code:

using System.Linq; // all important

class P
{
    static void Main(string[]A)
    {
        var I=A.Select(int.Parse); // create int array

        for(int m=I.Max(),j=m+1,i,y,x;j-->-m;) // for each line...
        {
            var r=""; // current line

            for(i=-2*m-1;++i<2*m-(y=j<0?-j-1:j);) // for each char...
                r+="/\\_- "[// append something to the current line
                (x=i<0?-i-1:i)>y&(x+=y)%2>0&x/2<m&&I.Contains(x/2+1)?
                    (i^j)&1: // slashes as appropriate - I can't work out why this bit works, but it seems to
                x-y<(y=j<0?-j:j)&y<=m&I.Contains(y)?
                    j<0?2:3: // _ or - if required
                4]; // otherwise a space

            System.Console.WriteLine(r); // print current line
        }
    }
}

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.