Mangkuk Diisi dengan Air

19

Anda harus menulis program atau fungsi yang menerima volume mangkuk dan volume air di dalamnya sebagai input dan output atau mengembalikan representasi ASCII mangkuk dengan air di dalamnya dengan volume yang diinginkan.

Mangkuk memiliki struktur sebagai berikut:

 \     /
  \___/

Mangkuk memiliki setidaknya satu _karakter. Hitungan \'s dan/ ' juga positif dan mereka sama karena simetri.

Volume mangkuk adalah jumlah total _dan spacekarakter antara \'s dan /ditambah satu untuk setiap pasangan \dan /. Ini berarti mangkuk di atas memiliki volume 10:

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

Perhatikan bahwa dua mangkuk yang berbeda dapat memiliki volume yang sama. Misalnya kedua mangkuk berikut memiliki volume 18:

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

Kita bisa menuangkan air ke dalam mangkuk. Air direpresentasikan sebagai deretan ~karakter, bukan spasi di dalam mangkuk. Baris bawah tidak memiliki spasi sehingga tidak dapat berisi ~'s. Ini berarti contoh kita dapat diisi dengan air hanya dengan satu cara:

 \~~~~~/
  \___/

Mangkuk lain dapat diisi dengan berbagai cara:

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

Volume air dalam mangkuk adalah volume baris mangkuk bawah ini ~karakter. Contoh di atas memiliki volume air 4, 6 and 2masing - masing.

Memasukkan

  • Dua bilangan bulat positif, volume mangkuk dan volume air.
  • Anda dapat memilih urutan dua angka.
  • Dua bilangan bulat dapat dimasukkan dalam format daftar umum apa saja (daftar, tupel, array, dll.) Atau sebagai dua bilangan bulat terpisah.
  • Setidaknya satu konfigurasi mangkuk-air yang valid dijamin untuk nilai input.

Keluaran

  • Representasi ASCII dari mangkuk dengan air di mana mangkuk dan volume air cocok dengan input.
  • Jika Anda memilih untuk mengembalikan hasil alih-alih mencetak, hasilnya harus dikembalikan sebagai string tunggal (atau alternatif terdekat bahasa Anda).
  • Setiap spasi spasi tambahan diperbolehkan.
  • Tidak ada spasi putih terkemuka yang tidak perlu diizinkan.
  • Jika ada beberapa konfigurasi yang benar, Anda bebas untuk memilih mana yang Anda hasilkan tetapi Anda hanya bisa menampilkan salah satunya.

Contohnya

Setiap pasangan integer input diikuti oleh satu atau lebih output yang mungkin.

6 2
\~~~/
 \_/

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

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

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

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

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

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

Ini kode golf sehingga entri terpendek menang.

randomra
sumber

Jawaban:

6

CJam, 72 70 69 byte

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

Cobalah online di juru bahasa CJam .

Run time dan penggunaan memori adalah O (menakutkan) , jadi tiga kasus uji terakhir harus diverifikasi menggunakan Java interpreter (dan ruang heap tambahan).

Contoh dijalankan

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

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

Bagaimana itu bekerja

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

C, 231 229 byte

Pengiriman awal :) Ada banyak lagi golf yang bisa dilakukan di sini.

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

Tidak Disatukan:

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
sumber
Apakah mungkin menemukan mangkuk yang cocok dengan volume mangkuk tetapi tidak dapat memenuhi volume air?
Vartan
At least one valid bowl-water configuration is guaranteed for the input values.- OP
Cole Cameron
2

Javascript ES5, 364 byte

Inilah yang bisa saya dapatkan dengan cepat selama makan siang, bantu saya mainkan golf saat shift saya berakhir!

Sumber

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

Golf:

(dijalankan melalui minifier untuk kompres, shift makan siang berakhir)

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

Perl, 227 172 byte

Jalankan dengan opsi -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}}}}

Terima kasih kepada Dennis untuk bantuan bermain golf ini.

Menghitung volume mangkuk sebagai tinggi * (lebar + tinggi), di mana lebar adalah jumlah _karakter dan tinggi adalah jumlah \karakter.

Setiap kombinasi tinggi dan lebar diuji dalam sepasang loop bersarang sampai volume mangkuk yang benar ditemukan, kemudian dilakukan pengulangan terhadap level ketinggian air yang mungkin dilakukan untuk mengetahui apakah volume air yang benar dimungkinkan dengan lebar tersebut.

Dimungkinkan untuk menghapus loop ketiga dengan hanya menghitung ketinggian air menggunakan rumus kuadratik dengan 1, b sebagai lebar dan c sebagai negatif dari volume air yang diinginkan, dan memeriksa apakah itu bilangan bulat, tetapi itu membutuhkan lebih banyak byte dari sekedar melakukan satu putaran. Ini dia (183 byte):

/ /;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
sumber
2

Python 2, 162 byte

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

Agak berantakan, tapi ini usaha pertamaku. Ia mencoba semua kemungkinan jumlah baris r, mengatur jumlah garis bawah dasar menjadi a = V/r-r. Kemudian ia mencoba semua ketinggian permukaan air yang mungkin kdan memeriksa apakah mangkuk itu valid, mencetaknya jika demikian.

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

Ini pada dasarnya menghitung tinggi dan lebar ember dan air dan mencetaknya.

Berusaha keras untuk menghapus bagian loop sementara jelek di awal (di mana saya menghitung ketinggian ember dan ketinggian dari mana air harus diambil. Saat ini, semua baris dalam kode kecuali untuk yang terakhir adalah untuk menghitung lebar dan tinggi). Masih mencoba: P

Mengujinya untuk berbagai kasus -

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

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

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

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

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

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