ASCII水厂


19

介绍

考虑一个字符网格,f A\/例如

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

哪里:

  • f 代表向下方倒水的水龙头
  • A 将上面的水分叉,所以正好有一半左,右又有一半
  • \ 将水流向右上方移动一个单位
  • / 将上方的水流向左移动一个单位
  • 组合\/产生了一个容量无限的槽,可以收集上方的水流
  • [space] 是空荡荡的空间,水无法通过

从中我们可以想象水(*)从水龙头流出并落入水槽或网格区域时所走的路径:

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

假设3个水龙头一次输出相同量的水,我们可以看到

  • 所有第一个水龙头的水都进入较低的水槽。
  • 第二个水龙头的一半水流到下部水槽,另一半流到下部水槽和落水网格之间。
  • 第三龙头的水的四分之一流到下部水槽,四分之一从网格底部掉落,四分之一进入上部水槽,四分之一从右边的网格掉落。

由此我们可以看出,(1 + 3/4 + 1/4 + 1/4) / 3 = 75%水被水槽捕获并(1/4 + 1/4 + 1/4) / 3 = 25%从网格上掉下。

挑战性

您可以完成与此ASCII水流设置有关的任何或所有这些挑战。它们都是代码高尔夫,每个挑战的最短答案是获胜者。接受的答案将是完成最多挑战的人,并且总代码长度是决胜局。

挑战1
编写一个程序,为给定的网格输出流入槽中的水量。上面示例的输出将仅仅是0.75

挑战2
编写一个程序,给定一个网格,*像我上面所做的那样在水流过的地方绘制。除空格字符外,您不应覆盖任何内容,并且网格不应更改大小。所以对于像

 f
/A

不需要做任何事情,因为尽管水确实在A的两侧流动,但是如果不移除A,就不能向左抽水,/而没有扩大2×2网格也就不能向右抽水。

挑战3(已更新)
编写一个程序,该程序使用两个非负整数,即总T和保持K的数量(T> = K)。生成并绘制一个正好为网格的网格,f以便当该龙头倒出T单位的水时,恰好K会流入槽中。如果不可能在特定(T,K)对的有限网格中执行此操作,则输出“不可能”。

澄清(适用于所有挑战)

  • 输入可以通过stdin或文件,甚至可以通过网格的字符串表示形式进行的函数调用。只要弄清楚如何运行不同的输入即可。
  • 输出必须转到stdout。
  • \AA/AA也波谷你所期望的。
  • w x h网格将始终是w * h字符的格式良好的矩形,不包括换行符。不会缺少尾随空格,也不会出现*
  • 网格尺寸可以小至1×1,也可以大。(在合理范围内任意大,可以使用int.maxValue之类的限制。T和K也是如此。)
  • 流上方的f流直接流过它。
  • 水龙头可以在任何地方,而不仅限于第一行。
  • A 总是将倒在上面的水量精确地分成两半。

注意:/A和之类的事情//都是完全有效的。水字符之间自由流动(尽管挑战2有没有足够的空间来绘制)。

因此,在设置中

ff

/A

f流倾泻而下,撞到/并向左移动。正确的f流倾泻而下,撞击A,半顺利,和左半之间那张A/

例如

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

3
+1不错的挑战。至于挑战3,顶部的网格将是3 fs,因此不是一个有效的答案
edc65

@ edc65啊,不错!
加尔文的爱好2014年


2
对于第二个挑战,您需要指定如何处理输入,例如,/A如果水掉到上A。对于所有挑战,最好弄清是否\A是低谷。对于第三个挑战,是否应该A假设落在a上的3个单位是分裂的1.5 / 1.5(因此输入实际上是一个有理数)还是2 / 1在这种情况下,哪一方接收2
彼得·泰勒

1
@PeterTaylor谢谢。我已经阐明了这些观点。我想T和K可能是浮点数,但为简单起见,我将它们保留为整数。(但如果T = 3确实命中了,A那么双方都将获得1.5。这取决于编码器,以确保浮动精度不是问题。)
卡尔文的爱好

Answers:


3

所有挑战C#690bytes(416bytes + 274bytes)

挑战1&2 C#579 446 416bytes

这是一个完整的程序,大约可以完成挑战1和2。它从stdin读取输入行,直到收到空行。它先打印出Challenge 2的结果,然后打印出Challenge 1的结果。使用.NET十进制类希望避免任何舍入错误。

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

少打高尔夫球:

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

测试运行(我保证那里没有尾随空格):

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

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

挑战3 C#274bytes

这是一个完整的程序,它应该完成的挑战3.我一个设法写我自己的整数分析器来读取输入,而不是保存6字节Split荷兰国际集团一ReadLine和使用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"));}}

少打高尔夫球:

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

测试运行(再次缺少尾随空格,我保证在那里):

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

3

首先,我对挑战有疑问。由于我没有足够的声誉来评论这个问题,所以在这里写:

  • 什么是行为/A(水对A流出), //(流动右侧的水),并在此原则的变化?水会流到侧面的第一个“自由点”还是流到其邻居的“下方”?

只需简单尝试,就可以简化操作(稍后我将通过编辑此文章来完成)。

编辑:第二版,小一点。我采用了一种不同的方法:不是从每个单元检查顶部和侧面的内容,而是从水龙头开始,然后递归向下“流动”。

Javascript,226个字节(挑战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字节(挑战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个字节(挑战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)};

如何使用

提供地图的二维表示。这是问题中提供的示例:

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

输出量

挑战1:它将简单地创建一个对话框(警报),并显示结果(上例中为0.75)。

挑战2:它将直接修改地图。我应该打印吗?如果是这样,是否接受console.log?作为有效输出?

挑战1 + 2:以上两者结合起来,显然 ...


水在角色之间不断流动,好像在拥抱A斜线或斜线一样。我已经在问题中澄清了这一点。
加尔文的爱好

问题指出Output must go to stdout.
user80551

您将输入格式指定为每行给出一个由一个字符组成的字符串数组,但请记住您可以索引str[0]到字符串中。那将是一个字符串数组,而不是一个字符数组。
tomsmeding

1
user80551谢谢,我不知道为什么它会从我的脑海中溜走。我将尽快更新我的代码。@tomsmeding是的,它适用于我对难题1的回答。但是对于难题2,我直接修改了输入,因此无法使用str [i]修改字符串中的字符,因此无法使用数组数组。
2014年

2

Python 3,186个字节(挑战3)

我从VisualMelon的答案中得到了网格的想法。该函数应该为任意大的T和K向stdout打印一个有效的网格,只要有可能(有限大小的网格)。

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)

如何使用

c以总金额和要保留的金额作为参数调用该函数。

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

>>> c(6, 2)
Impossible
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.