Cuenco lleno de agua

19

Debería escribir un programa o función que reciba el volumen de un tazón y el volumen del agua en él como entrada y salidas o devuelva una representación ASCII de un tazón con agua con los volúmenes deseados.

Un cuenco tiene la siguiente estructura:

 \     /
  \___/

El cuenco tiene al menos un _personaje. El recuento de \'sy /' s también es positivo y es igual debido a la simetría.

El volumen del recipiente es el número total de _y spacecaracteres entre los \'s y /' s más uno por cada par de \y /. Esto significa que el tazón anterior tiene el volumen de 10:

 \     /  =>  xxxxx x (the last one is for the \/ pair)
  \___/        xxx x (the last one is for the \/ pair)

Tenga en cuenta que dos tazones diferentes podrían tener el mismo volumen. Por ejemplo, los dos cuencos siguientes tienen un volumen de 18:

\       /
 \     /      \         /
  \___/        \_______/

Podemos verter un poco de agua en el tazón. El agua se representa como una fila de ~caracteres en lugar de espacios dentro del recipiente. La fila inferior no tiene espacios, por lo que no puede contener los ~'s. Esto significa que nuestro ejemplo se puede llenar con agua de una sola manera:

 \~~~~~/
  \___/

Otros cuencos se pueden llenar de múltiples maneras:

 \~~~~~/   \     /
  \   /     \~~~/
   \_/       \_/

El volumen del agua en un recipiente es el volumen de las filas del recipiente debajo de los ~caracteres. Los ejemplos anteriores tienen volúmenes de agua de 4, 6 and 2respectivamente.

Entrada

  • Dos enteros positivos, el volumen del cuenco y el volumen del agua.
  • Puedes elegir el orden de los dos números.
  • Los dos enteros se pueden ingresar en cualquier formato de lista común (lista, tupla, matriz, etc.) o como dos enteros separados.
  • Se garantiza al menos una configuración válida de cuenco-agua para los valores de entrada.

Salida

  • La representación ASCII de un recipiente con agua donde el volumen del recipiente y el agua coinciden con la entrada.
  • Si elige devolver el resultado en lugar de imprimirlo, debe devolverse como una sola cadena (o la alternativa más cercana a su idioma).
  • Se permite cualquier espacio en blanco al final.
  • No se permiten espacios en blanco iniciales innecesarios.
  • Si hay múltiples configuraciones correctas, usted es libre de elegir cuál generar, pero solo puede generar una de ellas.

Ejemplos

Cada par entero de entrada es seguido por una o más salidas posibles.

6 2
\~~~/
 \_/

10 4
\~~~~~/
 \___/

24 8
\        /
 \~~~~~~/
  \    /
   \__/

42 12 //either of the two output is correct
\           /
 \         /
  \~~~~~~~/
   \     /
    \   /
     \_/

\               /
 \~~~~~~~~~~~~~/
  \___________/

90 68
\~~~~~~~~~~~~~~~~~~~~~/
 \                   /
  \                 /
   \               /
    \_____________/

102 42
\                     /
 \                   /
  \~~~~~~~~~~~~~~~~~/
   \               /
    \             /
     \___________/

Este es el código de golf, por lo que gana la entrada más corta.

randomra
fuente

Respuestas:

6

CJam, 72 70 69 bytes

q~:QW=3m*{:,2ff*),)ff+}%{::)1fbQ=}=~W%ee_,S*W'_t@,~'~t.{S\+.*"\/".+N}

Pruébelo en línea en el intérprete de CJam .

El tiempo de ejecución y el uso de memoria son O (aterrador) , por lo que los últimos tres casos de prueba deben verificarse utilizando el intérprete de Java (y espacio de almacenamiento dinámico adicional).

Ejecución de ejemplo

$ time java -Xmx4G -jar cjam-0.6.5.jar bowl.cjam <<< '[42 102]'
\                     /
 \                   /
  \~~~~~~~~~~~~~~~~~/
   \               /
    \             /
     \___________/

real    0m40.669s
user    3m13.100s
sys     0m11.690s

Cómo funciona

q~:Q     e# Read from STIDN, evaluate and save the result in Q.
W=       e# Select the last element of Q (bowl volume B).
3m*      e# Push all vectors of {0,...,B-1} × {0,...,B-1} x {0,...,B-1}.

