Zbuduj mi piramidę

16

Musisz zbudować piramidę z kostek. Kostki można oglądać pod 2 kątami:

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

To jest przykład kostek 2-wymiarowych z 2 możliwych kątów. Wysokość kostek to $sizeukośniki (lub odwrotne), a szerokość sześcianu jest 2 * $sizepodkreślona. Szerokość najwyższego poziomu powinna zawierać dodatkowy znak podkreślenia.

Dane wejściowe będą dostarczane jako ciąg znaków zawierający liczbę (rozmiar kostki), ukośnik lub ukośnik odwrotny (w celu wskazania kierunku / kąta) oraz inną liczbę (wysokość piramidy).

Przykłady:

Wejście:

1/1

Wynik:

 ___
/\__\
\/__/

Wejście:

1\1

Wynik:

 ___
/__/\
\__\/

Wejście:

2/1

Wynik:

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

Wejście:

1/2

Wynik:

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

Wejście:

2\2

Wynik:

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

Wejście:

1/3

Wynik:

         ___  
     ___/\__\
 ___/\__\/__/
/\__\/__/\__\
\/__/\__\/__/
    \/__/\__\
        \/__/
  • Końcowe / wiodące białe znaki są prawidłowe.
  • Standardowe luki są niedozwolone.
  • Możesz założyć, że dane wejściowe będą zawsze prawidłowe.
  • Możesz założyć, że dane wejściowe nie spowodują zbyt dużego wyniku, tj .: brak zawijania linii, gdy dane wyjściowe zostaną wydrukowane na terminalu.
  • Rozmiar sześcianu i wysokość piramidy jest dodatnia (tj. ≥ 1)
  • To jest golf golfowy, więc wygrywa najkrótszy kod w bajtach.

Aktualny zwycięzca to:

Glen O z 270 bajtami w Julii

wyzwanie pozostaje otwarte. jeśli pobijesz obecny najlepszy, zaktualizuję zaakceptowaną odpowiedź.

Gilad Hoch
źródło
2
Twoje kostki różnią się od tych z ostatnich wyzwań ze wzorem diamentu, ponieważ górny rząd ma podkreślenia 2s + 1, podczas gdy pozostałe wyzwania miały podkreślenia 2s w górnym rzędzie i 2s-1 w pozostałych rzędach. Oznacza to, że wysokość w poziomie wynosi 3 s + 1. Myślę, że dobrze jest mieszać różne rzeczy. Po prostu dokonanie obserwacji na wypadek, gdyby ktoś jej nie zauważył.
Level River St
1
jakie są maksymalne wartości rozmiaru i wysokości? czy możemy założyć, że są jednocyfrowe?
Level River St
nie, możesz nie założyć, że jest to jedna cyfra, ale możesz założyć, że podane dane wejściowe nie spowodują, że wynik będzie „zbyt duży”, tj. nie spowoduje zawijania linii w twoim terminalu.
gilad hoch

Odpowiedzi:

3

Julia - 503 455 369 346 313 270 bajtów

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

Nie golfowany:

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

Stosowanie:

f("3/2")

lub

f("2\\3")
Glen O
źródło
9

Perl, 343 bajtów

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

Multiline z komentarzami:

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

Przykładowe dane wyjściowe:

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

Próbowałem również zaimplementować go jako funkcję C przy użyciu tego samego algorytmu, mając nadzieję na zaoszczędzenie bajtów z luksusu jednoznakowych nazw zmiennych, ale skończyło się to 15 bajtami większymi, przy 358 bajtach (aby go -std=c89przerwać, należy go skompilować pod gcc voidw nagłówku funkcji):

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
źródło
Powinieneś być w stanie uzyskać większość, jeśli nie wszystkie te 15 bajtów kopii wersji C: printf("%c" --> putchar(, printf("\n") --> puts(""), przenieść wszystkie deklaracje int poza funkcją, można wyeliminować int (patrz meta.codegolf.stackexchange.com/q/5532/15599 ), zmień wszystkie literały znaków dla ich kodów ascii, np ' ' --> 32. Refaktoryzacja pętli np. for(k+1;z--;)Może również pomóc, ale jest trudniejsza.
Level River St
Myślę też, że emoże być int pod warunkiem, że zainicjujesz go do zera. sscanf nadpisze tylko najmniej znaczący bajt i może pozostawić wszelkie śmieci w pozostałych trzech bajtach.
Level River St
wreszcie myślę, że w tym przypadku pełny program będzie lepszy niż funkcja. mainZamiast tego jzyskujesz trzy dodatkowe znaki, ale nie musisz przekazywać parametrów si możesz skorzystać z automatycznej inicjalizacji zmiennych globalnych.
Level River St
3

Ruby, 332

Jedynym golfem wykonanym do tej pory jest wyeliminowanie komentarzy i wcięć. Później zagram w golfa.

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

Ustawiam tablicę spacji i wsuwam w nią poszczególne postacie. Przeciąganie zarówno jednej kostki na drugą (praca od dołu do góry), jak i samej kostki jest dość duże, aby uniknąć dodatkowego kodu. Tworzę piramidę, rysując romb (podobny do /codegolf//a/54297/15599 ) i tłumiąc górną połowę.

Najtrudniejszą częścią było narysowanie skalowalnej kostki. Zacząłem od sześciokąta obwodowego z 2n + 1 _znakami po poziomych bokach. Ja też miałem 2n + 1 /i \tak miałem jeden zbyt wiele, ale przez wykreślenie _ostatni raz zastępowania nimi.

Jedynie linie wewnętrzne zmieniane są w zależności od kierunku, w którym zwrócona jest kostka. Spisuję wszystko /i \za pomocą jednego zadania. abspomaga odwrócić kierunek i i>>9&1dodaje dodatkowe 1 do ujemnych wartości i, co obniża górną część w dół. dla i= 0 jeden z wymaganych _jest wykreślany, więc łańcuch selektora '\_/'zawiera wszystkie trzy symbole, wybrane zgodnie ze znakiem i.

Biała spacja wokół wyjścia jest duża, ale nie nadmierna: 4 * p * n wysoka i 8 * p * n szeroka (ta ostatnia ma umożliwić, aby wierzchołek kostki zawsze znajdował się w środku wyjścia). Rozumiem „końcowe / wiodące białe znaki ”, aby uwzględnić całe linie, ale w razie potrzeby można je zmienić.

Nieskluczony kod

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
źródło