Construa-me uma pirâmide

16

Você precisa construir uma pirâmide a partir de cubos. Os cubos podem ser vistos de dois ângulos:

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

Este é um exemplo para cubos de tamanho 2 a partir dos 2 ângulos possíveis. A altura dos cubos é $sizebarras (ou barras invertidas) e a largura do cubo é 2 * $sizesublinhada. A largura do nível superior deve conter um caractere sublinhado extra.

A entrada será fornecida como uma sequência contendo um número (tamanho de cubos), barra ou barra invertida (para indicar direção / ângulo) e outro número (altura da pirâmide).

Exemplos:

Entrada:

1/1

Resultado:

 ___
/\__\
\/__/

Entrada:

1\1

Resultado:

 ___
/__/\
\__\/

Entrada:

2/1

Resultado:

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

Entrada:

1/2

Resultado:

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

Entrada:

2\2

Resultado:

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

Entrada:

1/3

Resultado:

         ___  
     ___/\__\
 ___/\__\/__/
/\__\/__/\__\
\/__/\__\/__/
    \/__/\__\
        \/__/
  • Os espaços em branco à direita / à esquerda estão OK.
  • As brechas padrão não são permitidas.
  • Você pode assumir que a entrada sempre será válida.
  • Você pode assumir que a entrada não causará uma saída muito grande, ou seja: sem quebra de linha quando a saída for impressa no terminal.
  • O tamanho do cubo e a altura da pirâmide são positivos (ou seja, ≥ 1)
  • Isso é código-golfe, então o código mais curto em bytes vence.

O vencedor atual é:

Glen O com 270 bytes em julia

o desafio permanece aberto. se você vencer o atual, atualizarei a resposta aceita.

Gilad Hoch
fonte
2
Seus cubos são diferentes dos desafios recentes nos padrões de diamante, em que a linha superior tem sublinhados 2s + 1, enquanto os outros desafios tiveram sublinhados 2s na linha superior e 2s-1 nas outras linhas. Isso significa que seu tom horizontal é 3s + 1. Eu acho que é bom misturar as coisas. Apenas fazendo a observação caso alguém perca.
Level River St
11
quais são os valores máximos de tamanho e altura? podemos assumir que eles são um dígito?
Level River St
não, você não pode assumir que seja um dígito, mas você pode assumir que a entrada fornecida não fará com que a saída seja "muito grande", ou seja, não causará quebra de linha no seu terminal.
gilad hoch

Respostas:

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

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

ou

f("2\\3")
Glen O
fonte
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$/}

Multilinha com comentários:

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

Exemplo de saída:

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

Eu também tentei implementá-lo como uma função C usando o mesmo algoritmo, esperando salvar bytes do luxo de nomes de variáveis ​​de um caractere, mas ele acabou sendo 15 bytes maior, a 358 bytes (precisa ser compilado com o -std=c89gcc para deixar de fora). o voidno cabeçalho da função):

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");}}
samgak
fonte
Você deve ser capaz de obter a maioria, se não todos esses 15 bytes de volta na versão C: printf("%c" --> putchar(, printf("\n") --> puts(""), mover todas as declarações int fora da função, então você pode eliminar o int (ver meta.codegolf.stackexchange.com/q/5532/15599 ), altere todos os literais de caracteres para seus códigos ascii, por exemplo ' ' --> 32. Refatorar os loops for, por exemplo, for(k+1;z--;)também pode ajudar, mas é mais complicado.
Level River St
Também acho que epode ser um int, desde que você o inicialize em zero. sscanf substituirá apenas o byte menos significativo e poderá deixar qualquer lixo existente nos outros três bytes.
Level River St
finalmente, acho que um programa completo funcionará melhor do que uma função nesse caso. Você ganha três caracteres extras em mainvez de, jmas não precisa passar o parâmetro s, e pode tirar proveito da inicialização automática de variáveis ​​globais.
Level River St
3

Ruby, 332

O único golfe realizado até agora é a eliminação de comentários e recuos. Mais tarde vou jogar golfe.

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

Eu montei uma variedade de espaços e coloquei os caracteres individuais nele. Há muita sobreposição de um cubo em cima de outro (trabalho de baixo para cima) e dentro do próprio cubo, para evitar código extra. Eu faço a pirâmide desenhando um losango (semelhante a /codegolf//a/54297/15599 ) e suprimindo a metade superior.

A parte difícil foi desenhar o cubo escalável. Comecei com um hexágono de perímetro com 2n + 1 _caracteres nos lados horizontais. Eu também tinha 2n + 1 /e \, portanto, tinha muitos, mas, ao traçar o _último, eu os sobrescrevia.

As linhas internas são as únicas que são alteradas dependendo da direção em que o cubo está voltado. Eu traço tudo /e \com uma única tarefa. absajuda a reverter a direção e i>>9&1adiciona 1 extra aos valores negativos de i, o que diminui a parte superior. para i= 0, um dos requeridos _é plotado em excesso, portanto, a sequência do seletor '\_/'contém todos os três símbolos, selecionados de acordo com o sinal de i.

O espaço em branco ao redor da saída é amplo, mas não excessivo: 4 * p * n alto e 8 * p * n de largura (este último é para permitir que o cubo apex esteja sempre no centro da saída.) Entendo "à direita / à esquerda" espaços em branco "para incluir linhas inteiras, mas pode revisar se necessário.

Código 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
Level River St
fonte