代码高尔夫:新年的烟花

bal*_*pha 63 language-agnostic

2009年即将结束,随着经济和所有,我们将节省我们的钱,而不是购买昂贵的烟花,我们将在今年的ASCII艺术庆祝.

挑战

给定一组烟花和时间,在那个时刻拍摄烟花的照片并将其绘制到控制台.

在新年前夜(UTC)午夜之前输入的最佳解决方案将获得500代表的赏金.这是代码高尔夫,因此字符数量很大; 然而,社区投票也是如此,我保留最佳/最酷/最有创意/等等的最终决定.

输入数据

请注意,我们的坐标系是从左到右,从下到上,所以所有的烟花都是在y-coordinate为0(零)时启动的.

输入数据由表单的烟花组成

(x, speed_x, speed_y, launch_time, detonation_time)
Run Code Online (Sandbox Code Playgroud)

哪里

  • x 是烟花发射的位置(列),
  • speed_x并且speed_y是发射时烟花的水平和垂直速度,
  • launch_time 是这个烟花发射的时间点,
  • detonation_time 是这个烟花爆炸的时间点.

烟花数据可以在您的程序中硬编码为5元组(或您的语言中的等效元素)列表,不计入您的字符数.但是,必须很容易更改此数据.

您可以做出以下假设:

  • 有合理数量的烟花(比如少于一百)
  • 对于每个烟花,所有五个数字都是一个合理范围内的整数(比如说,16位就足够了),
  • -20 <= x <= 820
  • -20 <= speed_x <= 20
  • 0 < speed_y <= 20
  • launch_time >= 0
  • launch_time < detonation_time < launch_time + 50

单个附加输入数据是应该呈现的时间点.这是一个非负整数,通过标准输入或命令行参数(无论您选择哪个)给出.

这个想法是(假设您的程序是一个名为python的脚本firework.py),这个bash脚本为您提供了一个漂亮的烟火动画:

#!/bin/bash
I=0
while (( 1 )) ; do
    python firework.py $I
    I=$(( $I + 1 ))
done
Run Code Online (Sandbox Code Playgroud)

(随意把等效的.BAT文件放在这里).

烟花的生活

烟花的生命如下:

  • 在发布时间之前,可以忽略它.
  • 在发射时,火箭具有位置(x, 0)和速度矢量(speed_x, speed_y).
  • 对于每个时间步,速度矢量被添加到该位置.通过对牛顿定律的一点拉伸,我们假设速度保持不变.
  • 在爆炸时,火箭爆炸成九个火花.所有九个火花在这个时间点都有相同的位置(这是火箭的位置,没有它爆炸),但它们的速度不同.每个速度都取决于火箭的速度,增加了-20,0或20,speed_x并添加了-10,0或10 speed_y.这是九种可能的组合.
  • 在爆炸时间之后,重力开始拉动:每个时间步,从每个火花中减去重力常数,恰好是2(2)speed_y.水平speed_x保持不变.
  • 对于爆炸时间后的每个时间步,首先将速度矢量添加到位置,然后从中减去2 speed_y.
  • 当火花的y位置低于零时,你可能会忘记它.

产量

我们想要的是烟花的图片,它看起来在给定的时间点.我们只能看看框架0 <= x <= 7890 <= y <= 239,它映射到79x24字符输出.

因此,如果火箭或火花具有位置(247,130),我们在第24列(从零开始,因此它是第25列),第13行(从零开始并从底部开始计数)中绘制一个字符,因此它是第23行 - 13 = 10,输出的第11行).

绘制哪个角色取决于火箭/火花的当前速度:

  • 如果移动是水平*,即speed_y == 0 or abs(speed_x) / abs(speed_y) > 2字符是" -".
  • 如果移动是垂直*,即speed_x == 0 or abs(speed_y) / abs(speed_x) > 2字符是" |".
  • 否则运动是对角线的,角色是" \"或" /"(你猜对了).
  • 如果相同的位置不止一次被吸引(即使它是相同的字符),我们X改为" ".因此,假设你有一个火花(536, 119)和一个火花(531, 115),你绘制一个" X",无论它们的速度如何.

*更新:这些是整数除法,因此斜率必须分别至少为3,或最多为1/3

