Чаша с водой


19

Вы должны написать программу или функцию, которая получает объем чаши и объем воды в нем в качестве входных данных и выводит или возвращает ASCII-представление чаши с водой в нем с требуемыми объемами.

Чаша имеет следующую структуру:

 \     /
  \___/

Чаша имеет хотя бы одного _персонажа. Количество \'s и /' также положительно, и они равны из-за симметрии.

Объем чаши общее количество _и spaceсимволы между \й и /'s плюсом один для каждой пары \и /. Это означает, что вышеупомянутая миска имеет объем 10:

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

Обратите внимание, что две разные чаши могут иметь одинаковый объем. Например, обе следующие чаши имеют объем 18:

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

Мы можем налить немного воды в миску. Вода представлена ​​в виде ряда ~символов вместо пробелов внутри чаши. В нижнем ряду нет пробелов, поэтому он не может содержать ~символы. Это означает, что наш пример может быть заполнен водой только одним способом:

 \~~~~~/
  \___/

Другие чаши могут быть заполнены несколькими способами:

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

Объем воды в чаше является объем чаши строк ниже в ~символы. Вышеприведенные примеры имеют объемы воды 4, 6 and 2соответственно.

вход

  • Два натуральных числа, объем чаши и объем воды.
  • Вы можете выбрать порядок двух чисел.
  • Два целых числа могут быть введены в любом общем формате списка (список, кортеж, массив и т. Д.) Или в виде двух отдельных целых чисел.
  • Для входных значений гарантируется как минимум одна действительная конфигурация воды в чаше.

Выход

  • ASCII-представление чаши с водой, где объем чаши и воды соответствуют входным данным.
  • Если вы решите вернуть результат вместо печати, он должен быть возвращен в виде одной строки (или ближайшей альтернативы вашего языка).
  • Разрешены любые конечные пробелы.
  • Никакие ненужные начальные пробелы не допускаются.
  • Если имеется несколько правильных конфигураций, вы можете выбрать, какую вы выводите, но вы можете вывести только одну из них.

Примеры

За каждой парой входных целых чисел следуют один или несколько возможных выходов.

6 2
\~~~/
 \_/

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

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

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

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

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

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

Это код гольф, поэтому выигрывает самый короткий вход.

Ответы:


6

CJam, 72 70 69 байт

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

Попробуйте онлайн в интерпретаторе CJam .

Время выполнения и использование памяти O (страшно) , поэтому последние три тестовых случая должны быть проверены с использованием интерпретатора Java (и дополнительного пространства кучи).

Пример запуска

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

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

Как это устроено

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

2

C 231 229 байт

Ранняя подача :) Здесь гораздо больше игры в гольф.

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 */
            }
        }
    }
}

Можно ли встретить чашу, которая соответствует объему чаши, но не может соответствовать объему воды?
Вартан

At least one valid bowl-water configuration is guaranteed for the input values.- ОП
Коул Кэмерон

2

Javascript ES5, 364 байта

Это то, что я мог бы быстро придумать во время моего ланча, помочь мне сыграть в гольф, когда моя смена заканчивается!

Источник

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

Golfed:

(побежал через мини-фильтр для сжатия, обеденная смена закончилась)

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}

2

Perl, 227 172 байта

Запустите с параметром -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}}}}

Спасибо Деннису за помощь в игре в гольф.

Вычисление объема чаши , как высота * (ширина + высота), где ширина количество _символов и высота есть число \символов.

Каждая комбинация высоты и ширины проверяется в паре вложенных петель, пока не будет найден правильный объем чаши, затем выполняется другая петля над возможными уровнями высоты воды, чтобы определить, возможен ли правильный объем воды с этой шириной.

Можно удалить третий цикл, только вычисление уровня воды с использованием квадратичной формулы с, как 1, B в качестве ширины и с в качестве отрицательного требуемого объема воды, и проверок, если это целое число, но это занимает больше байт чем просто делает петлю. Здесь в любом случае (183 байт):

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

2

Python 2, 162 байт

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

Немного грязно, но вот моя первая попытка. Он пробует все возможные номера строк r, устанавливая число базового подчеркивания быть a = V/r-r. Тогда он пробует все возможные высоты уровня воды kи проверяет , если чаша действительно, печать, если так.


1

Python 2.7, 284 270 260 байт

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

Это в основном вычисляет высоту и ширину ковша и воды и печатает их.

Пытался изо всех сил удалить некрасивую часть цикла while в начале (где я вычисляю высоту ведра и высоту, с которой должна вытягиваться вода. Сейчас все строки в коде, кроме последней, предназначены для вычисления ширины и высота). Все еще пытаюсь: P

Тестирование для разных случаев -

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

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

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

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

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

(102, 42)
\                     /
 \                   /
  \~~~~~~~~~~~~~~~~~/
   \               /
    \             /
     \___________/
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.