Fantasmas y calabazas

15

Aquí hay una calabaza ASCII tallada en una Jack-o-Lantern. ¿No es lindo?

((^v^))

Aquí hay un fantasma ASCII. ¡Mira qué espeluznante es!

\{O.O}/

Obviamente, las calabazas tienen que estar en el suelo, con un espacio entre ellas para que no se pudran.

Sin embargo, a los fantasmas les gusta estar encima de las calabazas, por lo que son aún más espeluznantes . Sin embargo, tienen que pararse sobre dos calabazas, de lo contrario su peso fantasmal aplastará la calabaza debajo de ellos. Pero, debido a cómo funciona su magia fantasmal , varios fantasmas pueden apilar y compartir calabazas, siempre que los fantasmas se dividan de manera uniforme en las calabazas inferiores o en los fantasmas inferiores. En otras palabras, formando una forma como una pirámide humana . Tenga en cuenta que los fantasmas no pueden acumularse en fantasmas a menos que haya una calabaza debajo (así es como funciona la magia).

Dados dos enteros no negativos gy p, representando el número de ghosts y pumpkins, genera la formación más compacta más a la izquierda posible, siguiendo las reglas de apilamiento de la pirámide anteriores. Las sobras de calabazas y fantasmas (es decir, aquellos que no forman la pirámide) van al suelo a la derecha.

Para aclarar, estas formaciones están bien (nueva línea en blanco separada) y sirven como ejemplo 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^))

Estas formaciones no están bien

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

Dos enteros no negativos en cualquier formato conveniente . Al menos uno de los números será distinto de cero. Puede tomar las entradas en cualquier orden (es decir, en los ejemplos que tuve primero con calabazas); especifique cómo toma las entradas en su respuesta.

Salida

Una representación de arte ASCII de los fantasmas y calabazas, siguiendo las reglas anteriores. Las nuevas líneas iniciales / finales u otros espacios en blanco son opcionales, siempre que los fantasmas y las calabazas se alineen adecuadamente.

Reglas

  • Un programa completo o una función son aceptables. Si es una función, puede devolver el resultado en lugar de imprimirlo.
  • Las lagunas estándar están prohibidas.
  • Este es el por lo que se aplican todas las reglas habituales de golf, y gana el código más corto (en bytes).
AdmBorkBork
fuente
¿Cuál es la formación correcta para 7 calabazas y 6 fantasmas?
Neil
@Neil Dado que las reglas solicitan la salida más compacta más a la izquierda, sería una pirámide de 6 fantasmas sobre 4 calabazas, con 3 calabazas adicionales a la derecha. Lo agregaré como ejemplo.
AdmBorkBork
Bueno, su uso de compacto me confundió: podría poner a todos los fantasmas en la misma fila, ¡así que es más compacto verticalmente!
Neil
¿Siempre se proporcionarán calabazas antes que los fantasmas?
Gabriel Benamy
2
Me gusta que los fantasmas y las calabazas estén haciendo una pirámide humana
MayorMonty

Respuestas:

5

JavaScript (ES7), 166 164 159 bytes

Guardado 5 bytes gracias 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):''

Formateado y 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 subyacente

La parte difícil es encontrar el ancho óptimo Gde la pirámide fantasma.

El número de fantasmas gen tal pirámide viene dado por:

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

Recíprocamente, el ancho de una pirámide que contiene gfantasmas es la raíz real de la ecuación cuadrática resultante:

G² + G - 2g = 0

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

G = (-1 ± √Δ) / 2

Lo que conduce a la siguiente raíz real (también conocida como raíz triangular ):

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

Sin embargo, el ancho de la pirámide también está limitado por la cantidad de calabazas: no podemos tener más de p-1 fantasmas sobre pcalabazas. De ahí la fórmula final utilizada en el código:

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

Versión 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 prueba (ES6)

Arnauld
fuente
1
Creo que j=(g+g)**.5+.5|0debería funcionar.
Neil
Buena explicación!
AdmBorkBork
@Neil Esto es más corto y más confiable. (Mi método tenía algunos valores no válidos, comenzando en g = 5051.) Gracias.
Arnauld
3

Perl, 246 bytes (las líneas nuevas no son parte del código y se proporcionan únicamente para facilitar la lectura)

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

Acepta dos números: primero las calabazas, seguidas de los fantasmas. Entrada de muestra:

5 20

Salida de muestra:

                \{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
fuente
Oh, leíste mi redacción un poco diferente de lo que pretendía: los fantasmas solo pueden apilarse encima de los fantasmas si hay una calabaza debajo, de lo contrario, deben ir al archivo único correcto. Es por eso que el 0p 4gcaso de prueba tiene todos los fantasmas en una línea, en lugar de apilados.
AdmBorkBork
@TimmyD Muy bien, lo arreglé ahora. Aunque tendré que hacer un poco de golf para reducirlo.
Gabriel Benamy