输出(写入标准输出)是24行,每行以换行符结束.尾随空格被忽略,因此您可以(但不需要)填充宽度为79.这些行不得超过79个字符(不包括换行符).所有内部空间必须是空格字符(ASCII 32).

样本数据

烟花:

fireworks = [(628, 6, 6, 3, 33),
             (586, 7, 11, 11, 23),
             (185, -1, 17, 24, 28),
             (189, 14, 10, 50, 83),
             (180, 7, 5, 70, 77),
             (538, -7, 7, 70, 105),
             (510, -11, 19, 71, 106),
             (220, -9, 7, 77, 100),
             (136, 4, 14, 80, 91),
             (337, -13, 20, 106, 128)]
Run Code Online (Sandbox Code Playgroud)

时间33的输出:






       \         |         /                                                   


                                                      /                   \    

       -         |         /                                                   




       -         |         -                                                   


                                                      /                   \    





时间77的输出:













                                            \                                  






                                                \                              
                      X                                                        


                      \                                                        

93时的输出:




              \   |   /                                                        

              \   /   /                                                        

              -   -   -              \                                         




       \                                                                       







  /                               \                               \            



更新:我已将0到99的预期输出上传到firework.ü-wie-geek.de/NUMBER.html,其中NUMBER是时间.它包括调试信息; 点击一个粒子来查看它的当前位置,速度等等.是的,它是一个变音域.如果您的浏览器无法处理(显然Stack Overflow都不能),请尝试firework.xn---wie-geek-p9a.de.

另一个更新:正如下面的评论中暗示的那样,YouTube现在可以提供更长的烟火.它是使用MizardX条目的修改版本创建的,总烟花数量为170(是的,这超出了规范的要求,但程序优雅地处理了它).除了颜色,音乐和结束屏幕之外,可以通过此代码高尔夫的任何条目重新创建动画.所以,如果你非常讨厌享受ASCII艺术烟火(你知道的话):玩得开心,祝大家新年快乐!

Jua*_*uan 12

继承我的Python解决方案:

c = [(628, 6, 6, 3, 33),
    (586, 7, 11, 11, 23),
    (185, -1, 17, 24, 28),
    (189, 14, 10, 50, 83),
    (180, 7, 5, 70, 77),
    (538, -7, 7, 70, 105),
    (510, -11, 19, 71, 106),
    (220, -9, 7, 77, 100),
    (136, 4, 14, 80, 91),
    (337, -13, 20, 106, 128)]
t=input()
z=' '
s=([z]*79+['\n'])*23+[z]*79
def p(x,y,i,j):
    if 0<=x<790 and 0<=y<240:p=x/10+(23-y/10)*80;I=abs(i);J=abs(j);s[p]='X-|\\/'[[s[p]!=z,I>=3*J,J>=3*I,i*j<0,1].index(1)]
for x,i,j,l,d in c:
    T=t-l;x+=i*T
    if t>=d:e=t-d;[p(x+X*e,j*T+e*(Y-e+1),i+X,j+Y-2*e)for X in -20,0,20 for Y in -10,0,10]
    elif t>=l:p(x,j*T,i,j)
print ''.join(s)
Run Code Online (Sandbox Code Playgroud)

从stdin获取时间,它有342个字符的漂亮数字.我还在想象OP如何获得320:P

编辑:这是我能得到的最好的,根据wc的322个字符

t=input()
s=([' ']*79+['\n'])*24
def p(x,y,i,j):
 if 790>x>-1<y<240:p=x/10+(23-y/10)*80;I=abs(i);J=abs(j);s[p]='X-|\\/'[[s[p]>' ',I>=3*J,J>=3*I,i*j<0,1].index(1)]
for x,i,j,l,d in c:
 T=t-l;x+=i*T;e=t-d
 if t>=d:[p(x+X*e,j*T+e*(Y-e+1),i+X,j+Y-2*e)for X in-20,0,20for Y in-10,0,10]
 elif t>=l:p(x,j*T,i,j)
print''.join(s),
Run Code Online (Sandbox Code Playgroud)


bal*_*pha 9

既然选择了胜利者 - 祝贺Juan - 这是我自己的解决方案,Python中有304个字符:

