Code Golf: New Year's Fireworks [closed]

Solution 1:

Heres my solution in 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)

Takes the time from the stdin and it has the nice number of 342 characters. I'm still trying to imagine how the OP got 320 :P

Edit: This is the best I could get, 322 chars acording to wc

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),

Solution 2:

Now that the winner is chosen – congratulations to Juan – here is my own solution, 304 characters in Python:

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

This is not really fast, because for each point in the 79x24 display, it loops through all fireworks to see if any of them is visible at this point.

Here is a version that tries to explain what's going on:

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