Wodociągi ASCII

19

Wprowadzenie

Rozważ siatkę znaków, f A\/takich jak

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

gdzie:

  • f przedstawia kran, który wylewa strumień wody w dół
  • A rozgałęzia się strumień wody powyżej, więc dokładnie połowa idzie w lewo, a dokładnie połowa idzie w prawo
  • \ przesuwa strumień wody powyżej w prawo o jedną jednostkę
  • / przesuwa strumień wody powyżej w lewo o jedną jednostkę
  • kombinacje \/tworzą koryto o nieskończonej pojemności, które zbiera strumienie wody nad nim
  • [space] jest pustą przestrzenią, przez którą woda może się poruszać

Z tego możemy sobie wyobrazić ścieżkę, którą podążałaby woda ( *) wychodząca z kranów i opadająca do koryta lub poza obszar kratki:

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

Zakładając, że 3 krany wytwarzają taką samą ilość wody pojedynczo, możemy to zobaczyć

  • Cała woda z pierwszego kranu trafia do dolnej rynny.
  • Połowa wody drugiego kranu trafia do dolnej rynny, a druga połowa jest dzielona między dolną rynnę i spada z siatki.
  • Jedna czwarta wody trzeciego kranu trafia do dolnej rynny, jedna czwarta spada z dna kratki, jedna czwarta spada do górnej rynny, a jedna czwarta spada z kratki w prawo.

Na podstawie tego możemy stwierdzić, że (1 + 3/4 + 1/4 + 1/4) / 3 = 75%woda jest chwytana przez koryta i (1/4 + 1/4 + 1/4) / 3 = 25%spada z siatki.

Wyzwania

Możesz wykonać dowolne lub wszystkie z tych wyzwań związanych z konfiguracją przepływu wody ASCII. Wszyscy są golfem, najkrótszą odpowiedzią dla każdego wyzwania jest zwycięzca. Zaakceptowaną odpowiedzią będzie osoba, która ukończy najwięcej wyzwań, z całkowitą długością kodu jako rozstrzygającym.

Wyzwanie 1
Napisz program, który wydobywa część wody, która przepływa do niecki dla danej sieci. Wyjście z powyższego przykładu byłoby po prostu 0.75.

Wyzwanie 2
Napisz program, który, biorąc pod uwagę siatkę, rysuje *kropki w miejscach, w których woda płynie, tak jak zrobiłem powyżej. Nie należy nadpisywać niczego poza znakami spacji, a siatka nie powinna zmieniać rozmiaru. Więc na coś takiego

 f
/A

nic nie trzeba robić, ponieważ chociaż woda płynie po obu stronach litery A, nie można jej wyciągnąć w lewo bez usunięcia /i nie można jej przesunąć w prawo bez powiększenia siatki 2 × 2.

Wyzwanie 3 (zaktualizowane)
Napisz program, który przyjmuje dwie nieujemne liczby całkowite, całkowitą T i kwotę, aby zachować K (T> = K). Wygeneruj i narysuj siatkę dokładnie ftaką, że gdy ten kran wyleje T jednostek wody, dokładnie K przepłynie do koryt. Jeśli nie da się tego zrobić w siatce skończonej dla konkretnej pary (T, K), wówczas wypisz „Impossible”.

Wyjaśnienia (dotyczą wszystkich wyzwań)

  • Dane wejściowe mogą być wprowadzane przez stdin, plik, a nawet wywołanie funkcji na reprezentacji ciągu siatki. Po prostu wyjaśnij, jak uruchamiać różne wejścia.
  • Dane wyjściowe muszą przejść do standardowego wyjścia.
  • \Ai A/a AAsą także korytka jak można się spodziewać.
  • Siatka W by H będzie zawsze dobrze sformatowanym prostokątem znaków W * H, nie licząc nowych linii. Nie będzie brakujących spacji końcowych i żadnych wystąpień *.
  • Wymiary siatki mogą być tak małe jak 1 × 1 i dowolnie duże. (Arbitralnie duży w granicach rozsądku, int.maxValue lub podobny jest dopuszczalnym limitem. To samo dotyczy T i K.)
  • Przez nią fprzepływa strumień powyżej strumienia .
  • Krany mogą być wszędzie, nie tylko w górnym rzędzie.
  • A zawsze dzieli ilość nalanej na nią wody dokładnie na pół.

Uwaga: rzeczy takie jak /Ai //są całkowicie poprawne. Woda jest swobodnie przepływać między znakami (choć na wyzwanie 2 nie znajduje się wystarczająco dużo miejsca, aby ją wyciągnąć).

Tak więc w konfiguracji

ff

/A

Lewy fstrumień leje się w dół, uderza /i przesuwa się w lewo. Prawy fstrumień wylewa się, uderza A, połowa idzie w prawo, a połowa idzie w lewo między Ai /.

na przykład

 ff
 **