t=input()
Q=range
for y in Q(24):print"".join((["\\/|-"[3*(h*h>=9*v*v)or(v*v>=9*h*h)*2or h*v>0]for X,H,V,L,D in F for s,Z,K,P,u in[(t-D,t>D,t-L,G%3*20-20,G/3*10-10)for G in[Q(9),[4]][t<D]]for h,v in[[P+H,u+V-2*s*Z]]if((X+H*K+P*s)/10,23-(V*K-s*(Z*s-Z-u))/10)==(x,y)][:2]+[" ","X"])[::3][-1]for x in Q(79))
Run Code Online (Sandbox Code Playgroud)

这并不是很快,因为对于79x24显示器中的每个点,它会遍历所有烟花以查看此时是否有任何烟花可见.

这是一个试图解释发生了什么的版本:

t=input()
Q=range
for y in Q(24):
    line = ""
    for x in Q(79):
        chars = [] # will hold all characters that should be drawn at (x, y)
        for X,H,V,L,D in F: # loop through the fireworks
            s = t - D
            Z = t > D
            K = t - L

            # if t < D, i.e. the rocket hasn't exploded yet, this is just [(0, 0)];
            # otherwise it's all combinations of (-20, 0, 20) for x and (-10, 0, 10)
            speed_deltas = [(G % 3 * 20 - 20, G / 3 * 10 -10) for G in [Q(9), [4]][t < D]]

            for P, u in speed_deltas:
                if x == (X + H*K + P*s)/10 and y == 23 - (V*K - s*(Z*s - Z - u))/10:

                    # the current horizontal and vertical speed of the particle
                    h = P + H
                    v = u + V - 2*s*Z

                    # this is identical to (but shorter than) abs(h) >= 3 * abs(v)
                    is_horizontal = h*h >= 9*v*v

                    is_vertical = v*v >= 9*h*h
                    is_northeast_southwest = h*v > 0

                    # a shorter way of saying
                    # char_index = (3 if is_horizontal else 2 if is_vertical else 1
                    #               if is_northeast_southwest else 0)
                    char_index = 3 * is_horizontal or 2 * is_vertical or is_northeast_southwest

                    chars.append("\\/|-"[char_index])

        # chars now contains all characters to be drawn to this point. So we have
        # three possibilities: If chars is empty, we draw a space. If chars has
        # one element, that's what we draw. And if chars has more than one element,
        # we draw an "X".

        actual_char = (chars[:2] + [" ", "X"])[::3][-1] # Yes, this does the trick.
        line += actual_char

    print line
Run Code Online (Sandbox Code Playgroud)


Mar*_*rot 8

蟒蛇:

fireworks = [(628, 6, 6, 3, 33),
             (586, 7, 11, 11, 23),
             (185, -1, 17, 24, 28),
             (189, 14, 10, 50, 83),
             (180, 7, 5, 70, 77),
             (538, -7, 7, 70, 105),
             (510, -11, 19, 71, 106),
             (220, -9, 7, 77, 100),
             (136, 4, 14, 80, 91),
             (337, -13, 20, 106, 128)]
import sys
t = int(sys.argv[1])
particles = []
for x, speed_x, speed_y, launch_time, detonation_time in fireworks:
    if t < launch_time:
        pass
    elif t < detonation_time:
        x += speed_x * (t - launch_time)
        y  = speed_y * (t - launch_time)
        particles.append((x, y, speed_x, speed_y))
    else:
        travel_time = t - detonation_time
        x += (t - launch_time) * speed_x
        y  = (t - launch_time) * speed_y - travel_time * (travel_time - 1)
        for dx in (-20, 0, 20):
            for dy in (-10, 0, 10):
                x1 = x + dx * travel_time
                y1 = y + dy * travel_time
                speed_x_1 = speed_x + dx
                speed_y_1 = speed_y + dy - 2 * travel_time
                particles.append((x1, y1, speed_x_1, speed_y_1))
rows = [[' '] * 79 for y in xrange(24)]
for x, y, speed_x, speed_y in particles:
    x, y = x // 10, y // 10
    if 0 <= x < 79 and 0 <= y < 24:
        row = rows[23 - y]
        if row[x] != ' ': row[x] = 'X'
        elif speed_y == 0 or abs(speed_x) // abs(speed_y) > 2: row[x] = '-'
        elif speed_x == 0 or abs(speed_y) // abs(speed_x) > 2: row[x] = '|'
        elif speed_x * speed_y < 0: row[x] = '\\'
        else: row[x] = '/'
