Build Me a Pyramid


16

Devi costruire una piramide dai cubi. I cubi possono essere visualizzati da 2 angolazioni:

  _____        _____
 /\    \      /    /\
/  \____\    /____/  \
\  /    /    \    \  /
 \/____/      \____\/

Questo è un esempio per i cubi di 2 dimensioni dai 2 angoli possibili. L'altezza dei cubi è $sizebarra (o barra) e la larghezza del cubo è 2 * $sizesottolineata. La larghezza del livello superiore deve contenere un carattere di sottolineatura aggiuntivo.

L'input verrà fornito come una stringa contenente un numero (dimensione dei cubi), barra o barra rovesciata (per indicare la direzione / angolo) e un altro numero (altezza della piramide).

Esempi:

Ingresso:

1/1

Produzione:

 ___
/\__\
\/__/

Ingresso:

1\1

Produzione:

 ___
/__/\
\__\/

Ingresso:

2/1

Produzione:

  _____
 /\    \
/  \____\
\  /    /
 \/____/

Ingresso:

1/2

Produzione:

     ___ 
 ___/\__\
/\__\/__/
\/__/\__\
    \/__/

Ingresso:

2\2

Produzione:

  _____          
 /    /\         
/____/  \_____   
\    \  /    /\ 
 \____\/____/  \ 
 /    /\    \  /
/____/  \____\/ 
\    \  /        
 \____\/        

Ingresso:

1/3

Produzione:

         ___  
     ___/\__\
 ___/\__\/__/
/\__\/__/\__\
\/__/\__\/__/
    \/__/\__\
        \/__/
  • Gli spazi bianchi finali / iniziali sono OK.
  • Le scappatoie standard non sono ammesse.
  • Puoi presumere che l'input sia sempre valido.
  • Si può supporre che l'ingresso non causi un output troppo grande, ovvero: nessun avvolgimento di riga quando l'output viene stampato sul terminale.
  • Le dimensioni del cubo e l'altezza della piramide sono positive (cioè ≥ 1)
  • Questo è code-golf, quindi vince il codice più breve in byte.

Il vincitore attuale è:

Glen O con 270 byte in julia

la sfida rimane aperta. se batti l'attuale migliore, aggiornerò la risposta accettata.


2
I tuoi cubi sono diversi da quelli delle recenti sfide del motivo a rombi, in quanto la riga superiore ha 2 sottolineature 2 + 1, mentre le altre sfide avevano 2 sottolineature sulla riga superiore e 2s-1 sulle altre righe. Ciò significa che il passo orizzontale è 3s + 1. Immagino sia bello mescolare le cose. Sto solo facendo l'osservazione nel caso qualcuno lo manchi.
Level River St

1
quali sono i valori massimi di dimensione e altezza? possiamo supporre che siano una cifra?
Level River St

no, non si può presumere che sia una cifra, ma si può presumere che l'input fornito non causi che l'output sia "troppo grande", cioè non causerà il ritorno a capo nel proprio terminale.
Gilad Hoch,

Risposte:


3

Julia - 503 455 369 346 313 270 byte

f=A->(t=47A;h='/'+45t;(m,n)=int(split(A,h));W=2m*n+1;X=(l=3m+1)n+m+1;s=fill(' ',X,W);s[end,:]=10;for i=1:n,j=i:n,M=1:m s[M+i*l+[[L=[J=(2j-i)m,J,J-m]+M W-L]X.-[l,m,0] [0 m].+[1,m,m].+[J,J+m,J-m]X-l]]=[1,1,1]*[h 139-h 95 s[i*l,i*m-m+1]=95]end;print((t?s:flipud(s))...))

Ungolfed:

function f(A)
  t=47A      # Determine if '/' is in A ('/' = char(47))
  h='/'+45t   # Set h to the appropriate slash ('\\' = char(92), 92=47+45)
  (m,n)=int(split(A,h)) # Get the two integers from A
  W=2m*n+1    # Get number of rows of output (vertical height of pyramid)
  X=(l=3m+1)n+m+1 # Get columns of output + 1 (for newlines)
  s=fill(' ',X,W) # Create 'canvas' of size X x W
  s[end,:]=10 # Put newlines at end of each output row
  for i=1:n, j=i:n, M=1:m
    # This is where the fun happens.
    # K and L represent the shifting points for '/' and '\\' in the
    # horizontal and vertical directions.
    # They are used to make the code neater (and shorter).
    K=M+i*l-[l,m,0]
    L=[J,J,J-m]+M
    # The next two assign the slashes to appropriate places
    s[K+L*X]=h
    s[K+(W-L)X]=139-h
    # This one puts the first 2m underscores in each of the underscore sets
    s[M+i*l-l+[0 m].+[1,m,m].+[J,J+m,J-m]X]=95
    # This places the final underscores on the top edges (repeatedly)
    s[i*l,i*m-m+1]=95
  end
  # The above produces the array orientation for backslash, but uses
  # the "wrong" slashes along the diagonals if there's a forward slash.
  # This line flips the matrix in that case, before printing it.
  print((t?s:flipud(s))...))
