ASCII-Wasserwerk


19

Intro

Betrachten Sie ein Raster der Zeichen f A\/wie

f  f  f  
      A  
   A / \ 
\ /     A
    A \/ 
   /     
 \/         

woher:

  • f stellt einen Wasserhahn dar, der einen Wasserstrahl nach unten gießt
  • A teilt den Wasserstrom oben auf, so dass genau die Hälfte nach links und genau die Hälfte nach rechts geht
  • \ verschiebt den Wasserstrom um eine Einheit nach oben rechts
  • / verschiebt den Wasserstrom um eine Einheit nach oben links
  • Die Kombination \/erzeugt einen Trog mit unendlicher Kapazität, der die darüber fließenden Wasserströme sammelt
  • [space] ist ein leerer Raum, durch den sich das Wasser bewegen kann

Daraus können wir uns den Weg vorstellen, den das Wasser ( *) nehmen würde, wenn es aus den Wasserhähnen kommt und entweder in die Tröge oder aus dem Gitterbereich fällt:

f  f  f    <-- first second and third faucets
*  * *A* 
* *A*/ \*
\*/ *  *A  <-- a '*' is not drawn to the right of this A because it would be out of the 9×7 bounds
 * *A*\/   <-- upper trough
 **/ *   
 \/  *     <-- lower trough

Angenommen, die 3 Wasserhähne geben nacheinander die gleiche Menge Wasser ab, dann können wir das sehen

  • Das gesamte Wasser des ersten Wasserhahns fließt in den unteren Trog.
  • Eine Hälfte des Wassers des zweiten Wasserhahns fließt in den unteren Trog und die andere Hälfte wird zwischen dem unteren Trog und dem Abfallen vom Gitter aufgeteilt.
  • Ein Viertel des Wassers des dritten Wasserhahns fließt in den unteren Trog, ein Viertel fällt vom Boden des Gitters ab, ein Viertel fließt in den oberen Trog und ein Viertel fällt rechts vom Gitter ab.

Daran können wir erkennen, dass (1 + 3/4 + 1/4 + 1/4) / 3 = 75%das Wasser von den Trögen aufgefangen wird und (1/4 + 1/4 + 1/4) / 3 = 25%vom Gitter fällt.

Herausforderungen

Sie können einige oder alle dieser Herausforderungen im Zusammenhang mit dieser ASCII-Wasserflusskonfiguration abschließen. Sie sind alle Code-Golf, die kürzeste Antwort für jede Herausforderung ist der Gewinner. Die akzeptierte Antwort ist die Person, die die meisten Herausforderungen mit der Gesamtcodelänge als Unentschieden meistert.

Herausforderung 1
Schreiben Sie ein Programm, das den Anteil des Wassers ausgibt, der für ein bestimmtes Gitter in Tröge fließt. Die Ausgabe des obigen Beispiels wäre einfach 0.75.

Herausforderung 2
Schreiben Sie ein Programm, das *anhand eines Rasters die Stellen zeichnet , an denen das Wasser fließt, wie oben beschrieben. Sie sollten nichts außer Leerzeichen überschreiben, und das Raster sollte die Größe nicht ändern. Also für sowas

 f
/A

Es muss nichts getan werden, da, obwohl Wasser auf beiden Seiten des A fließt, es nicht nach links gezogen werden kann, ohne das A zu entfernen, /und es nicht nach rechts gezogen werden kann, ohne das 2 × 2-Gitter zu vergrößern.

Herausforderung 3 (aktualisiert)
Schreiben Sie ein Programm, das zwei nicht-negative ganze Zahlen, die Summe T und die Menge, um K zu behalten, enthält (T> = K). Erzeugen und zeichnen Sie ein Gitter mit genau einem fsolchen, dass genau K in Tröge fließt, wenn dieser Wasserhahn T Wassereinheiten ausgießt. Wenn dies in einem endlichen Gitter für ein bestimmtes (T, K) Paar nicht möglich ist, geben Sie 'Impossible' aus.

