ASCII Waterworks

19

Intro

Considérons une grille de caractères f A\/tels que

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

où:

  • f représente un robinet qui verse un jet d'eau vers le bas
  • A bifurque le jet d'eau au-dessus, donc exactement la moitié va à gauche et exactement la moitié va à droite
  • \ déplace le jet d'eau au-dessus vers la droite d'une unité
  • / déplace le jet d'eau au-dessus vers la gauche d'une unité
  • les combinaisons \/créent un bac à capacité infinie qui recueille les cours d'eau au-dessus
  • [space] est un espace vide que l'eau peut traverser

À partir de cela, nous pouvons imaginer le chemin que l'eau ( *) emprunterait en sortant des robinets et en tombant dans les auges ou hors de la zone de la grille:

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

En supposant que les 3 robinets produisent la même quantité d'eau un par un, nous pouvons voir que

  • Toute l'eau du premier robinet va dans le bac inférieur.
  • Une moitié de l'eau du deuxième robinet va dans le bac inférieur et l'autre moitié est répartie entre le bac inférieur et tombe du réseau.
  • Un quart de l'eau du troisième robinet va dans le bac inférieur, un quart tombe du bas de la grille, un quart va dans le bac supérieur et un quart tombe du réseau vers la droite.

De cela, nous pouvons dire que (1 + 3/4 + 1/4 + 1/4) / 3 = 75%l'eau est captée par les auges et (1/4 + 1/4 + 1/4) / 3 = 25%tombe du réseau.

Défis

Vous pouvez relever tout ou partie de ces défis liés à cette configuration de débit d'eau ASCII. Ils sont tous du golf de code, la réponse la plus courte pour chaque défi est le gagnant. La réponse acceptée sera la personne qui réussit le plus de défis, avec la longueur totale du code comme bris d'égalité.

Défi 1
Écrivez un programme qui produit la fraction d'eau qui coule dans les auges pour une grille donnée. La sortie de l'exemple ci-dessus serait simplement 0.75.

Défi 2
Écrivez un programme qui, étant donné une grille, dessine *les points dans les endroits où l'eau coule comme je l'ai fait ci-dessus. Vous ne devez pas remplacer quoi que ce soit en dehors des caractères d'espacement et la grille ne doit pas changer de taille. Donc, pour quelque chose comme

 f
/A

rien ne doit être fait car, bien que l'eau coule de chaque côté du A, elle ne peut pas être tirée vers la gauche sans retirer le /et elle ne peut pas être tirée vers la droite sans agrandir la grille 2 × 2.

Défi 3 (mis à jour)
Écrivez un programme qui prend deux entiers non négatifs, le total T et le montant à garder K (T> = K). Générez et dessinez une grille avec exactement une ftelle que lorsque ce robinet versera T unités d'eau, exactement K coulera dans des auges. S'il est impossible de le faire dans une grille finie pour une paire (T, K) particulière, alors affichez «Impossible».

