Disegna esagoni concentrici ASCII


15

Scrivi il programma più breve possibile che comprende un insieme di interi positivi distinti e genera un rendering ASCII di esagoni concentrici con quelle lunghezze laterali, costituite da barre, sottolineature, spazi e newline.

Vince il programma più breve in byte contato da https://mothereff.in/byte-counter .

Esempi

(Hanno un aspetto migliore con meno spazio tra le linee.)

Se l'ingresso è 1l'output dovrebbe essere l'esagono con lunghezza laterale 1:

 __ 
/  \
\__/

Si noti che vengono utilizzati due trattini bassi per la parte superiore e inferiore dell'esagono, in modo che sia meglio proporzionato.

In generale, la dimensione N esagono contiene N barre su ciascun lato angolato e 2 * N trattini bassi su entrambi i lati superiore e inferiore.

Se l'input è 1 2l'output dovrebbero essere gli esagoni concentrici con lunghezza laterale 1 e 2:

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

Se l'ingresso è 1 3l'output dovrebbe essere:

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

Se l'ingresso è 1 3 2l'output dovrebbe essere:

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

eccetera.

Regole I / O

L'input deve provenire dalla riga di comando o dallo stdin ma può essere in qualunque formato sia più conveniente.

Ad esempio, si potrebbe dare ad ogni numero come argomento della riga di comando: > myprogram 1 3 2, o si potrebbe chiedere all'utente di inserire i numeri come un elenco preformattato: [1, 3, 2].

L'output deve andare su stdout o l'equivalente più vicino alla tua lingua.

Regole aggiuntive

  • L'input sarà sempre un insieme di interi positivi distinti, non necessariamente in alcun ordine .
  • L'output deve ...
    • non contiene alcun carattere oltre /\ _e newline.
    • non hanno spazi finali o spazi iniziali non necessari.
    • non contiene nuove righe iniziali estranee ma potrebbe avere una riga finale finale opzionale .
  • Se non viene immesso nulla, non viene emesso nulla (tranne forse una nuova riga).
  • Se ti aiuta, puoi supporre che gli interi di input siano inferiori a 2 16 .

Fa 1riferimento all'esagono più interno o più esterno?
NinjaBearMonkey

@hsl Il 1(o qualsiasi numero) si riferisce all'esagono con lunghezza laterale di 1. (Con l'avvertenza che 1 barra = 2 trattini bassi.) Quindi 1farà sempre riferimento all'esagono più interno.
Calvin's Hobbies,

Risposte:


4

CJam, 148 116 109 byte

Ciò ha richiesto molto più tempo di quanto mi aspettassi. Inizialmente, volevo solo costruire in modo iterativo il quadrante in alto a sinistra, come nelle sfide con i diamanti, e poi ottenere il resto dal mirroring. Ma non ho notato che i caratteri di sottolineatura non obbediscono alla simmetria speculare tra la metà superiore e inferiore. Quindi ho dovuto rifare la maggior parte di questo, per generare la metà destra in modo iterativo e quindi eseguire il mirroring solo una volta (a sinistra).

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}/

Provalo qui.

Un esempio di Fibonacci:

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

Spiegazione:

Come detto in alto, inizio costruendo la metà giusta in modo iterativo. Cioè, inizialmente ho solo un singolo spazio nella griglia, e poi per ogni possibile anello, circondo la griglia esistente in spazi o un nuovo semi-esagono.

Una volta fatto, rispondo ogni linea a sinistra e la riempio con spazi iniziali per un corretto allineamento. Ecco una ripartizione del codice:

"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()

Approccio alternativo (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)

(e 133 caratteri)

Dal momento che questa domanda richiede specificamente la quantità di byte nella rappresentazione UTF8, ho dovuto effettivamente sbloccarlo un po 'in modo che sia più lungo ma la sua rappresentazione UTF8 è più corta. (In particolare, il carattere dell'operatore pendolare è di tre byte mentre ()solo due, quindi l'ottimizzazione non funziona più e rende l'assegnazione molto costosa.)

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

Versione precedente, che è più corta in caratteri (124) ma utilizza più byte se rappresentata in UTF-8 (230, che la metterebbe al secondo posto):

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

Test:

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

Ciò non sembra soddisfare le specifiche per i lati superiore e inferiore (dovrebbero essere caratteri di sottolineatura, non trattini) e di conseguenza devono essere sfalsati di una linea per i lati inferiori.
Martin Ender,

1

Perl 5, 352 (349 byte + 3 per anEflag)

Questo potrebbe probabilmente essere risolto molto di più ..

@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 
}

Esempio ( 1 5 3 14):

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

1

C # - 388 316 byte

Modifica: modificato il modo in cui evita di stampare spazi finali e ha lanciato LINQ

Programma semplice che accetta argomenti da riga di comando. Esamina ogni possibile carattere in ogni riga di un rettangolo definito dalla dimensione massima esagonale e lo aggiunge alla riga corrente, prima di tagliare le linee e stamparle successivamente (produce la nuova riga finale opzionale).

Codice Golfed:

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);}}}

Codice non golfato:

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
        }
    }
}

0

APL (Dyalog Classic) , 151 byte (93 con la classica codifica APL)

{a0⍴⍨1 0+1 2×n←⌈/⍵⋄a[⊃,/i,¨¨⍵+⍵-1+i←⍳¨⍵]←1⋄a←(⊖⍪-)a⋄a[⊃,/(n+⍵,-⍵),¨¨,⍨i]←2⋄' /_\'[4|(⌽,-)a]}

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.