Hantu dan Labu

15

Ini labu ASCII yang diukir menjadi Jack-o-Lantern. Bukankah itu lucu?

((^v^))

Ini hantu ASCII. Lihat betapa seramnya itu!

\{O.O}/

Jelas, labu harus berada di tanah, dengan ruang di antara mereka sehingga tidak membusuk.

Hantu, bagaimanapun, suka berdiri di atas labu, jadi mereka bahkan lebih menakutkan . Namun, mereka harus berdiri di atas dua labu, jika tidak, berat hantu mereka akan menghancurkan labu di bawah mereka. Tetapi, karena cara sihir hantu mereka bekerja, banyak hantu dapat menumpuk dan berbagi labu, asalkan hantu itu terbagi rata pada labu yang lebih rendah atau hantu yang lebih rendah. Dengan kata lain, membentuk bentuk seperti piramida manusia . Perhatikan bahwa hantu tidak bisa menumpuk pada hantu kecuali ada labu di bawahnya (begitulah cara kerjanya).

Diberi dua bilangan bulat non-negatif, gdan p, mewakili jumlah ghost danp umpkins, menghasilkan formasi paling kiri paling kompak, mengikuti aturan susunan piramida di atas. Labu dan hantu sisa (yaitu, mereka yang tidak membentuk piramida) pergi ke tanah ke kanan.

Untuk klarifikasi, formasi ini OK (dipisahkan baris baru kosong), dan berfungsi sebagai contoh I / O:

0p 1g
\{O.O}/

1p 0g
((^v^))

1p 1g
((^v^)) \{O.O}/

2p 1g
    \{O.O}/
((^v^)) ((^v^))

2p 2g
    \{O.O}/
((^v^)) ((^v^)) \{O.O}/

3p 1g
    \{O.O}/
((^v^)) ((^v^)) ((^v^))

3p 2g
    \{O.O}/ \{O.O}/
((^v^)) ((^v^)) ((^v^))

3p 3g
        \{O.O}/
    \{O.O}/ \{O.O}/
((^v^)) ((^v^)) ((^v^))

0p 4g
\{O.O}/ \{O.O}/ \{O.O}/ \{O.O}/

3p 0g
((^v^)) ((^v^)) ((^v^))

7p 6g
            \{O.O}/
        \{O.O}/ \{O.O}/
    \{O.O}/ \{O.O}/ \{O.O}/
((^v^)) ((^v^)) ((^v^)) ((^v^)) ((^v^)) ((^v^)) ((^v^))

Formasi ini Tidak Baik

\{O.O}/
((^v^))

    \{O.O}/
((^v^))

((^v^)) ((^v^)) \{O.O}/

    \{O.O}/
    \{O.O}/
((^v^)) ((^v^))

            \{O.O}/
\{O.O}/ ((^v^)) ((^v^))

    ((^v^))
((^v^)) ((^v^))

      \{O.O}/
((^v^)) ((^v^))

Memasukkan

Dua bilangan bulat non-negatif dalam format apa pun yang nyaman . Setidaknya salah satu angka akan menjadi nol. Anda dapat mengambil input dalam urutan mana pun (mis., Dalam contoh yang saya miliki labu dulu) - harap tentukan bagaimana Anda mengambil input dalam jawaban Anda.

Keluaran

Representasi ASCII-art dari hantu dan labu, mengikuti aturan di atas. Leading / trailing newlines atau spasi putih lainnya adalah opsional, asalkan hantu dan labu berbaris dengan tepat.

Aturan

  • Program lengkap atau fungsi dapat diterima. Jika suatu fungsi, Anda dapat mengembalikan output daripada mencetaknya.
  • Celah standar dilarang.
  • Ini adalah sehingga semua aturan golf biasa berlaku, dan kode terpendek (dalam byte) menang.
AdmBorkBork
sumber
Apa formasi yang benar untuk 7 labu dan 6 hantu?
Neil
@Neil Karena aturan meminta output paling kompak paling kiri, itu akan menjadi piramida 6 hantu di atas 4 labu, dengan 3 labu tambahan di sebelah kanan. Saya akan menambahkannya sebagai contoh.
AdmBorkBork
Nah, penggunaan compact Anda membuat saya bingung - saya bisa menempatkan semua hantu di baris yang sama, jadi itu lebih kompak secara vertikal!
Neil
Akankah labu selalu disediakan sebelum hantu?
Gabriel Benamy
2
Saya suka bahwa hantu dan labu membuat piramida manusia
MayorMonty

Jawaban:

5

JavaScript (ES7), 166 164 159 byte

Disimpan 5 byte berkat Neil

f=(p,g,j=(g*2)**.5+.5|0,G=j>p-1?p?p-1:0:j,P=`
`,i=~j?g-G*++G/2:G,n=i>0?i>g?g:i:0)=>p|g?f(0,g-n,-1,G-1,P+'    ')+P+'((^v^)) '.repeat(p)+'\\{O.O}/ '.repeat(n):''

