Tigela cheia de água

19

Você deve escrever um programa ou função que receba o volume de uma tigela e o volume de água nela como entrada e saída ou retorne uma representação ASCII de uma tigela com água nos volumes desejados.

Uma tigela tem a seguinte estrutura:

 \     /
  \___/

A tigela tem pelo menos um _caractere. A contagem de \'s' e /'s também é positiva e é igual devido à simetria.

O volume da tigela é o número total de caracteres _e spaceentre os \'s /' e mais um para cada par de \e /. Isso significa que a tigela acima tem o volume de 10:

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

Observe que duas taças diferentes podem ter o mesmo volume. Por exemplo, as duas tigelas a seguir têm um volume de 18:

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

Podemos derramar um pouco de água na tigela. A água é representada como uma linha de ~caracteres em vez de espaços dentro da tigela. A linha inferior não tem espaços, portanto não pode conter os ~. Isso significa que nosso exemplo pode ser preenchido com água de apenas uma maneira:

 \~~~~~/
  \___/

Outras tigelas podem ser preenchidas de várias maneiras:

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

O volume da água em uma tigela é o volume das linhas da tigela abaixo dos ~caracteres. Os exemplos acima têm volumes de água 4, 6 and 2respectivamente.

Entrada

  • Dois números inteiros positivos, o volume da tigela e o volume da água.
  • Você pode escolher a ordem dos dois números.
  • Os dois números inteiros podem ser inseridos em qualquer formato de lista comum (lista, tupla, matriz etc.) ou como dois números inteiros separados.
  • Pelo menos uma configuração válida de água da bacia é garantida para os valores de entrada.

Resultado

  • A representação ASCII de uma tigela com água, onde os volumes da tigela e da água correspondem à entrada.
  • Se você optar por retornar o resultado em vez de imprimir, ele deverá ser retornado como sequência única (ou a alternativa mais próxima do seu idioma).
  • Qualquer espaço em branco à direita é permitido.
  • Nenhum espaço em branco inicial desnecessário é permitido.
  • Se houver várias configurações corretas, você poderá escolher qual delas será a sua, mas somente uma delas.

Exemplos

Cada par inteiro de entrada é seguido por uma ou mais saídas possíveis.

6 2
\~~~/
 \_/

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

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

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

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

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

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

Este é um código de golfe, portanto a entrada mais curta vence.

randomra
fonte

Respostas:

6

CJam, 72 70 69 bytes

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

Experimente on-line no intérprete CJam .

O tempo de execução e o uso da memória são O (assustadores) , portanto, os três últimos casos de teste devem ser verificados usando o interpretador Java (e espaço extra na pilha).

Exemplo de execução

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

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

Como 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
fonte
2

C, 231 229 bytes

Envio antecipado :) Há muito mais golfe para fazer aqui.

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);}}}

Ungolfed:

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
fonte
É possível encontrar uma tigela que corresponda ao volume da tigela, mas que não possa encontrar um volume de água?
Vartan 30/07
At least one valid bowl-water configuration is guaranteed for the input values.- OP
Cole Cameron
2

Javascript ES5, 364 bytes

Isto é o que eu poderia criar rapidamente durante o meu almoço, me ajudar a jogar golfe enquanto meu turno termina!

Fonte

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;
         }
       }

Golfe:

(percorreu o minifier para comprimir, o turno do almoço terminou)

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
fonte
2

Perl, 227 172 bytes

Execute com a opção -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}}}}

Agradeço ao Dennis por ajudar a resolver isso.

Calcula o volume da tigela como altura * (largura + altura), em que largura é o número de _caracteres e altura é o número de \caracteres.

Cada combinação de altura e largura é testada em um par de loops aninhados até que o volume correto do recipiente seja encontrado; em seguida, outro loop sobre os possíveis níveis de altura da água é feito para descobrir se é possível um volume correto de água com essa largura.

É possível remover o terceiro loop apenas calculando o nível de água usando a fórmula quadrática com a como 1, b como a largura ec como negativo do volume de água desejado e verificando se é um número inteiro, mas que consome mais bytes do que apenas fazer um loop. Aqui está assim mesmo (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
fonte
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

Um pouco bagunçado, mas aqui está minha primeira tentativa. Ele tenta todos os números possíveis de linhas r, configurando o número de sublinhados base a = V/r-r. Depois, tenta todas as alturas possíveis do nível da água ke verifica se a tigela é válida, imprimindo-a se for o caso.

Sp3000
fonte
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

Isso basicamente calcula a altura e a largura do balde e da água e as imprime.

Tentei remover a parte feia do loop while no início (em que eu calculo a altura do balde e a altura de onde a água deve ser retirada. No momento, todas as linhas do código, exceto a última, destinam-se ao cálculo da largura e altura). Ainda tentando: P

Testando para casos diferentes -

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

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

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

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

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

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