{        e# For each vector [X Y Z]:
  :,     e#   Push [[0 1 ... X-1] [0 1 ... Y-1] [0 1 ... Z-1]].
  2ff*   e#   Multiply each coordinate by 2.
  ),)    e#   Pop the last vector, compute its length and increment.
  ff+    e#   Add the result to each component of each vector.
}%       e# Result: [[Z Z+2 ... Z+2(X-1)] [Z Z+2 ... Z+2(Y-1)]]

{        e# Find:
  ::)    e#   Increment each coordinate (to account for the volume in "\/").
  1fb    e#   Sum the coordinate of both vectors.
  Q=     e#   Compare the result to Q (desired volumes).
}=       e# If they match, push the array and break.

~        e# Dump both vectors on the stack.
W%       e# Reverse the rightmost one (corresponds to the bowl volume).
ee       e# Enumerate its coordinates.
         e# [Z+2(Y-1) ... Z+2 Z] -> [[0 Z+2(Y-1)] ... [Y-2 Z+2] [Y-1 Z]].
_,S*     e# Compute the length (Y) and push a string of Y spaces.
W'_t     e# Replace the last space with an underscore.
@        e# Rotate the leftmost vector (corresponds to the water volume) on top.
,        e# Compute its length (X).
~'~t     e# Replace the space at index X from the right with a tilde.

.{       e# For each enumerates coordinate and the corresponding character:
  S\+    e#   Append the character to the string " ".
  .*     e#   Vectorized repetition: [1 2] " ~" -> [" " "~~"]
  "\/".+ e#   Append the first (second) solidus to the first (second) string.
  N      e#   Push a linefeed.
}
Dennis
fuente
2

C, 231 229 bytes

Presentación temprana :) Hay mucho más golf para hacer aquí.

v,V,w,h,H,i,j;main(c,a)char**a;{V=atoi(a[1]);v=atoi(a[2]);for(;++H;)for(h=0;h++<H;){for(w=1;h*h+w*h-h<v;++w);if(H*H+w*H-H==V){for(;H--;){printf("%*s",++i,"\\");for(j=0;j++<w-1+2*H;)putchar(H?H==h?'~':32:95);puts("/");}exit(0);}}}

Sin golf:

int v,V,w,h,H,i,j;
int main(int c, char **a)
{
    V=atoi(a[1]); /* Volume of bowl */
    v=atoi(a[2]); /* Volume of water */

    for(;++H;) /* Make the bowl taller */
    {
        for(h=0;h++<H;) /* Make the water taller */
        {
            for(w=1;h*h+w*h-h<v;++w); /* Make the bowl wider until the water volume matches */
            if(H*H+w*H-H==V) /* if the bowl volume matches, then we're good */
            {
                for(;H--;) /* Print out the bowl, one line at a time */
                {
                    printf("%*s",++i,"\\"); /* Print the left edge */
                    /* Print the inside (either with air/water, the top of the water, or the bottom of the bowl */
                    for(j=0;j++<w-1+2*H;)
                        putchar(H?H==h?'~':32:95);
                    /* Print the right edge of the bowl */
                    puts("/");
                }
                exit(0); /* die, we're done */
            }
        }
    }
}
Cole Cameron
fuente
¿Es posible encontrar un tazón que coincida con el volumen del tazón pero no puede alcanzar un volumen de agua?
Vartan
At least one valid bowl-water configuration is guaranteed for the input values.- OP
Cole Cameron
2

Javascript ES5, 364 bytes

Esto es lo que podría pensar rápidamente durante mi almuerzo, ¡ayúdame a jugar golf mientras termina mi turno!

Fuente

function V(x,v) { // calculate volume of bowl/water
    for(i=v,j=x;i--;j+=2) {
      v+=j; 
    }
    return v
}
function B(x,y,l) { // draw bowl/water
    for(s="",h=y,w = x+2*y;y--;s+="\n")
        for(i=w;i--;) {
            f= i>h-y-1 && w-i > h-y;
            s+=i==h-y-1?"/": 
                w-i == h-y? "\\":
                y==l-1 && f? "~" :
                !y && f?"_":" "
        }
    return s;
}
n=prompt().split(" ");
b=+n[0]; // bowl volume
w=+n[1]; // water volume
for(x=b;x;x--)  // loop through possible widths
  for(y=b;y;y--)  // loop through possible heights
    if(V(x,y)==b) // check if we found bowl volume
       for(y2=y;y2;y2--) { // check possible water heights
         v = V(x,y2-1);
         if(v==w){ // see if volume matches
          alert(B(x,y,y2));
          x=1;break;
         }
       }

Golfizado:

