Bangun Me Pyramid

16

Anda perlu membangun piramida dari kubus. Kubus dapat dilihat dari 2 sudut:

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

Ini adalah contoh untuk 2 kubus ukuran dari 2 sudut yang memungkinkan. Ketinggian kubus adalah $sizegaris miring (atau garis miring), dan lebar kubus adalah 2 * $sizegaris bawah. Lebar tingkat atas harus berisi karakter garis bawah ekstra.

Input akan diberikan sebagai string yang berisi angka (ukuran kubus), garis miring atau garis miring terbalik (untuk menunjukkan arah / sudut), dan angka lain (ketinggian piramida).

Contoh:

Memasukkan:

1/1

Keluaran:

 ___
/\__\
\/__/

Memasukkan:

1\1

Keluaran:

 ___
/__/\
\__\/

Memasukkan:

2/1

Keluaran:

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

Memasukkan:

1/2

Keluaran:

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

Memasukkan:

2\2

Keluaran:

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

Memasukkan:

1/3

Keluaran:

         ___  
     ___/\__\
 ___/\__\/__/
/\__\/__/\__\
\/__/\__\/__/
    \/__/\__\
        \/__/
  • Trailing / spasi putih terkemuka tidak masalah.
  • Celah standar tidak diijinkan.
  • Anda dapat berasumsi bahwa input akan selalu valid.
  • Anda dapat mengasumsikan input tidak akan menyebabkan output terlalu besar, yaitu: tidak ada pembungkus garis ketika output dicetak ke terminal.
  • Ukuran kubus & tinggi piramida positif (yaitu ≥ 1)
  • Ini adalah kode-golf, jadi kode terpendek dalam byte menang.

Pemenang saat ini adalah:

Glen O dengan 270 byte di julia

tantangan tetap terbuka. jika Anda mengalahkan yang terbaik saat ini, saya akan memperbarui jawaban yang diterima.

gilad hoch
sumber
2
Kubus Anda berbeda dari yang ada di tantangan pola berlian baru-baru ini, di mana baris atas memiliki garis bawah 2s + 1, sedangkan tantangan lainnya memiliki garis bawah 2s di baris atas dan 2s-1 di baris lainnya. Itu berarti pitch horizontal Anda adalah 3s +1. Saya kira itu baik untuk menggabungkan hal-hal di sekitar. Hanya melakukan pengamatan kalau-kalau ada orang yang melewatkannya.
Level River St
1
apa nilai maksimal ukuran dan tinggi? dapatkah kita menganggap mereka satu digit?
Level River St
tidak, Anda mungkin tidak menganggap itu satu digit, tetapi Anda dapat menganggap input yang disediakan tidak akan menyebabkan output menjadi "terlalu besar", yaitu tidak akan menyebabkan pembungkus baris di terminal Anda.
gilad hoch

Jawaban:

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

Tidak Terkumpul:

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

Pemakaian:

f("3/2")

atau

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

Multiline dengan komentar:

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

Contoh output:

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

Saya juga mencoba mengimplementasikannya sebagai fungsi C menggunakan algoritma yang sama, berharap untuk menyimpan byte dari kemewahan nama variabel karakter tunggal, tetapi akhirnya menjadi 15 byte lebih besar, pada 358 byte (perlu dikompilasi dengan di -std=c89bawah gcc untuk meninggalkan yang voiddi header fungsi):

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
sumber
Anda harus bisa mendapatkan sebagian besar, jika tidak semua orang 15 byte kembali pada versi C: printf("%c" --> putchar(, printf("\n") --> puts(""), memindahkan semua deklarasi int luar fungsi, maka Anda dapat menghilangkan int (lihat meta.codegolf.stackexchange.com/q/5532/15599 ), ubah semua literal karakter untuk kode ascii mereka mis ' ' --> 32. Refactoring untuk loop Anda misalnya for(k+1;z--;)juga bisa membantu tetapi lebih rumit.
Level River St
Juga saya pikir ebisa menjadi int asalkan Anda menginisialisasi ke nol. sscanf hanya akan menimpa byte paling signifikan dan dapat meninggalkan sampah yang ada di tiga byte lainnya.
Level River St
akhirnya saya pikir program lengkap akan lebih baik daripada fungsi dalam hal ini. Anda mendapatkan tiga karakter tambahan mainalih-alih jtetapi Anda tidak harus melewati parameter s, dan Anda dapat memanfaatkan inisialisasi otomatis variabel global.
Level River St
3

Ruby, 332

Satu-satunya golf yang dilakukan sejauh ini adalah penghapusan komentar dan indentasi. Saya akan bermain golf nanti.

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

Saya mengatur array spasi dan memasukkan karakter individu ke dalamnya. Ada cukup banyak overdrawing dari satu kubus di atas yang lain (bekerja dari bawah ke atas) dan di dalam kubus itu sendiri, untuk menghindari kode tambahan. Saya membuat piramida dengan menggambar belah ketupat (mirip dengan /codegolf//a/54297/15599 ) dan melampaui bagian atas.

Bagian yang sulit adalah menggambar kubus yang bisa diukur. Saya mulai dengan segi enam perimeter dengan 2n +1 _karakter di sisi horizontal. Saya juga punya 2n +1 /dan \, jadi saya punya terlalu banyak, tetapi dengan merencanakan yang _terakhir saya menimpa mereka.

Garis internal adalah satu-satunya yang diubah tergantung pada arah yang dihadapi kubus. Saya memplot semua /dan \dengan satu tugas. absmembantu membalikkan arah, dan i>>9&1menambahkan 1 ekstra ke nilai negatif i, yang menurunkan bagian atas ke bawah. untuk i= 0 salah satu yang diperlukan _overplotted, sehingga string pemilih '\_/'berisi ketiga simbol, dipilih sesuai dengan tanda i.

Ruang kosong di sekitar output cukup tetapi tidak berlebihan: 4 * p * n tinggi dan 8 * p * n lebar (yang terakhir adalah untuk memungkinkan apex cube untuk selalu berada di pusat output.) Saya mengerti "trailing / leading spasi putih "untuk memasukkan seluruh baris, tetapi dapat merevisi jika perlu.

Kode tidak dikunci

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
sumber