Klarstellungen (gelten für alle Herausforderungen)

  • Die Eingabe kann über stdin, eine Datei oder sogar einen Funktionsaufruf in der Zeichenfolgendarstellung des Rasters erfolgen. Machen Sie einfach klar, wie Sie verschiedene Eingaben ausführen.
  • Die Ausgabe muss auf stdout gehen.
  • \Aund A/und AAsind auch Tröge, wie Sie es erwarten würden.
  • Ein wxh-Raster ist immer ein gut formatiertes Rechteck aus w * h-Zeichen ohne Zeilenumbruch. Es werden keine nachgestellten Leerzeichen fehlen und keine Vorkommen von *.
  • Die Rastermaße können so klein wie 1 × 1 und beliebig groß sein. (Beliebig groß innerhalb der Vernunft, int.maxValue oder dergleichen ist eine akzeptable Grenze. Gleiches gilt für T und K.)
  • Ein Strom über einem ffließt durch ihn hindurch.
  • Die Wasserhähne können überall sein, nicht nur in der obersten Reihe.
  • A teilt immer genau die Hälfte der Wassermenge auf.

Hinweis: Dinge wie /Aund //sind vollkommen gültig. Das Wasser fließt frei zwischen den Charakteren (obwohl für Herausforderung 2 nicht genügend Platz zum Zeichnen vorhanden ist).

Also im Setup

ff

/A

Der linke fStrom ergießt sich, trifft auf /und verschiebt sich nach links. Der rechte fStrom ergießt sich, trifft den A, die Hälfte geht nach rechts und die Hälfte geht nach links zwischen dem Aund dem /.

z.B

 ff
 **
*/A*
** *
** *

3
+1 Schöne Herausforderung. Was Herausforderung 3 würde das Gitter an der Spitze keine gültige Antwort sein , weil es 3 hat fs
edc65

@ edc65 Ah, guter Fang!
Calvins Hobbys


2
Für die zweite Herausforderung müssen Sie festlegen, wie mit Eingaben umgegangen werden soll, /Awenn Wasser auf die fällt A. Bei allen Herausforderungen wäre es gut zu klären, ob \Aes sich um eine Talsohle handelt. Für die dritte Herausforderung sollten 3 Einheiten, die auf eine fallen, Aals geteilt angenommen werden 1.5 / 1.5(die Eingabe ist also wirklich eine einzige rationale Zahl), oder ist es 2 / 1in welchem ​​Fall die 2?
Peter Taylor

