Construis-moi une pyramide

16

Vous devez construire une pyramide à partir de cubes. Les cubes peuvent être vus sous 2 angles:

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

Ceci est un exemple pour des cubes de 2 tailles sous les 2 angles possibles. La hauteur des cubes est des $sizebarres obliques (ou des barres obliques inverses) et la largeur du cube est 2 * $sizesoulignée. La largeur de niveau supérieur doit contenir un caractère de soulignement supplémentaire.

L'entrée sera fournie sous la forme d'une chaîne contenant un nombre (taille des cubes), une barre oblique ou une barre oblique inverse (pour indiquer la direction / l'angle) et un autre nombre (hauteur de la pyramide).

Exemples:

Contribution:

1/1

Production:

 ___
/\__\
\/__/

Contribution:

1\1

Production:

 ___
/__/\
\__\/

Contribution:

2/1

Production:

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

Contribution:

1/2

Production:

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

Contribution:

2\2

Production:

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

Contribution:

1/3

Production:

         ___  
     ___/\__\
 ___/\__\/__/
/\__\/__/\__\
\/__/\__\/__/
    \/__/\__\
        \/__/
  • Les espaces de fin / de début sont corrects.
  • Les failles standard ne sont pas autorisées.
  • Vous pouvez supposer que la saisie sera toujours valide.
  • Vous pouvez supposer que l'entrée ne provoquera pas une sortie trop importante, c'est-à-dire: pas de retour à la ligne lorsque la sortie est imprimée sur le terminal.
  • La taille du cube et la hauteur de la pyramide sont positives (c'est-à-dire ≥ 1)
  • C'est le code-golf, donc le code le plus court en octets gagne.

Le gagnant actuel est:

Glen O avec 270 octets en Julia

défi reste ouvert. si vous battez le meilleur du moment, je mettrai à jour la réponse acceptée.

gilad hoch
la source
2
Vos cubes sont différents de ceux des défis de motif de diamant récents, dans la mesure où la ligne supérieure a 2 soulignements 2 + 1, tandis que les autres défis avaient 2 soulignements 2 sur la rangée supérieure et 2 s -1 sur les autres rangées. Cela signifie que votre hauteur horizontale est de 3 s + 1. Je suppose que c'est bon de mélanger les choses. Faire juste l'observation au cas où quelqu'un la manquerait.
Level River St
1
quelles sont les valeurs maximales de taille et de hauteur? pouvons-nous supposer qu'ils sont à un chiffre?
Level River St
non, vous ne pouvez pas supposer qu'il s'agit d'un chiffre, mais vous pouvez supposer que l'entrée fournie n'entraînera pas une sortie "trop ​​grande", c'est-à-dire qu'elle n'entraînera pas de retour à la ligne dans votre terminal.
gilad hoch

Réponses:

3

Julia - 503 455 369 346 313 270 octets

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

Non 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

Usage:

f("3/2")

ou

f("2\\3")
Glen O
la source
9

Perl, 343 octets

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

Multiligne avec commentaires:

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

Exemple de sortie:

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

J'ai également essayé de l'implémenter en tant que fonction C en utilisant le même algorithme, dans l'espoir de sauver les octets du luxe des noms de variable à un seul caractère, mais cela a fini par 15 octets de plus, à 358 octets (doit être compilé avec -std=c89sous gcc pour ne pas voiddans l' en-tête de la fonction):

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
la source
Vous devriez être en mesure d'obtenir la plupart, sinon tous les 15 octets de retour sur la version C: printf("%c" --> putchar(, printf("\n") --> puts(""), déplacer toutes les déclarations int en dehors de la fonction, vous pouvez éliminer le int (voir meta.codegolf.stackexchange.com/q/5532/15599 ), changez tous les littéraux de caractères pour leurs codes ascii, par exemple ' ' --> 32. La refactorisation de vos boucles for, par exemple, for(k+1;z--;)peut également aider mais est plus délicate.
Level River St
Je pense aussi que epeut être un int à condition de l'initialiser à zéro. sscanf ne remplacera que l'octet le moins significatif et peut laisser les déchets existants dans les trois autres octets.
Level River St
enfin je pense qu'un programme complet ira mieux qu'une fonction dans ce cas. Vous gagnez trois caractères supplémentaires à la mainplace de jmais vous n'avez pas à transmettre de paramètre s, et vous pouvez profiter de l'initialisation automatique des variables globales.
Level River St
3

Rubis, 332

Le seul golf fait jusqu'à présent est l'élimination des commentaires et des retraits. Je jouerai au golf plus tard.

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

J'ai mis en place un tableau d'espaces et y pousser les personnages individuels. Il y a pas mal de surdimensionnement d'un cube au-dessus d'un autre (travail de bas en haut) et dans le cube lui-même, pour éviter un code supplémentaire. Je fais la pyramide en dessinant un losange (similaire à /codegolf//a/54297/15599 ) et en écrasant la moitié supérieure.

La partie difficile dessinait le cube évolutif. J'ai commencé avec un hexagone de périmètre avec 2n + 1 _caractères sur les côtés horizontaux. J'avais également eu 2n + 1 /et \, donc j'en avais un de trop, mais en traçant le _dernier je les écrase.

Les lignes internes sont les seules qui changent en fonction de la direction du cube. Je trace tout /et \avec une seule affectation. absaide à inverser la direction et i>>9&1ajoute un 1 supplémentaire aux valeurs négatives de i, ce qui abaisse la partie supérieure vers le bas. pour i= 0, l'un des éléments requis _est surploté, de sorte que la chaîne de sélection '\_/'contient les trois symboles, sélectionnés selon le signe de i.

L'espace autour de la sortie est ample mais pas excessif: 4 * p * n haut et 8 * p * n large (ce dernier permet au cube de l'apex d'être toujours au centre de la sortie.) Je comprends "trailing / leader" espaces blancs "pour inclure des lignes entières, mais peut être révisé si nécessaire.

Code non 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
Level River St
la source