*/A*
** *
** *
Hobby Calvina
źródło
3
+1 Niezłe wyzwanie. Jeśli chodzi o wyzwanie 3, siatka u góry nie byłaby prawidłową odpowiedzią, ponieważ ma 3 fs
edc65
@ edc65 Ah, dobry chwyt!
Calvin's Hobbies
2
Bardzo, bardzo podobny: codegolf.stackexchange.com/questions/26059/…
Howard
2
W drugim wyzwaniu musisz określić sposób obsługi danych wejściowych, np. /AJeśli woda spadnie na A. W przypadku wszystkich wyzwań dobrze byłoby wyjaśnić, czy \Ajest to koryto. W przypadku trzeciego wyzwania należy Azałożyć , że 3 jednostki, które padają, należy podzielić 1.5 / 1.5(tak więc dane wejściowe to tak naprawdę pojedyncza liczba wymierna), czy też 2 / 1w jakim przypadku, która strona otrzymuje 2?
Peter Taylor
1
@PeterTaylor Thanks. Wyjaśniłem te punkty. Wydaje mi się, że T i K mogą być zmiennoprzecinkowe, ale dla uproszczenia zachowuję je jako liczby całkowite. (Ale jeśli T = 3 trafi, a Anastępnie obie strony otrzymają 1,5. Zadaniem programisty jest upewnienie się, że precyzja pływaka nie stanowi problemu.)
Hobby Calvina

Odpowiedzi:

3

Wszystkie wyzwania C # 690 bajtów (416 bajtów + 274 bajtów)

Wyzwania 1 i 2 C # 579 446 416 bajtów

Jest to kompletny program, który powinien wykonać Wyzwania 1 i 2. Odczytuje wiersze wejścia ze standardowego wejścia, aż do otrzymania pustej linii. Wyświetla wynik dla Wyzwania 2, a następnie dla Wyzwania 1. Używa klasy dziesiętnej .NET, aby, mam nadzieję, uniknąć błędów zaokrąglania.

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

Mniej golfa:

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

Uruchomienie testowe (z obietnicą braku spacji końcowych):

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

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

Wyzwanie 3 C # 274 bajtów

Jest to kompletny program, który powinien zakończyć Wyzwanie 3. I a udało się uratować 6bytes pisząc własną całkowitą parser czytać wejście zamiast Spliting ReadLinei korzystania 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"));}}

Mniej golfa:

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

Uruchomienie testowe (znowu przy braku spacji końcowych, które obiecuję, że są):

32 17
 f
AA
/ /
 A
/ /
 A
/ /
 A
/ /
AA
/ /
VisualMelon
źródło
3

Przede wszystkim mam pytanie dotyczące wyzwania. Ponieważ nie mam wystarczającej reputacji, aby skomentować to pytanie, piszę to tutaj:

  • Jakie jest zachowanie /A(woda płynąca na A), //(woda płynąca po prawej stronie) i odmiany tej zasady? Czy woda płynie do pierwszego „wolnego miejsca” z boku, czy płynie „poniżej” swojego sąsiada?

Wystarczy prosta próba, można ją uprościć (co zrobię później, edytując ten post).

Edycja: druga wersja, nieco mniejsza. Wybrałem inne podejście: zamiast szukać każdej komórki, aby sprawdzić, co się dzieje z góry i po bokach, zaczynam od kranów i „płynę” w dół z rekurencją.

JavaScript, 226 bajtów (wyzwanie 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 bajty (wyzwanie 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 bajtów (wyzwanie 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)};

Jak używać

Podaj dwuwymiarową reprezentację mapy. Oto przykład podany w pytaniu:

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

Wynik

Wyzwanie 1: Po prostu utworzy okno dialogowe (alert) z wynikiem (0,75 dla powyższego przykładu).

Wyzwanie 2: Bezpośrednio zmodyfikuje mapę. Czy powinienem to wydrukować? Jeśli tak, to czy plik console.log jest akceptowany? jako prawidłowy wynik?

Wyzwanie 1 + 2: Oba powyższe połączone, oczywiście ...

Odśwież
źródło
Woda płynie między postaciami, jakby ściskała linie znaków Alub ukośników. Wyjaśniłem to w pytaniu.
Calvin's Hobbies
Pytanie brzmiOutput must go to stdout.
użytkownik80551
Podałeś jako format wejściowy, że możesz podać tablicę ciągów jednoznakowych na wiersz, ale pamiętaj, że możesz indeksować str[0]ciągi. Byłaby to tablica ciągów zamiast tablicy tablic znaków.
tomsmeding
1
user80551 Dzięki, nie wiem, dlaczego wymknęło mi się to z głowy. Zaktualizuję mój kod jak najszybciej. @tomsmeding Tak, działa na moją odpowiedź na wyzwanie 1. Ale dla wyzwania 2 modyfikuję bezpośrednio dane wejściowe i nie można modyfikować znaku w ciągu za pomocą str [i], stąd użycie tablicy tablic.
odświeżenie
2

Python 3, 186 bajtów (wyzwanie 3)

Pomysł na siatkę wziąłem z odpowiedzi VisualMelon . Funkcja powinna wydrukować prawidłową siatkę na standardowe wyjście dla dowolnie dużych T i K, pod warunkiem, że jest to możliwe (siatka o skończonych rozmiarach).

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)

Jak używać

Wywołaj cfunkcję z całkowitą kwotą i kwotą, aby zachować jako argumenty

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

>>> c(6, 2)
Impossible
Cyjanogenoid
źródło