1
@ PeterTaylor Vielen Dank. Ich habe diese Punkte geklärt. Ich denke, T und K könnten Floats sein, aber ich halte sie der Einfachheit halber ganzzahlig. (Aber wenn T = 3 trifft, erhalten Abeide Seiten 1,5. Es ist Sache
des

Antworten:


3

Alle Herausforderungen C # 690 Byte (416 Byte + 274 Byte)

Herausforderungen 1 & 2 C # 579 446 416 Bytes

Dies ist ein vollständiges Programm, das die Herausforderungen 1 und 2 in etwa erfüllen sollte. Es liest die Eingabezeilen von stdin, bis es eine leere Zeile erhält. Es gibt das Ergebnis für Herausforderung 2 und dann das Ergebnis für Herausforderung 1 aus. Verwendet die .NET-Dezimalklasse, um hoffentlich Rundungsfehler zu vermeiden.

using C=System.Console;class P{static void Main(){decimal u,t=0,f=0;string c,z="";for(decimal[]n=null,o;(c=C.ReadLine())!="";z+='\n'){int s=c.Length,i=s,e;o=n;n=new decimal[s];for(o=o??n;i-->0;n[i]+=(e&2)*u/2){e=c[i]%13;u=o[i]/(e<1?2:1);if(e%8<1)if(i>0)if(c[i-1]%7<3)t+=u;else n[i-1]+=u;if(e<2)if(i<s-1)if(c[i+1]%2>0)t+=u;else n[i+1]+=u;if(e>9){u++;f++;}}for(;++i<s;)z+=c[i]<33&n[i]>0?'*':c[i];}C.WriteLine(z+t/f);}}

Weniger golfen:

using C=System.Console;
class P
{
    static void Main()
    {
        decimal u,t=0,f=0;
        string c,z="";

        for(decimal[]n=null,o;(c=C.ReadLine())!="";z+='\n')
        {
            int s=c.Length,i=s,e;
            o=n;
            n=new decimal[s];
            for(o=o??n;i-->0;n[i]+=(e&2)*u/2)
            {
                e=c[i]%13;
                u=o[i]/(e<1?2:1);

                if(e%8<1)
                    if(i>0)
                        if(c[i-1]%7<3)t+=u;
                        else n[i-1]+=u;
                if(e<2)
                    if(i<s-1)
                        if(c[i+1]%2>0)t+=u;
                        else n[i+1]+=u;
                if(e>9)
                {
                    u++;
                    f++;
                }
            }
            for(;++i<s;)
                z+=c[i]<33&n[i]>0?'*':c[i];
        }

        C.WriteLine(z+t/f);
    }
}

Testlauf (mit einem Mangel an nachgestellten Leerzeichen, die ich verspreche, sind da):

f  f  f
      A
   A / \
\ /     A
    A \/
   /
 \/

f  f  f
*  * *A*
* *A*/ \*
\*/ *  *A
 * *A*\/
 **/ *
 \/  *
0.75

Herausforderung 3 C # 274 Bytes

Dies ist ein vollständiges Programm, das Herausforderung 3 abschließen sollte. Es ist mir gelungen, 6 Bytes einzusparen, indem ich meinen eigenen Integer-Parser geschrieben habe, um die Eingabe zu lesen, anstatt Splita ReadLineund using zu verwenden long.Parse.

using C=System.Console;class P{static void Main(){long t=-1,f=t,k;for(;f<0;)for(f=t,t=0;(k=C.Read())>47;)t=t*10+k-48;var r="Impossible\n";for(k=t;k<t*f;)k*=2;if(f<1||(k/f)*f==k)for(r=" f \n";t>0&t<f;t-=(t/f)*f)r+=((t*=2)<f?" ":"A")+"A \n/ /\n";C.Write(r+(t<f?"":"AAA\n"));}}

Weniger golfen:

using C=System.Console;
class P
{
    static void Main()
    {
        long t=-1,f=t,k;
        for(;f<0;)
            for(f=t,t=0;(k=C.Read())>47;)
                t=t*10+k-48;

        var r="Impossible\n";
        for(k=t;k<t*f;)
            k*=2;
        if(f<1||(k/f)*f==k)
            for(r=" f \n";t>0&t<f;t-=(t/f)*f)
                r+=((t*=2)<f?" ":"A")+"A \n/ /\n";
        C.Write(r+(t<f?"":"AAA\n"));
    }
}

Testlauf (wieder mit fehlenden Trailing Spaces, von denen ich verspreche, dass sie da sind):

32 17
 f
AA
/ /
 A
/ /
 A
/ /
 A
/ /
AA
/ /

3

Zuallererst habe ich eine Frage bezüglich der Herausforderung. Da ich nicht genug Reputation habe, um die Frage zu kommentieren, schreibe ich sie hier:

  • Was ist das Verhalten von /A(Wasser fließt auf A), //(Wasser fließt auf der rechten Seite) und Variationen dieses Prinzips? Fließt das Wasser zum ersten "freien Punkt" an der Seite oder fließt es "unter" dem Nachbarn?

Nur ein einfacher Versuch, es kann vereinfacht werden (was ich später tun werde, indem ich diesen Beitrag bearbeite).

Edit: Zweite Version, etwas kleiner. Ich habe einen anderen Ansatz gewählt: Anstatt nach jeder Zelle zu suchen, um zu überprüfen, was von oben und von den Seiten kommt, gehe ich von den Wasserhähnen aus und "fließe" mit Rekursion nach unten.

Javascript, 226 Bytes (Herausforderung 1)

function f(c){function h(b,a,d,e){b<c.length&&0<=a&&a<c[0].length&&("\\"==c[b][a]?"/"==e||"A"==e?g+=d:h(b,a+1,d,"\\"):"/"==c[b][a]?"\\"==e||"A"==e?g+=d:h(b,a-1,d,"/"):"A"==c[b][a]?"A"==e||"\\"==e||"/"==e?g+=d:(h(b,a-1,d/2,"A"),h(b,a+1,d/2,"A")):h(b+1,a,d,c[b][a]))}for(var g=0,m=0,k=0;k<c.length;k++)for(var l=0;l<c[k].length;l++)"f"==c[k][l]&&(h(k+1,l,1),m++);alert(g/m)};

Javascript, 204 Bytes (Herausforderung 2)

function f(c){function e(b,a,d){b<c.length&&0<=a&&a<c[0].length&&("\\"==c[b][a]?"/"!=d&&"A"!=d&&e(b,a+1,"\\"):"/"==c[b][a]?"\\"!=d&&"A"!=d&&e(b,a-1,"/"):"A"==c[b][a]?"A"!=d&&"\\"!=d&&"/"!=d&&(e(b,a-1,"A"),e(b,a+1,"A")):(" "==c[b][a]&&(c[b][a]="*"),e(b+1,a,c[b][a])))}for(var g=0;g<c.length;g++)for(var h=0;h<c[g].length;h++)"f"==c[g][h]&&e(g+1,h)};

Javascript, 238 Bytes (Herausforderung 1 + 2)

function f(c){function h(b,a,d,e){b<c.length&&0<=a&&a<c[0].length&&("\\"==c[b][a]?"/"==e||"A"==e?g+=d:h(b,a+1,d,"\\"):"/"==c[b][a]?"\\"==e||"A"==e?g+=d:h(b,a-1,d,"/"):"A"==c[b][a]?"A"==e||"\\"==e||"/"==e?g+=d:(h(b,a-1,d/2,"A"),h(b,a+1,d/2,"A")):(" "==c[b][a]&&(c[b][a]="*"),h(b+1,a,d,c[b][a])))}for(var g=0,m=0,k=0;k<c.length;k++)for(var l=0;l<c[k].length;l++)"f"==c[k][l]&&(h(k+1,l,1),m++);alert(g/m)};

Wie benutzt man

Geben Sie eine zweidimensionale Darstellung der Karte an. Hier ist das Beispiel in der Frage:

var input = [["f"," "," ","f"," "," ","f"," "," "],[" "," "," "," "," "," ","A"," "," "],[" "," "," ","A"," ","/"," ","\\"," "],["\\"," ","/"," "," "," "," "," ","A"],[" "," "," "," ","A"," ","\\","/"," "],[" "," "," ","/"," "," "," "," "," "],[" ","\\","/"," "," "," "," "," "," "]];
f(input);

Ausgabe

Herausforderung 1: Es wird einfach ein Dialogfeld (Warnung) mit dem Ergebnis erstellt (0,75 für das obige Beispiel).

Herausforderung 2: Die Karte wird direkt geändert. Soll ich es ausdrucken? Wenn ja, wird console.log akzeptiert? als gültige Ausgabe?

Herausforderung 1 + 2: Beide oben genannten Punkte zusammengenommen, offensichtlich ...


Das Wasser fließt weiter zwischen den Charakteren, als ob es die Linien der Aoder der Schrägstriche umgibt. Ich habe das in der Frage geklärt.
Calvins Hobbys

Die Frage lautetOutput must go to stdout.
user80551

Sie haben als Eingabeformat festgelegt, dass Sie ein Array von Zeichenfolgen mit einem Zeichen pro Zeile angeben. Beachten Sie jedoch, dass Sie Zeichenfolgen indizieren können str[0]. Das wäre ein Array von Strings anstelle eines Arrays von Zeichen.
Tomsmeding

1
user80551 Danke, ich weiß nicht, warum es aus meinem Kopf gerutscht ist. Ich werde meinen Code so schnell wie möglich aktualisieren. @tomsmeding Ja, es funktioniert für meine Antwort auf die Herausforderung 1. Für die Herausforderung 2 ändere ich die Eingabe direkt, und Sie können ein Zeichen in einer Zeichenfolge nicht mit str [i] ändern, daher wird ein Array von Arrays verwendet.
Aktualisierung vom

2

Python 3, 186 Bytes (Herausforderung 3)

Ich habe die Idee für das Raster von VisualMelons Antwort übernommen . Die Funktion sollte für beliebig große T und K ein gültiges Raster auf stdout ausgeben, sofern dies möglich ist (Raster mit endlicher Größe).

from fractions import*
def c(T,K):
 p=print;g=gcd(T,K);K//=g;T//=g
 if T&(T-1):p('Impossible')
 else:
  p(' f ')
  while T-1:
   T//=2;p('A/'[K<T]+'A \n///')
   if K>=T:K-=T
  p('AAA'*K)

Wie benutzt man

Rufen Sie die cFunktion mit dem Gesamtbetrag und dem Betrag auf, die als Argumente beibehalten werden sollen.

>>> c(24, 9)
 f 
/A 
///
AA 
///
AA 
///

>>> c(6, 2)
Impossible
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.