print '\n'.join(''.join(row) for row in rows)
Run Code Online (Sandbox Code Playgroud)

如果删除初始烟花声明,将变量名压缩为单个字符,将空格压缩到最小,则可以获得590个字符.


Can*_*der 7

C:

删除所有不必要的空格(不包括烟花声明的632字节):

#define N 10
int F[][5]={628,6,6,3,33,586,7,11,11,23,185,-1,17,24,28,189,14,10,50,83,180,7,5,70,77,538,-7,7,70,105,510,-11,19,71,106,220,-9,7,77,100,136,4,14,80,91,337,-13,20,106,128};
#define G F[i]
#define R P[p]
g(x,y){if(y==0||abs(x)/abs(y)>2)return 45;if(x==0||abs(y)/abs(x)>2)return'|';if(x*y<0)return 92;return 47;}main(int A,char**B){int a,b,c,C[24][79]={},d,i,j,p=0,P[N*9][3],Q,t=atoi(B[1]),x,y;for(i=0;i<N;i++){if(t>=G[3]){a=t-G[3];x=G[0]+G[1]*a;y=G[2]*a;if(t<G[4]){R[0]=x;R[1]=y;R[2]=g(G[1],G[2]);p++;}else{b=t-G[4];y-=b*(b-1);for(c=-20;c<=20;c+=20){for(d=-10;d<=10;d+=10){R[0]=x+c*b;R[1]=y+d*b;R[2]=g(G[1]+c,G[2]+d-2*b);p++;}}}}}Q=p;for(p=0;p<Q;p++){x=R[0]/10;y=R[1]/10;if(R[0]>=0&&x<79&&R[1]>=0&&y<24)C[y][x]=C[y][x]?88:R[2];}for(i=23;i>=0;i--){for(j=0;j<79;j++)putchar(C[i][j]?C[i][j]:32);putchar(10);}}
Run Code Online (Sandbox Code Playgroud)

这里是完全相同的代码,添加了空白以便于阅读:

#define N 10

int F[][5] = {
    628, 6, 6, 3, 33,
    586, 7, 11, 11, 23,
    185, -1, 17, 24, 28,
    189, 14, 10, 50, 83,
    180, 7, 5, 70, 77,
    538, -7, 7, 70, 105,
    510, -11, 19, 71, 106,
    220, -9, 7, 77, 100,
    136, 4, 14, 80, 91,
    337, -13, 20, 106, 128
};

#define G F[i]
#define R P[p]

g(x, y) {
    if(y == 0 || abs(x)/abs(y) > 2)
        return 45;
    if(x == 0 || abs(y)/abs(x) > 2)
        return '|';
    if(x*y < 0)
        return 92;
    return 47;
}