(pasó por el minificador para comprimir, terminó el turno de almuerzo)

function V(f,r){for(i=r,j=f;i--;j+=2)r+=j;return r}function B(r,y,n){for(s="",h=y,w=r+2*y;y--;s+="\n")for(i=w;i--;)f=i>h-y-1&&w-i>h-y,s+=i==h-y-1?"/":w-i==h-y?"\\":y==n-1&&f?"~":!y&&f?"_":" ";return s}for(n=prompt().split(" "),b=+n[0],w=+n[1],x=b;x;x--)for(y=b;y;y--)if(V(x,y)==b)for(y2=y;y2;y2--)if(v=V(x,y2-1),v==w){alert(B(x,y,y2)),x=1;break}
Vartan
fuente
2

Perl, 227 172 bytes

Ejecutar con la opción -n:

/ /;for$h(1..$`){for$w(1..$`){for$l(1..($h*($w+$h)==$`)*$h){if($l*($w+$l)==$'){for(0..$h-1){print$"x$_."\\".($_<$h-1?$_==$h-$l-1?"~":$":"_")x($w+($h-$_-1)*2)."/
"}exit}}}}

Gracias a Dennis por ayudarme a jugar golf.

Calcula el volumen del bol como altura * (ancho + alto), donde ancho es el número de _caracteres y alto es el número de \caracteres.

Cada combinación de altura y ancho se prueba en un par de bucles anidados hasta que se encuentra el volumen correcto del recipiente, luego se realiza otro bucle sobre los posibles niveles de altura del agua para determinar si es posible un volumen de agua correcto con ese ancho.

Es posible eliminar el tercer bucle simplemente calculando el nivel del agua usando la fórmula cuadrática con a como 1, b como el ancho yc como el negativo del volumen de agua deseado, y verificando si es un número entero, pero eso requiere más bytes que solo hacer un bucle. Aquí está de todos modos (183 bytes):

/ /;for$h(1..$`){for$w(1..$`){if($h*($w+$h)==$`){$l=(sqrt($w*$w+4*$')-$w)/2;if(int$l==$l){for(0..$h-1){print$"x$_."\\".($_<$h-1?$_==$h-$l-1?"~":$":"_")x($w+($h-$_-1)*2)."/
"}exit}}}}
samgak
fuente
2

Python 2, 162 bytes

V,W=input()
r=1
while r*r<V:a=V/r-r;k=1;exec"if(a+k)*k==W*(V%r<1):i=1;exec\"print' '*~-i+'\%s/'%(' _~'[(i==r)-(i==r-k)]*(a+2*(r-i)));i+=1;\"*r;r=V\nk+=1\n"*r;r+=1

Un poco desordenado, pero aquí está mi primer intento. Intenta todos los números posibles de filas r, configurando el número de guiones bajos básicos como a = V/r-r. Luego prueba todas las alturas posibles del nivel del agua ky comprueba si el recipiente es válido, imprimiéndolo si es así.

Sp3000
fuente
1

Python 2.7, 284 270 260 bytes

def f(b,w,i=1,e='while s<%s:j+=2;s+=j'):
 while 1:
    i+=1;j=s=i;exec e%w
    if s==w:p=j;exec e%b
    if s==b:break
 h=(j-i)/2+1;t=w=i+(h-1)*2+1
 for j in range(h):r,s,t=((' '*(t-2),'_'*(i-1))[j==h-1],'~'*(t-2))[j==h-(p-i)/2-2],(w-t)/2,t-2;print" "*s+"\\"+r+"/"+" "*s

Básicamente, esto calcula la altura y el ancho del balde y el agua y los imprime.

Intenté eliminar la parte fea del bucle mientras comenzaba (donde calculo la altura del balde y la altura desde donde se debe extraer el agua. En este momento, todas las líneas del código, excepto la última, son para calcular el ancho y altura). Todavía lo intento: P

Probándolo para diferentes casos -

>>> execfile("buckets.py")
(6, 2)
\~~~/
 \_/

(10, 4)
\~~~~~/
 \___/

(24, 8)
\        /
 \~~~~~~/
  \    /
   \__/

(42, 12)
\           /
 \         /
  \~~~~~~~/
   \     /
    \   /
     \_/

(90, 68)
\~~~~~~~~~~~~~~~~~~~~~/
 \                   /
  \                 /
   \               /
    \_____________/

(102, 42)
\                     /
 \                   /
  \~~~~~~~~~~~~~~~~~/
   \               /
    \             /
     \___________/
Kamehameha
fuente