Fantasmas e abóboras

15

Aqui está uma abóbora ASCII esculpida em uma Jack-o-Lantern. Não é fofo?

((^v^))

Aqui está um fantasma ASCII. Olha como é assustador!

\{O.O}/

Obviamente, as abóboras precisam estar no chão, com um espaço entre elas para não apodrecer.

Os fantasmas, no entanto, gostam de ficar em cima de abóboras, então são ainda mais assustadores . No entanto, eles têm que ficar em duas abóboras, caso contrário, seu peso fantasmagórico esmagará a abóbora por baixo delas. Mas, devido à forma como sua mágica fantasmagórica funciona, vários fantasmas podem empilhar e compartilhar abóboras, desde que os fantasmas sejam divididos igualmente nas abóboras inferiores ou nos fantasmas inferiores. Em outras palavras, formando uma pirâmide humana . Observe que os fantasmas não podem acumular fantasmas a menos que haja uma abóbora por baixo (é assim que a mágica funciona).

Dado dois números inteiros não negativos ge p, representando o número de ghosts e pumpkins, produz a formação mais à esquerda mais compacta possível, seguindo as regras de empilhamento da pirâmide acima. Sobras de abóboras e fantasmas (ou seja, aqueles que não formam a pirâmide) caem no chão à direita.

Para esclarecimento, essas formações estão OK (nova linha em branco separada) e servem como exemplo de E / S:

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

Essas formações não estão 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^))

Entrada

Dois números inteiros não negativos em qualquer formato conveniente . Pelo menos um dos números será diferente de zero. Você pode pegar as entradas em qualquer ordem (ou seja, nos exemplos que eu tinha abóboras primeiro) - especifique como você recebe as entradas na sua resposta.

Resultado

Uma representação em arte ASCII dos fantasmas e abóboras, seguindo as regras acima. Novas linhas iniciais / finais ou outro espaço em branco são opcionais, desde que os fantasmas e as abóboras se alinhem adequadamente.

Regras

  • Um programa completo ou uma função são aceitáveis. Se uma função, você pode retornar a saída em vez de imprimi-la.
  • As brechas padrão são proibidas.
  • Isso é portanto todas as regras usuais de golfe se aplicam e o código mais curto (em bytes) vence.
AdmBorkBork
fonte
Qual é a formação correta para 7 abóboras e 6 fantasmas?
28416 Neil
@ Neil Como as regras pedem a saída mais compacta à esquerda, seria uma pirâmide de 6 fantasmas em cima de 4 abóboras, com mais 3 abóboras à direita. Vou adicioná-lo como um exemplo.
AdmBorkBork 28/10
Bem, seu uso do compacto me confundiu - eu poderia colocar todos os fantasmas na mesma linha, então é mais compacto na vertical!
Neil
As abóboras sempre serão fornecidas antes dos fantasmas?
Gabriel Benamy 28/10
2
Eu gosto que os fantasmas e abóboras estão fazendo uma pirâmide humana #
MayorMonty 28/10

Respostas:

5

JavaScript (ES7), 166 164 159 bytes

Guardado 5 bytes graças a 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):''

Formatado e comentado

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

Matemática subjacente

A parte complicada é descobrir a largura ideal Gda pirâmide fantasma.

O número de fantasmas gem uma pirâmide é dado por:

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

Reciprocamente, a largura de uma pirâmide contendo gfantasmas é a raiz real da equação quadrática resultante:

G² + G - 2g = 0

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

G = (-1 ± √Δ) / 2

O que leva à seguinte raiz real (também conhecida como raiz triangular ):

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

No entanto, a largura da pirâmide também é limitada pelo número de abóboras: não podemos ter mais do que p-1fantasmas sobre as pabóboras. Daí a fórmula final usada no código:

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

Versão ES6, 173 171 166 bytes

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

Casos de teste (ES6)

Arnauld
fonte
1
Eu acho que j=(g+g)**.5+.5|0deveria funcionar.
Neil
Boa explicação!
AdmBorkBork
@ Neil Isso é mais curto e mais confiável. (Meu método teve alguns valores inválidos, começando em g = 5051.) Obrigado.
Arnauld
3

Perl, 246 bytes (as novas linhas não fazem parte do código e são fornecidas apenas para facilitar a leitura)

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

Aceita dois números: abóboras primeiro, seguidas por fantasmas. Entrada de amostra:

5 20

Saída de amostra:

                \{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
fonte
Ah, você leu minhas palavras um pouco diferente do que eu pretendia - fantasmas só podem se acumular em cima de fantasmas se houver uma abóbora por baixo, caso contrário, eles precisam ir para o arquivo único certo. É por isso que o 0p 4gcaso de teste tem todos os fantasmas em uma linha, em vez de empilhados.
AdmBorkBork
@ TimmyD Tudo bem, eu consertei agora. Vou precisar de um pouco de golfe para reduzi-lo.
Gabriel Benamy 28/10