Diformat dan dikomentari

f = (                                    // given:
  p,                                     // - p = number of pumpkins
  g,                                     // - g = number of ghosts
  j = (g * 2) ** .5 + .5 | 0,            // - j = ceil(triangular root of g)
  G = j > p - 1 ? p ? p - 1 : 0 : j,     // - G = max(0, min(p - 1, j))
  P = '\n',                              // - P = padding string (+ line-break)
  i = ~j ?                               // - i =
    g - G * ++G / 2                      //   first iteration: g - G * (G + 1) / 2
  : G,                                   //   next iterations: G
  n = i > 0 ? i > g ? g : i : 0          // - n = max(0, min(i, g)) = number of
) =>                                     //   ghosts to print at this iteration
p | g ?                                  // if there's still something to print:
  f(                                     //   do a recursive call with:
    0,                                   //   - no pumpkin anymore
    g - n,                               //   - the updated number of ghosts
    -1,                                  //   - j = -1 (so that ~j == 0)
    G - 1,                               //   - one less ghost on the pyramid row
    P + '    '                           //   - updated padding string
  ) +                                    //   
  P +                                    //   append padding string
  '((^v^)) '.repeat(p) +                 //   append pumpkins
  '\\{O.O}/ '.repeat(n)                  //   append ghosts
: ''                                     // else: stop

Matematika yang mendasari

Bagian yang sulit adalah untuk mengetahui lebar optimal Gpiramida hantu.

Jumlah hantu gdalam piramida tersebut diberikan oleh:

g = 1 + 2 + 3 + ... + G = G(G + 1) / 2

Timbal balik, lebar piramida yang mengandung ghantu adalah akar nyata dari persamaan kuadratik yang dihasilkan:

G² + G - 2g = 0

Δ = 1² - 4(-2g)
Δ = 8g + 1

G = (-1 ± √Δ) / 2

Yang mengarah ke root asli berikut (juga dikenal sebagai root triangular ):

G = (√(8g + 1) - 1) / 2

Namun, lebar piramida juga dibatasi oleh jumlah labu: kita dapat memiliki tidak lebih dari p-1 hantu di atas plabu. Oleh karena itu rumus akhir yang digunakan dalam kode:

j = ⌈(√(8g + 1) - 1) / 2⌉
G = max(0, min(p - 1, j))

Versi ES6, 173 171 166 byte

f=(p,g,j=Math.pow(g*2,.5)+.5|0,G=j>p-1?p?p-1:0:j,P=`
`,i=~j?g-G*++G/2:G,n=i>0?i>g?g:i:0)=>p|g?f(0,g-n,-1,G-1,P+'    ')+P+'((^v^)) '.repeat(p)+'\\{O.O}/ '.repeat(n):''

Test case (ES6)

Arnauld
sumber
1
Saya pikir j=(g+g)**.5+.5|0harus bekerja.
Neil
Penjelasan yang bagus!
AdmBorkBork
@ Neil Ini lebih pendek dan lebih dapat diandalkan. (Metode saya memiliki beberapa nilai yang tidak valid, mulai dari g = 5051.) Terima kasih.
Arnauld
3

Perl, 246 byte (baris baru bukan bagian dari kode dan disediakan hanya untuk dibaca)

($c,$d)=<>=~/(\d+)/g;
$p="((^v^)) ";$g="\\{O.O}/ ";
for($f[0]=$c;$d>0;$d--){$f[$b+1]+1<$f[$b]?$f[++$b]++:$f[$b]++;$f[0]+=$d,$d=0 if$b==$c-1;$f[$b]==1?$b=0:1}
$h[0]=($p x$c).$g x($f[0]-$c);$h[$_].=$"x(4*$_).$g x$f[$_]for(1..$#f);
say join$/,reverse@h;

Menerima dua angka: labu pertama, diikuti oleh hantu. Input sampel:

5 20

Output sampel:

                \{O.O}/ 
            \{O.O}/ \{O.O}/ 
        \{O.O}/ \{O.O}/ \{O.O}/ 
    \{O.O}/ \{O.O}/ \{O.O}/ \{O.O}/ 
((^v^)) ((^v^)) ((^v^)) ((^v^)) ((^v^)) \{O.O}/ \{O.O}/ \{O.O}/ \{O.O}/ \{O.O}/ \{O.O}/ \{O.O}/ \{O.O}/ \{O.O}/ \{O.O}/ \{O.O}/ 
Gabriel Benamy
sumber
Oh, Anda membaca kata-kata saya sedikit berbeda dari apa yang saya maksudkan - Hantu hanya dapat menumpuk di atas hantu jika ada labu di bawahnya, jika tidak mereka harus pergi ke file tunggal yang tepat. Itu sebabnya 0p 4gtest case memiliki semua hantu dalam satu baris, bukannya ditumpuk.
AdmBorkBork
@TimmyD Baiklah, saya memperbaikinya sekarang. Saya perlu melakukan sedikit golf untuk mengurangi itu.
Gabriel Benamy