Clarifications (s'appliquent à tous les défis)

  • L'entrée peut se faire via stdin, ou un fichier, ou même un appel de fonction sur la représentation sous forme de chaîne de la grille. Indiquez simplement comment exécuter différentes entrées.
  • La sortie doit aller à stdout.
  • \Aet A/et AAsont également des creux comme vous vous en doutez.
  • Une grille w par h sera toujours un rectangle bien formaté de caractères w * h sans compter les nouvelles lignes. Il n'y aura aucun espace de fin manquant et aucune occurrence de *.
  • Les dimensions de la grille peuvent être aussi petites que 1 × 1 et arbitrairement grandes. (Arbitrairement grande dans la raison, int.maxValue ou similaire est une limite acceptable. Il en va de même pour T et K.)
  • Un ruisseau au-dessus d'un fcoule à travers lui.
  • Les robinets peuvent être n'importe où, pas seulement sur la rangée supérieure.
  • A divise toujours la quantité d'eau versée exactement en deux.

Remarque: des choses comme /Aet //sont parfaitement valides. L'eau ne circuler librement entre les personnages (bien que pour le défi 2 il n'y a pas assez de place pour dessiner).

Donc, dans la configuration

ff

/A

Le fruisseau gauche se déverse, frappe la /et se déplace vers la gauche. Le fcourant de droite se déverse, frappe le A, la moitié va à droite et la moitié va à gauche entre le Aet le /.

par exemple

 ff
 **
*/A*
** *
** *
Loisirs de Calvin
la source
3
+1 Beau défi. Quant au défi 3, la grille du haut ne serait pas une réponse valable car elle a 3 fs
edc65
@ edc65 Ah, bonne prise!
Calvin's Hobbies
2
Très très similaire: codegolf.stackexchange.com/questions/26059/…
Howard
2
Pour le deuxième défi, vous devez spécifier comment gérer les entrées comme /Asi l'eau tombait sur le A. Pour tous les défis, il serait bon de préciser s'il \As'agit d'un creux. Pour le troisième défi, faut- Ail supposer que 3 unités tombant sur un se divisent 1.5 / 1.5(donc l'entrée est vraiment un nombre rationnel unique) ou est-ce 2 / 1, dans quel cas, quel côté reçoit le 2?
Peter Taylor
1
@PeterTaylor Merci. J'ai clarifié ces points. Je suppose que T et K pourraient être des flottants mais je les garde entiers pour plus de simplicité. (Mais si T = 3 atteint un, les Adeux côtés obtiennent 1,5. C'est au codeur de s'assurer que la précision du flottement n'est pas un problème.)
Calvin's Hobbies

Réponses:

3

Tous les défis C # 690 octets (416 octets + 274 octets)

Défis 1 et 2 C # 579 446 416 octets

Il s'agit d'un programme complet qui devrait faire les défis 1 et 2, à peu près. Il lit les lignes d'entrée de stdin jusqu'à ce qu'il reçoive une ligne vide. Il imprime le résultat du défi 2, puis le résultat du défi 1. Utilise la classe décimale .NET pour éviter, espérons-le, toute erreur d'arrondi.

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

Moins golfé:

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

Test run (avec un manque d'espaces de fuite que je promets sont là):

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

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

Défi 3 C # 274 octets

Il s'agit d'un programme complet qui devrait compléter le défi 3. J'ai réussi à économiser 6 octets en écrivant mon propre analyseur entier pour lire l'entrée plutôt que de l' Splitingérer ReadLineet de l'utiliser 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"));}}

Moins golfé:

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

Test run (encore une fois avec un manque d'espaces de fuite que je promets sont là):

32 17
 f
AA
/ /
 A
/ /
 A
/ /
 A
/ /
AA
/ /
VisualMelon
la source
3

Tout d'abord, j'ai une question concernant le défi. Comme je n'ai pas assez de réputation pour commenter la question, je l'écris ici:

  • Quel est le comportement de /A(l'eau qui coule sur A), //(l'eau qui coule sur le côté droit) et les variations de ce principe? L'eau coule-t-elle vers le premier «point libre» sur le côté ou coule-t-elle «en dessous» de son voisin?

Juste un simple essai, il peut être simplifié waaaaay (ce que je ferai plus tard en éditant ce post).

Edit: Deuxième version, un peu plus petite. J'ai opté pour une approche différente: au lieu de chercher chaque cellule pour vérifier ce qui vient du haut et des côtés, je commence par les robinets et "coule" vers le bas avec récursivité.

Javascript, 226 octets (défi 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 octets (défi 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 octets (Défi 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)};

Comment utiliser

Fournissez une représentation bidimensionnelle de la carte. Voici l'exemple fourni dans la question:

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

Production

Défi 1: Il suffit de créer une boîte de dialogue (alerte) avec le résultat (0,75 pour l'exemple ci-dessus).

Défi 2: il modifiera directement la carte. Dois-je l'imprimer? Si oui, est-ce que console.log est accepté? comme sortie valide?

Défi 1 + 2: les deux combinés ci-dessus, évidemment ...

rafraîchir
la source
L'eau continue de couler entre les personnages comme si elle étreignait les lignes du Aou des barres obliques. Je l'ai précisé dans la question.
Calvin's Hobbies
La question déclareOutput must go to stdout.
user80551
Vous avez spécifié comme format d'entrée que vous devez donner un tableau de chaînes à un caractère par ligne, mais gardez à l'esprit que vous pouvez indexer str[0]en chaînes. Ce serait un tableau de chaînes au lieu d'un tableau de tableaux de caractères.
tomsmeding
1
user80551 Merci, je ne sais pas pourquoi cela m'est sorti de l'esprit. Je mettrai à jour mon code dès que possible. @tomsmeding Oui, cela fonctionne pour ma réponse au défi 1. Mais pour le défi 2, je modifie directement l'entrée et vous ne pouvez pas modifier un caractère dans une chaîne en utilisant str [i], d'où l'utilisation d'un tableau de tableaux.
refreshfr
2

Python 3, 186 octets (défi 3)

J'ai pris l'idée de la grille de la réponse de VisualMelon . La fonction devrait imprimer une grille valide à stdout pour des T et K arbitrairement grands, à condition que cela soit possible (grille de taille finie) bien sûr.

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)

Comment utiliser

Appelez la cfonction avec le montant total et le montant à conserver comme arguments.

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

>>> c(6, 2)
Impossible
Cyanogénoïde
la source