Schüssel mit Wasser gefüllt


19

Sie sollten ein Programm oder eine Funktion schreiben, die das Volumen einer Schüssel und das Volumen des Wassers als Ein- und Ausgabe empfängt oder eine ASCII-Darstellung einer Schüssel mit Wasser mit den gewünschten Volumina zurückgibt.

Eine Schüssel hat folgende Struktur:

 \     /
  \___/

Die Schüssel hat mindestens einen _Charakter. Die Anzahl von \'s und /' s ist ebenfalls positiv und sie sind aufgrund der Symmetrie gleich.

Das Volumen der Schüssel ist die Gesamtzahl _und die spaceZeichen zwischen \'s und /' s plus eins für jedes Paar von \und /. Dies bedeutet, dass die obige Schüssel das Volumen von 10:

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

Beachten Sie, dass zwei verschiedene Schalen das gleiche Volumen haben können. ZB haben beide folgenden Schalen ein Volumen von 18:

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

Wir können etwas Wasser in die Schüssel gießen. Das Wasser wird als eine Reihe von ~Zeichen anstelle von Leerzeichen in der Schüssel dargestellt. Die unterste Zeile enthält keine Leerzeichen und darf daher keine ~s enthalten. Dies bedeutet, dass unser Beispiel nur auf eine Weise mit Wasser gefüllt werden kann:

 \~~~~~/
  \___/

Andere Schalen können auf verschiedene Arten gefüllt werden:

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

Das Volumen des Wassers in einer Schüssel ist das Volumen der Schüsselreihen unter den ~Zeichen. Die obigen Beispiele haben jeweils ein Wasservolumen von 4, 6 and 2.

Eingang

  • Zwei positive ganze Zahlen, das Volumen der Schüssel und das Volumen des Wassers.
  • Sie können die Reihenfolge der beiden Zahlen wählen.
  • Die zwei Ganzzahlen können in jedem gängigen Listenformat (Liste, Tupel, Array usw.) oder als zwei separate Ganzzahlen eingegeben werden.
  • Für die Eingabewerte ist mindestens eine gültige Schüsselwasserkonfiguration garantiert.

Ausgabe

  • Die ASCII-Darstellung einer Schüssel mit Wasser, wobei Schüssel und Wasservolumen mit der Eingabe übereinstimmen.
  • Wenn Sie das Ergebnis zurückgeben möchten, anstatt es zu drucken, sollte es als einzelne Zeichenfolge (oder als die nächstliegende Alternative Ihrer Sprache) zurückgegeben werden.
  • Jedes nachfolgende Leerzeichen ist zulässig.
  • Es ist kein unnötiges führendes Leerzeichen zulässig.
  • Wenn es mehrere richtige Konfigurationen gibt, können Sie frei wählen, welche Sie ausgeben, aber Sie können nur eine davon ausgeben.

Beispiele

Jedem ganzzahligen Eingangspaar folgen ein oder mehrere mögliche Ausgänge.

6 2
\~~~/
 \_/

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

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

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

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

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

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

Dies ist Codegolf, also gewinnt der kürzeste Eintrag.

Antworten:


6

CJam, 72 70 69 Bytes

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

Probieren Sie es online im CJam-Interpreter aus .

Die Laufzeit und die Speichernutzung sind O (beängstigend) , daher sollten die letzten drei Testfälle mit dem Java-Interpreter (und zusätzlichem Heap-Speicherplatz) überprüft werden.

Beispiellauf

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

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

Wie es funktioniert

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 Bytes

Frühe Einreichung :) Hier gibt es noch viel mehr zu golfen.

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

Ist es möglich, auf eine Schüssel zu stoßen, die dem Schüsselvolumen entspricht, jedoch kein Wasservolumen aufweist?
Vartan,

At least one valid bowl-water configuration is guaranteed for the input values.- OP
Cole Cameron

2

Javascript ES5, 364 Bytes

Das ist es, was ich mir während des Mittagessens schnell einfallen lassen könnte, hilf mir beim Golfspielen, während meine Schicht endet!

Quelle

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 gespielt:

(Minifier zum Komprimieren durchlaufen, Mittagsschicht beendet)

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 Bytes

Führen Sie mit der Option -n aus:

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

Vielen Dank an Dennis für die Hilfe beim Golfspielen.

Berechnet das Schüsselvolumen als Höhe * (Breite + Höhe), wobei Breite die Anzahl der _Zeichen und Höhe die Anzahl der \Zeichen ist.

Jede Kombination von Höhe und Breite wird in einem Paar verschachtelter Schleifen getestet, bis das richtige Schüsselvolumen gefunden ist. Anschließend wird eine weitere Schleife über mögliche Wasserhöhenniveaus durchgeführt, um festzustellen, ob mit dieser Breite das richtige Wasservolumen möglich ist.

Sie können die dritte Schleife entfernen, indem Sie einfach den Wasserstand mithilfe der quadratischen Formel mit a als 1, b als Breite und c als Negativ des gewünschten Wasservolumens berechnen und überprüfen, ob es sich um eine Ganzzahl handelt. Dies erfordert jedoch mehr Bytes als nur eine Schleife zu machen. Hier ist es trotzdem (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}}}}

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

Ein bisschen chaotisch, aber hier ist mein erster Versuch. Es wird versucht, alle möglichen Zeilenzahlen anzugeben r, wobei die Anzahl der Basisunterstriche festgelegt wird a = V/r-r. Dann probiert es alle möglichen Wasserstandshöhen aus kund prüft, ob die Schüssel gültig ist, und druckt sie gegebenenfalls aus.


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

Dies berechnet im Grunde die Höhe und Breite des Eimers und des Wassers und druckt sie aus.

Es wurde versucht, den hässlichen Teil der while-Schleife am Anfang zu entfernen (wobei ich die Höhe des Eimers und die Höhe, aus der Wasser gezogen werden soll, berechne. Zur Zeit dienen alle Linien im Code mit Ausnahme der letzten zur Berechnung der Breite und Höhe). Versuchen Sie immer noch: P

Testen Sie es für verschiedene Fälle -

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

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

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

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

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

(102, 42)
\                     /
 \                   /
  \~~~~~~~~~~~~~~~~~/
   \               /
    \             /
     \___________/
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.