end

Uso:

f("3/2")

o

f("2\\3")

9

Perl, 343 byte

$_=<>;$_=~/(\d+)(\S)(\d+)/;$v=$2eq'/';$w=$1*3+1;for$y(0..$1*2*$3){$k=$w*$3+$1-1;for$z(0..$k){$x=$v?$k-$z:$z;$q=($y+$1-1)/$1|0;$r=$x/$w|0;$d=$q+$r&1;$f=($y-1)%$1;$f=$1-$f-1if$d;$g=($x-$f)%$w;$u=$r;$q=2*$3-$q+1,$u++if$q>$3;print(($q>=$r&&$q&&$g==0)||($q>$r&&$g==$w-$1)?$d^$v?'/':'\\':$q>=$u&&$y%$1==0&&$g>0&&$g<($w-$1+($q==$r))?"_":$")}print$/}

Multilinea con commenti:

$_=<>;$_=~/(\d+)(\S)(\d+)/;$v=$2eq'/'; # read input
$w=$1*3+1; # compute width of each cube in chars
for$y(0..$1*2*$3){$k=$w*$3+$1-1;for$z(0..$k){ # iterate over rows, columns
    $x=$v?$k-$z:$z;   # flip x co-ordinate based on 2nd param
    $q=($y+$1-1)/$1|0;$r=$x/$w|0;   # parallelogram row and column index
    $d=$q+$r&1;  # flag parallelogram as left or right leaning
    $f=($y-1)%$1;$f=$1-$f-1if$d;  # compute a zig-zag offset
    $g=($x-$f)%$w;  # compute column position, offset by zig-zag
    $u=$r;$q=2*$3-$q+1,$u++if$q>$3; # vertical threshold for printing chars   
    print(($q>=$r&&$q&&$g==0)||($q>$r&&$g==$w-$1)?$d^$v?'/':'\\': # output slash
    $q>=$u&&$y%$1==0&&$g>0&&$g<($w-$1+($q==$r))?"_":$") # underscore or space
}print$/}   # print out newline at end of row

Esempio di output:

2/3
                _____  
               /\    \ 
         _____/  \____\
        /\    \  /    /
  _____/  \____\/____/ 
 /\    \  /    /\    \ 
/  \____\/____/  \____\
\  /    /\    \  /    /
 \/____/  \____\/____/ 
       \  /    /\    \ 
        \/____/  \____\
              \  /    /
               \/____/ 

Ho anche provato a implementarlo come una funzione C usando lo stesso algoritmo, sperando di salvare i byte dal lusso dei nomi delle variabili a carattere singolo, ma è finito 15 byte in più, a 358 byte (deve essere compilato con -std=c89under gcc per smettere il voidnell'intestazione della funzione):

j(char*s){int c,p,v,x,y,k,z,u,g,w,r,d,q,f;char e;sscanf(s,"%d%c%d",&c,&e,&p);v=e=='/';w=c*3+1;for(y=0;y<=c*2*p;y++){k=w*p+c-1;for(z=0;z<=k;z++){x=v?k-z:z;q=(y+c-1)/c;r=x/w;d=q+r&1;f=(y+c-1)%c;if(d)f=c-f-1;g=(x-f)%w;u=r;if(q>p){q=2*p-q+1;u++;}printf("%c",(q>=r&&q&&g==0)||(q>r&&g==w-c)?d^v?'/':'\\':q>=u&&y%c==0&&g>0&&g<(w-c+(q==r))?'_':' ');}printf("\n");}}

Si dovrebbe essere in grado di ottenere la maggior parte, se non tutti quei 15 byte indietro sulla versione C: printf("%c" --> putchar(, printf("\n") --> puts(""), spostare tutte le dichiarazioni int fuori della funzione, allora si può eliminare il int (vedi meta.codegolf.stackexchange.com/q/5532/15599 ), cambia tutti i letterali dei caratteri per i loro codici ASCII, ad es ' ' --> 32. Anche il refactoring del tuo for loop for(k+1;z--;)può essere d'aiuto, ma è più complicato.
Level River St

Inoltre penso che epossa essere un int a condizione che tu lo inizializzi a zero. sscanf sovrascriverà solo il byte meno significativo e potrebbe lasciare qualsiasi spazzatura esistente negli altri tre byte.
Level River St

finalmente penso che un programma completo andrà meglio di una funzione in questo caso. Guadagni tre caratteri extra maininvece di jma non devi passare parametri in sgiro e puoi sfruttare l'inizializzazione automatica delle variabili globali.
Level River St

3

Ruby, 332

L'unico golf fatto finora è l'eliminazione di commenti e rientri. Giocherò a golf più tardi.

gets.match(/\D/)
d=$&<=>"@"
n=$`.to_i
m=2*n
p=$'.to_i
a=(0..h=4*n*p).map{' '*h*2}
(p*p).times{|j|
x=h-j/p*(3*n+1)*d
y=h/2+(j/p-j%p*2)*n
if j%p<=j/p
(-n).upto(n){|i|
a[y+i][i>0?x+m+1-i :x-m-i]=?/
a[y+i][i>0?x-m-1+i :x+m+i]='\\'
a[y+n][x+i]=a[y-n][x+i]=a[y][x-d*(n+i-1)]=?_
a[y+i+(i>>9&1)][x+d*i.abs]='\_/'[(0<=>i*d)+1]
}
end
}
puts a

Ho creato una serie di spazi e vi ho inserito i singoli personaggi. C'è un bel po 'di sovraccarico sia di un cubo sopra l'altro (lavorare dal basso verso l'alto) sia all'interno del cubo stesso, per evitare codice extra. Realizzo la piramide disegnando un rombo (simile a /codegolf//a/54297/15599 ) e sopprimendo la metà superiore.

La parte difficile era disegnare il cubo scalabile. Ho iniziato con un esagono perimetrale con 2n + 1 _caratteri sui lati orizzontali. Avevo anche avuto 2n + 1 /e \, quindi, ne avevo uno di troppo, ma tracciando l' _ultimo li sovrascrivo.

Le linee interne sono le uniche che vengono modificate in base alla direzione verso cui è rivolto il cubo. Traccio tutto /e \con un unico incarico. absaiuta a invertire la direzione e i>>9&1aggiunge un ulteriore 1 ai valori negativi di i, il che abbassa la parte superiore verso il basso. per i= 0 una delle richieste _è sovrastampata, quindi la stringa di selezione '\_/'contiene tutti e tre i simboli, selezionati in base al segno di i.

Lo spazio bianco attorno all'output è ampio ma non eccessivo: 4 * p * n alto e 8 * p * n largo (quest'ultimo è per consentire al cubo apice di essere sempre al centro dell'output). Capisco "trailing / lead spazi bianchi "per includere intere righe, ma può essere rivisto se necessario.

Codice Ungolfed

gets.match(/\D/)                                   #find the symbol that is not a digit. it can be extracted from $&
d=$&<=>"@"                                         #direction, -1 or 1 depends if ascii code for symbol is before or after "@"
n=$`.to_i                                          #side length extracted from match variable $`
m=2*n
p=$'.to_i                                          #pyramid height extracted from match variable $'
a=(0..h=4*n*p).map{' '*h*2}                        #setup an array of h strings of h*2 spaces

(p*p).times{|j|                                    #iterate p**2 times
  x=h-j/p*(3*n+1)*d                                #calculate x and y coordinates for each cube, in a rhombus
  y=h/2+(j/p-j%p*2)*n                              #x extends outwards (and downwards) from the centre, y extends upwards 

  if j%p<=j/p                                      #only print the bottom half of the rhombus, where cube y <= cube x  
    (-n).upto(n){|i|                               #loop 2n+1 times, centred on the centre of the cube 
      a[y+i][i>0?x+m+1-i :x-m-i]=?/                #put the / on the perimeter of the hexagon into the array          
      a[y+i][i>0?x-m-1+i :x+m+i]='\\'              #and the \ also.
      a[y+n][x+i]=a[y-n][x+i]=a[y][x-d*(n+i-1)]=?_ #plot all three lines of _ overwriting the / and \ on the top line    
      a[y+i+(i>>9&1)][x+d*i.abs]='\_/'[(0<=>i*d)+1]#plot the internal / and \ overwriting unwanted _
    }
  end
}
puts a
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.