main(int A, char**B){
    int a, b, c, C[24][79] = {}, d, i, j, p = 0, P[N*9][3], Q, t = atoi(B[1]), x, y;

    for(i = 0; i < N; i++) {
        if(t >= G[3]) {
            a = t - G[3];
            x = G[0] + G[1]*a;
            y = G[2]*a;
            if(t < G[4]) {
                R[0] = x;
                R[1] = y;
                R[2] = g(G[1], G[2]);
                p++;
            } else {
                b = t - G[4];
                y -= b*(b-1);
                for(c = -20; c <= 20; c += 20) {
                    for(d =- 10; d <= 10; d += 10) {
                        R[0] = x + c*b;
                        R[1] = y + d*b;
                        R[2] = g(G[1] + c, G[2] + d - 2*b);
                        p++;
                    }
                }
            }
        }
    }

    Q = p;

    for(p = 0; p < Q; p++) {
        x = R[0]/10;
        y = R[1]/10;
        if(R[0] >= 0 && x < 79 && R[1] >= 0 && y < 24)
            C[y][x] = C[y][x] ? 88 : R[2];
    }

    for(i = 23; i >= 0; i--) {
        for(j = 0; j < 79; j++)
            putchar(C[i][j] ? C[i][j] : 32);
        putchar(10);
    }
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*lli 7

对于Python,@ MizardX的解决方案很好,但显然不是codegolf优化 - 除了"不要真正计算"前缀的333个字符,即:

fireworks = [(628, 6, 6, 3, 33),
    (586, 7, 11, 11, 23),
    (185, -1, 17, 24, 28),
    (189, 14, 10, 50, 83),
    (180, 7, 5, 70, 77),
    (538, -7, 7, 70, 105),
    (510, -11, 19, 71, 106),
    (220, -9, 7, 77, 100),
    (136, 4, 14, 80, 91),
    (337, -13, 20, 106, 128)]
f = fireworks
### int sys argv append abs join f xrange
Run Code Online (Sandbox Code Playgroud)

(最后一条评论是我的一个小的codegolf-aux脚本的帮助器,它使所有可行的名称1-char机械 - 它需要被告知什么名字不能缩小;-),最短的我可以通过挤压来解决这个问题空格是592个字符(足够接近590 @MizardX声明).

拉出所有的句点("重构"代码高尔夫的心情),我得到,在前缀后面(我用单字符名称的小写我手动介绍或替换,大写我的codegolf-aux脚本自动替换):

import sys 
Z=int(sys.argv[1])
Y=[]
e=Y.extend
for X,W,V,U,T in f:
 if Z>=U:
  z=Z-U;X+=W*z
  if Z<T:e(((X,V*z,W,V),))
  else:R=Z-T;e((X+Q*R,z*V-R*(R-1)+P*R,W+Q,V+P-2*R)for Q in(-20,0,20)for P in(-10,0,10))
K=[79*[' ']for S in range(24)]
for X,S,W,V in Y:
 X,S=X/10,S/10 
 if(0<=X<79)&(0<=S<24):
  J=K[23-S];v=abs(V);w=abs(W)
  J[X]='X'if J[X]!=' 'else'-'if V==0 or w/v>2 else'|'if W==0 or v/w>2 else '\\'if W*V<0 else'/'
print '\n'.join(''.join(J)for J in K)
Run Code Online (Sandbox Code Playgroud)

测量为460个字符 - 减少130,即130/590 = 22%.

超出1个字符的名称和明显的方式以最小化间距,关键想法包括:单/除法(相同更好//为在Python 2.*整数),一个if/else代替一个的表达if/elif/else语句,extend用genexp而不是嵌套循环with append(允许删除一些空格和标点符号),不绑定到只出现一次的名称子表达式,绑定到名称子表达式,否则将重复(包括.extend属性查找),分号而不是换行符(如果可行)单独的行必须缩进,否则,将换行计为1个字符,没有保存).

是的,可读性受到了一些影响,但这在代码高尔夫中并不令人惊讶;-).

编辑:经过更多紧缩后,我现在有一个较小的程序(相同的前缀):

Z=input()
K=[79*[' ']for S in range(24)];a=-10,0,10
def g(X,S,W,V):
 X/=10;S/=10
 if(0<=X<79)&(0<=S<24):J=K[23-S];v=abs(V);w=abs(W);J[X]=[[['/\\'[W*V<0],'|'][v>2.9*w],'-'][w>2.9*v],'X'][J[X]!=' ']
for X,W,V,U,T in f:
 if Z>=U:
  z=Z-U;X+=W*z
  if Z<T:g(X,V*z,W,V)
  else:R=Z-T;[g(X+Q*2*R,z*V-R*(R-1)+P*R,W+Q*2,V+P-2*R)for Q in a for P in a]
print'\n'.join(''.join(J)for J in K)
Run Code Online (Sandbox Code Playgroud)

仍然是相同的输出,但现在是360个字符 - 比我以前的解决方案少了100个,我已经离开了这个答案的第一部分(仍然远远高于OP说他有的320,但是! - ).

我已经采取了自由允许输入时间值来从标准输入程度的优势(input比进口更严格sys和使用sys.argv[1]- !),消除了中间列表(瓦特/延长通话和它的最终循环)在支持g直接调用的新函数并在我们去的时候更新K,找到并删除了一些共性,将嵌套的if/else表达式重构为一个复杂的(但更简洁;-)构建和嵌套列表的索引,使用了这样一个事实:v>2.9*w更简洁w==0 or v/w>2(并且总是在要考虑的值范围内给出相同的结果).

编辑:将K("屏幕图像")放入1-D列表中再保存26个字符,将以下解决方案缩小到334(仍然在OP之上14,但是关闭......! - ):

Z=input()
K=list(24*(' '*79+'\n'))
a=-10,0,10
def g(X,S,W,V):
 if(0<=X<790)&(0<=S<240):j=80*(23-S/10)+X/10;v=abs(V);w=abs(W);K[j]=[[['/\\'[W*V<0],'|'][v>2.9*w],'-'][w>2.9*v],'X'][K[j]!=' ']
for X,W,V,U,T in f:
 if Z>=U:
  z=Z-U;X+=W*z
  if Z<T:g(X,V*z,W,V)
  else:R=Z-T;[g(X+Q*2*R,z*V-R*(R-1)+P*R,W+Q*2,V+P-2*R)for Q in a for P in a]
print ''.join(K),
Run Code Online (Sandbox Code Playgroud)


Aar*_*iel 7

在F#中用957*字符完成,它就像罪恶一样难看:

一系列烟花:

let F = [(628,6,6,3,33);(586,7,11,11,23);(185,-1,17,24,28);(189,14,10,50,83);(180,7,5,70,77);(538,-7,7,70,105);(510,-11,19,71,106);(220,-9,7,77,100);(136,4,14,80,91);(337,-13,20,106,128)]
Run Code Online (Sandbox Code Playgroud)

剩下的代码

let M=List.map
let C=List.concat
let P=List.partition
let L t f r=(let s=P(fun(_,_,_,u,_)->not(t=u))f
(fst s, r@(M(fun(x,v,w,_,t)->x,0,v,w,t)(snd s))))
let X d e (x,y,v,w)=C(M(fun(x,y,v,w)->[x,y,v-d,w;x,y,v,w;x,y,v+d,w])[x,y,v,w-e;x,y,v,w;x,y,v,w+e])
let D t r s=(let P=P(fun(_,_,_,_,u)->not(t=u))r
(fst P,s@C(M(fun(x,y,v,w,_)->(X 20 10(x,y,v,w)))(snd P))))
let rec E t l f r s=(
let(a,m)=L t f (M(fun(x,y,v,w,t)->x+v,y+w,v,w,t)r)
let(b,c)=D t m (M(fun(x,y,v,w)->x+v,y+w,v,w-2)s)
if(t=l)then(a,b,c)else E(t+1)l a b c)
let N=printf
let G t=(
let(f,r,s)=E 0 t F [] []
let os=s@(M(fun(x,y,v,w,_)->(x,y,v,w))r)
for y=23 downto 0 do (
for x=0 to 79 do (
let o=List.filter(fun(v,w,_,_)->((v/10)=x)&&((w/10)=y))os
let l=o.Length
if l=0 then N" "
elif l=1 then
let(_,_,x,y)=o.Head
N(
if y=0||abs(x)/abs(y)>2 then"-"
elif x=0||abs(y)/abs(x)>2 then"|"
elif y*x>0 then"/"
else"\\")
elif o.Length>1 then N"X")
N"\n"))
[<EntryPointAttribute>]
let Z a=
 G (int(a.[0]))
 0
Run Code Online (Sandbox Code Playgroud)

"漂亮"代码:

let fxs  = [(628,6,6,3,33);(586,7,11,11,23);(185,-1,17,24,28);(189,14,10,50,83);(180,7,5,70,77);(538,-7,7,70,105);(510,-11,19,71,106);(220,-9,7,77,100);(136,4,14,80,91);(337,-13,20,106,128)]

let movs xs = 
  List.map (fun (x, y, vx, vy) -> (x + vx, y + vy, vx, vy-2)) xs

let movr xs =
  List.map (fun (x, y, vx, vy, dt) -> (x + vx, y + vy, vx, vy, dt)) xs

let launch t fs rs =
  let split = List.partition(fun (lx, sx, sy, lt, dt) -> not (t = lt)) fs
  (fst split, rs @ (List.map(fun (lx, sx, sy, lt, dt) -> (lx, 0, sx, sy, dt)) (snd split)))

let split dx dy (x,y,sx,sy) =
  List.concat (List.map (fun (x,y,sx,sy)->[(x,y,sx-dx,sy);(x,y,sx,sy);(x,y,sx+dx,sy)]) [(x,y,sx,sy-dy);(x,y,sx,sy);(x,y,sx,sy+dy)])

let detonate t rs ss =
  let tmp = List.partition (fun (x, y, sx, sy, dt) -> not (t = dt)) rs
  (fst tmp, ss @ List.concat (List.map(fun (x, y, sx, sy, dt) -> (split 20 10 (x, y, sx, sy))) (snd tmp)))

let rec simulate t l fs rs ss =
  let (nfs, trs) = launch t fs (movr rs)
  let (nrs, nss) = detonate t trs (movs ss)
  if (t = l) then (nfs,nrs,nss)
  else 
    simulate (t+1) l nfs nrs nss

let screen t =
  let (fs, rs, ss) = simulate 0 t fxs [] []
  let os = ss @ (List.map(fun (x, y, sx, sy,_) -> (x, y, sx, sy)) rs)
  for y = 23 downto 0 do 
    for x = 0 to 79 do
      let o = List.filter(fun (px,py,_,_)->((px/10)=x) && ((py/10)=y)) os
      if o.Length = 0 then printf " "
      elif o.Length = 1 then
        let (_,_,sx,sy) = o.Head
        printf (
          if sy = 0 || abs(sx) / abs(sy) > 2 then "-"
          elif sx = 0 || abs(sy) / abs(sx) > 2 then "|"
          elif sy * sx > 0 then "/"
          else"\\"
        )
      elif o.Length > 1 then printf "X"
    printfn ""

[<EntryPointAttribute>]
let main args =
  screen (int(args.[0]))
  0
Run Code Online (Sandbox Code Playgroud)

完全被盗用新的和改进的逻辑重写.这和Python一样接近.你可以看到F#不向这里特设的脚本,在这里我要V和W的显式转换为浮动齿轮的弱点,声明主要功能有一个丑陋的属性来获取命令行参数,我不得不引用.NET System.Console.Write获得漂亮的输出.

哦,好好练习学习一门语言.

这是新代码,544字节:

let Q p t f=if p then t else f
let K=[|for i in 1..1920->Q(i%80>0)' ''\n'|]
let g(X,S,W,V)=
 if(X>=0&&X<790&&S>=0&&S<240)then(
let (j,v,w)=(80*(23-S/10)+X/10,abs(float V),abs(float W))
Array.set K j (Q(K.[j]=' ')(Q(w>2.9*v)'-'(Q(v>2.9*w)'|'(Q(W*V>0)'/''\\')))'X'))
let a=[-10;0;10]
[<EntryPointAttribute>]
let m s=
 let Z=int s.[0]
 for (X,W,V,U,T) in F do(
if Z>=U then
 let z,R=Z-U,Z-T
 let x=X+W*z
 if(Z<T)then(g(x,V*z,W,V))else(for e in[|for i in a do for j in a->(x+j*2*R,z*V-R*(R-1)+i*R,W+j*2,V+i-2*R)|]do g e))
 System.Console.Write K
 0
Run Code Online (Sandbox Code Playgroud)


me_*_*and 6

哈斯克尔

import Data.List
f=[(628,6,6,3,33),(586,7,11,11,23),(185,-1,17,24,28),(189,14,10,50,83),(180,7,5,70,77),(538,-7,7,70,105),(510,-11,19,71,106),(220,-9,7,77,100),(136,4,14,80,91),(337,-13,20,106,128)]
c=filter
d=True
e=map
a(_,_,_,t,_)=t
b(_,_,_,_,t)=t
aa(_,y,_,_)=y
ab(x,t,y,_,u)=(x,0,t,y,u)
ac(x,y,t,u,_)=[(x,y,t+20,u+10),(x,y,t,u+10),(x,y,t-20,u+10),(x,y,t+20,u),(x,y,t,u),(x,y,t-20,u),(x,y,t+20,u-10),(x,y,t,u-10),(x,y,t-20,u-10)]
g(x,y,t,u,v)=(x+t,y+u,t,u,v)
h(x,y,t,u)=(x+t,y+u,t,u-2)
i=(1,f,[],[])
j s 0=s
j(t,u,v,w)i=j(t+1,c((/=t).a)u,c((> t).b)x++(e ab.c((==t).a))u,c((>0).aa)(e h w)++(concat.e ac.c((==t).b))x)(i-1)
 where x=e g v
k x y
 |x==0='|'
 |3*abs y<=abs x='-'
 |3*abs x<=abs y='|'
 |(y<0&&x>0)||(y>0&&x<0)='\\'
 |d='/'
l(x,y,t,u,_)=m(x,y,t,u)
m(x,y,t,u)=(div x 10,23-div y 10,k t u)
n(x,y,_)(u,v,_)
 |z==EQ=compare x u
 |d=z
 where z=compare y v
o((x,y,t):(u,v,w):z)
 |x==u&&y==v=o((x,y,'X'):z)
 |d=(x,y,t):(o((u,v,w):z))
o x=x
q _ y []
 |y==23=""
 |d='\n':(q 0(y+1)[])
q v u((x,y,z):t)
 |u>22=""
 |v>78='\n':(q 0(u+1)((x,y,z):t))
 |u/=y='\n':(q 0(u+1)((x,y,z):t))
 |v/=x=' ':(q(v+1)u((x,y,z):t))
 |d = z:(q(v+1)u t)
p(_,_,v,w)=q 0 0((c z.o.sortBy n)((e l v)++(e m w)))
 where z(x,y,_)=x>=0&&x<79&&y>=0
r x=do{z <- getChar;(putStr.p)x}
s=e(r.j i)[1..]
main=foldr(>>)(return())s
Run Code Online (Sandbox Code Playgroud)

不像MizardX那么令人印象深刻,如果你删除f=…声明,它会以1068个字符进入,但是地狱,它很有趣.已经有一段时间了,因为我有机会和Haskell一起玩.

(稍微)更漂亮的版本也可用.

编辑:Ack.重读,我不太符合规范:这个版本每按一次键就会打印一个新的烟火显示屏,需要^C退出; 它不需要命令行参数并打印出相关的屏幕.


jso*_*son 5

Perl的

假设烟花数据定义为:

@f = (
   [628, 6, 6, 3, 33],
   [586, 7, 11, 11, 23],
   [185, -1, 17, 24, 28],
   [189, 14, 10, 50, 83],
   [180, 7, 5, 70, 77],
   [538, -7, 7, 70, 105],
   [510, -11, 19, 71, 106],
   [220, -9, 7, 77, 100],
   [136, 4, 14, 80, 91],
   [337, -13, 20, 106, 128]
);
Run Code Online (Sandbox Code Playgroud)
$t=shift;
for(@f){
    ($x,$c,$d,$l,$e)=@$_;
    $u=$t-$l;
    next if$u<0;
    $x+=$c*$u;
    $h=$t-$e;
    push@p,$t<$e?[$x,$d*$u,$c,$d]:map{$f=$_;map{[$x+$f*$h,($u*$d-$h*($h-1))+$_*$h,$c+$f,$d+$_-2*$h]}(-10,0,10)}(-20,0,20)
}
push@r,[($")x79]for(1..24);
for(@p){
   ($x,$y,$c,$d)=@$_;
   if (0 <= $x && ($x=int$x/10) < 79 && 0 <= $y && ($y=int$y/10) < 24) {
      @$_[$x]=@$_[$x]ne$"?'X':!$d||abs int$c/$d>2?'-':!$c||abs int$d/$c>2?'|':$c*$d<0?'\\':'/'for$r[23 - $y]
   }
}
$"='';
print$.,map{"@$_\n"}@r
Run Code Online (Sandbox Code Playgroud)

压缩,有433个字符.(见历史编辑)

这是基于多个先前的答案(主要是MizardX的),并且肯定可以改进.拖延其他与工作有关的任务的罪恶意味着我现在必须放弃.


原谅编辑 - 取出我所知道的所有技巧,这可以压缩到356 char:

sub p{
  ($X,$=,$C,$D)=@_;
  if(0<=$X&($X/=10)<79&0<=$=&($=/=10)<24){
    @$_[$X]=@$_[$X]ne$"?X:$D&&abs$C/$D<3?$C&&abs$D/$C<3?
    $C*$D<0?'\\':'/':'|':'-'for$r[23-$=]
  }
}
@r=map[($")x79],1..24;
$t=pop;
for(@f){
  ($x,$c,$d,$u,$e)=@$_;
  $x-=$c*($u-=$t);
  $u>0?1:($h=$t-$e)<0
  ?p$x,-$d*$u,$c,$d
  :map{for$g(-10,0,10){p$x+$_*$h,$h*(1-$h+$g)-$u*$d,$c+$_,$d+$g-2*$h}}-20,0,20
}
print@$_,$/for@r
Run Code Online (Sandbox Code Playgroud)

$=是一种特殊的Perl变量(以沿$%,$-$?)只能取整数值.使用它消除了使用该int功能的需要.