Duchy i Dynie

15

Oto dynia ASCII wyrzeźbiona w latarni morskiej. Czy to nie słodkie?

((^v^))

Oto duch ASCII. Zobacz, jakie to straszne!

\{O.O}/

Oczywiście dynie muszą znajdować się na ziemi, z odstępem między nimi, aby się nie gniły.

Duchy jednak lubią stać na dyniach , więc są jeszcze bardziej przerażające . Muszą jednak stać na dwóch dyniach, w przeciwnym razie ich upiorny ciężar zmiażdży dyni pod nimi. Ale ze względu na sposób działania ich widmowej magii wiele duchów może układać dynie i dzielić się nimi, pod warunkiem, że duchy są równo podzielone na niższe dynie lub na niższe duchy. Innymi słowy, tworząc kształt ludzkiej piramidy . Pamiętaj, że duchy nie mogą nakładać się na duchy, chyba że pod spodem znajduje się dynia (tak działa magia).

Biorąc pod uwagę dwie nieujemne liczby całkowite, gi preprezentując liczbę ghostów i pumpkinów, wysyłamy najbardziej kompaktową lewą formację, jak to możliwe, zgodnie z powyższymi regułami układania piramidy. Pozostałe dynie i duchy (czyli te, które nie tworzą piramidy) idą na ziemię po prawej stronie.

Dla wyjaśnienia te formacje są OK (oddzielone puste znaki nowej linii) i służą jako przykładowe operacje wejścia / wyjścia:

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

Te formacje nie są OK

\{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^))

Wejście

Dwie nieujemne liczby całkowite w dowolnym dogodnym formacie . Co najmniej jedna z liczb będzie niezerowa. Możesz przyjmować dane wejściowe w dowolnej kolejności (tj. W przykładach, w których najpierw miałem dynie) - określ, w jaki sposób przyjmujesz dane wejściowe w swojej odpowiedzi.

Wynik

Reprezentacja duchów i dyń w stylu ASCII, zgodnie z powyższymi zasadami. Wiodące / końcowe znaki nowej linii lub inne białe znaki są opcjonalne, pod warunkiem, że duchy i dynie są odpowiednio ustawione.

Zasady

  • Dopuszczalny jest pełny program lub funkcja. Jeśli funkcja, możesz zwrócić dane wyjściowe zamiast je drukować.
  • Standardowe luki są zabronione.
  • To jest więc obowiązują wszystkie zwykłe zasady gry w golfa, a wygrywa najkrótszy kod (w bajtach).
AdmBorkBork
źródło
Jaka jest poprawna formacja dla 7 dyń i 6 duchów?
Neil
@Neil Ponieważ zasady wymagają najbardziej zwartego wyjścia z lewej strony, byłaby to piramida 6 duchów na 4 dyniach, z dodatkowymi 3 dyniami po prawej. Dodam to jako przykład.
AdmBorkBork
Cóż, twoje użycie kompaktowego pomieszało mnie - mogłem umieścić wszystkie duchy w tym samym rzędzie, więc to jest bardziej kompaktowe w pionie!
Neil
Czy dynie zawsze będą dostarczane przed duchami?
Gabriel Benamy,
2
Podoba mi się, że duchy i dynie tworzą ludzką piramidę
MayorMonty

Odpowiedzi:

5

JavaScript (ES7), 166 164 159 bajtów

Zaoszczędź 5 bajtów dzięki Neilowi

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):''

Sformatowane i skomentowane

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

Podstawowa matematyka

Trudną częścią jest znalezienie optymalnej szerokości G piramidy duchów.

Liczbę duchów gw takiej piramidzie podaje:

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

Odwrotnie, szerokość piramidy zawierającej gduchy jest prawdziwym pierwiastkiem wynikowego równania kwadratowego:

G² + G - 2g = 0

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

G = (-1 ± √Δ) / 2

Co prowadzi do następującego prawdziwego korzenia (znanego również jako korzeń trójkątny ):

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

Jednak szerokość piramidy jest również ograniczona przez liczbę dyń: nie możemy mieć więcej niż p-1duchy nad pdyniami. Stąd ostateczna formuła zastosowana w kodzie:

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

Wersja ES6, 173 171 166 bajtów

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):''

Przypadki testowe (ES6)

Arnauld
źródło
1
Myślę, że j=(g+g)**.5+.5|0powinien działać.
Neil
Ładne wyjaśnienie!
AdmBorkBork
@Neil Jest to krótszy i bardziej niezawodny. (Moja metoda miała nieprawidłowe wartości, zaczynając od g = 5051.) Dzięki.
Arnauld
3

Perl, 246 bajtów (znaki nowego wiersza nie są częścią kodu i służą wyłącznie do odczytu)

($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;

Akceptuje dwie liczby: najpierw dynie, a następnie duchy. Przykładowe dane wejściowe:

5 20

Przykładowe dane wyjściowe:

                \{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
źródło
Och, czytasz moje sformułowanie trochę inaczej niż zamierzałem - Duchy mogą układać się na duchach tylko wtedy, gdy jest pod nimi dynia, w przeciwnym razie muszą przejść do odpowiedniego pojedynczego pliku. Dlatego w 0p 4gprzypadku testowym wszystkie duchy są umieszczone w jednej linii, a nie w stosie.
AdmBorkBork
@TimmyD W porządku, naprawiłem to teraz. Muszę jednak trochę pograć w golfa, aby to zmniejszyć.
Gabriel Benamy,