Construyeme una pirámide


16

Necesitas construir una pirámide a partir de cubos. Los cubos se pueden ver desde 2 ángulos:

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

Este es un ejemplo para cubos de 2 tamaños desde los 2 ángulos posibles. La altura de los cubos es $sizebarras (o barras diagonales), y el ancho del cubo es 2 * $sizesubrayado. El ancho del nivel superior debe contener un carácter de subrayado adicional.

La entrada se proporcionará como una cadena que contiene un número (tamaño de cubos), barra oblicua o barra invertida (para indicar dirección / ángulo) y otro número (altura de la pirámide).

Ejemplos:

Entrada:

1/1

Salida:

 ___
/\__\
\/__/

Entrada:

1\1

Salida:

 ___
/__/\
\__\/

Entrada:

2/1

Salida:

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

Entrada:

1/2

Salida:

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

Entrada:

2\2

Salida:

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

Entrada:

1/3

Salida:

         ___  
     ___/\__\
 ___/\__\/__/
/\__\/__/\__\
\/__/\__\/__/
    \/__/\__\
        \/__/
  • Los espacios en blanco finales / iniciales están bien.
  • Las lagunas estándar no están permitidas.
  • Puede asumir que la entrada siempre será válida.
  • Puede suponer que la entrada no causará una salida demasiado grande, es decir: sin ajuste de línea cuando la salida se imprime en el terminal.
  • El tamaño del cubo y la altura de la pirámide es positivo (es decir, ≥ 1)
  • Este es el código de golf, por lo que gana el código más corto en bytes.

El ganador actual es:

Glen O con 270 bytes en julia

El desafío permanece abierto. si superas al mejor actual, actualizaré la respuesta aceptada.


2
Sus cubos son diferentes de los de los desafíos de patrones de diamantes recientes, ya que la fila superior tiene guiones bajos 2s + 1, mientras que los otros desafíos tenían guiones bajos 2s en la fila superior y 2s-1 en las otras filas. Eso significa que su tono horizontal es 3s + 1. Supongo que es bueno mezclar cosas. Simplemente haciendo la observación en caso de que alguien la pierda.
Level River St

1
¿Cuáles son los valores máximos de tamaño y altura? ¿podemos suponer que son un dígito?
Level River St

no, no puede suponer que es un dígito, pero puede suponer que la entrada proporcionada no hará que la salida sea "demasiado grande", es decir, no causará el ajuste de línea en su terminal.
gilad hoch

Respuestas:


3

Julia - 503 455 369 346 313 270 bytes

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))...))

Sin golf:

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 bytes

$_=<>;$_=~/(\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$/}

Multilínea con comentarios:

$_=<>;$_=~/(\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

Salida de ejemplo:

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

También intenté implementarlo como una función C usando el mismo algoritmo, con la esperanza de guardar bytes del lujo de los nombres de variables de un solo carácter, pero terminó 15 bytes más grande, a 358 bytes (debe compilarse con -std=c89under gcc para dejarlo) el voiden el encabezado de la función):

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

Usted debe ser capaz de obtener la mayoría, si no todos los 15 bytes de vuelta en la versión C: printf("%c" --> putchar(, printf("\n") --> puts(""), mover todas las declaraciones int fuera de la función, a continuación, se puede eliminar la int (ver meta.codegolf.stackexchange.com/q/5532/15599 ), cambie todos los literales de caracteres para sus códigos ascii, por ejemplo ' ' --> 32. Refactorizar sus bucles for, por ejemplo for(k+1;z--;), también puede ayudar, pero es más complicado.
Level River St el

También creo que epuede ser un int siempre que lo inicialice a cero. sscanf solo sobrescribirá el byte menos significativo y puede dejar cualquier basura existente en los otros tres bytes.
Level River St

Finalmente, creo que un programa completo funcionará mejor que una función en este caso. Obtiene tres caracteres adicionales en mainlugar de, jpero no tiene que pasar parámetros s, y puede aprovechar la inicialización automática de variables globales.
Level River St

3

Rubí, 332

El único juego de golf realizado hasta ahora es la eliminación de comentarios y sangrías. Jugaré golf más tarde.

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

Configuré una serie de espacios y metí los caracteres individuales en él. Hay bastante sobreescritura de un cubo encima de otro (trabajo de abajo hacia arriba) y dentro del propio cubo, para evitar el código adicional. Hago la pirámide dibujando un rombo (similar a /codegolf//a/54297/15599 ) y suprimiendo la mitad superior.

La parte difícil fue dibujar el cubo escalable. Comencé con un hexágono perimetral con 2n + 1 _caracteres en los lados horizontales. También había tenido 2n + 1 /y \, por lo tanto, tenía uno demasiado, pero al trazar el _último los sobrescribo.

Las líneas internas son las únicas que se cambian según la dirección que esté mirando el cubo. Trazo todo /y \con una sola tarea. absayuda a invertir la dirección y i>>9&1agrega un 1 adicional a los valores negativos de i, lo que reduce la parte superior hacia abajo. for i= 0 uno de los requeridos _está sobreplotado, por lo que la cadena de selección '\_/'contiene los tres símbolos, seleccionados de acuerdo con el signo de i.

El espacio en blanco alrededor de la salida es amplio pero no excesivo: 4 * p * n alto y 8 * p * n ancho (este último es para permitir que el cubo del ápice esté siempre en el centro de la salida). Entiendo "arrastrar / liderar espacios en blanco "para incluir líneas completas, pero puede revisar si es necesario.

Código sin golf

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.