The year 2009 is coming to an end, and with the economy and all, we'll save our money and instead of buying expensive fireworks, we'll celebrate in ASCII art this year.
The challenge
Given a set of fireworks and a time, take a picture of the firework at that very time and draw it to the console.
The best solution entered before midnight on New Year's Eve (UTC) will receive a bounty of 500 rep. This is code golf, so the number of characters counts heavily; however so do community votes, and I reserve the ultimate decision as to what is best/coolest/most creative/etc.
Input Data
Note that our coordinate system is left-to-right, bottom-to-top, so all fireworks are launched at a y
-coordinate of 0 (zero).
The input data consists of fireworks of the form
(x, speed_x, speed_y, launch_time, detonation_time)
where
x
is the position (column) where the firework is launched,speed_x
andspeed_y
are the horizontal and vertical velocity of the firework at launch time,launch_time
is the point in time that this firework is launched,detonation_time
is the point in time that this firework will detonate.
The firework data may be hardcoded in your program as a list of 5-tuples (or the equivalent in your language), not counting towards your character count. It must, however, be easy to change this data.
You may make the following assumptions:
- there is a reasonable amount of fireworks (say, fewer then a hundred)
- for each firework, all five numbers are integers within a reasonable range (say, 16 bits would suffice for each),
-20 <= x <= 820
-20 <= speed_x <= 20
0 < speed_y <= 20
launch_time >= 0
launch_time < detonation_time < launch_time + 50
The single additional piece of input data is the point of time which is supposed to be rendered. This is a non-negative integer that is given to you via standard input or command line argument (whichever you choose).
The idea is that (assuming your program is a python script called firework.py
) this bash script gives you a nice firework animation:
#!/bin/bash
I=0
while (( 1 )) ; do
python firework.py $I
I=$(( $I + 1 ))
done
(feel free to put the equivalent .BAT file here).
Life of a firework
The life of a firework is as follows:
- Before the launch time, it can be ignored.
- At launch time, the rocket has the position
(x, 0)
and the speed vector(speed_x, speed_y)
. - For each time step, the speed vector is added to the position. With a little stretch applied to Newton's laws, we assume that the speed stays constant.
- At detonation time, the rocket explodes into nine sparks. All nine sparks have the same position at this point in time (which is the position that the rocket would have, hadn't it exploded),
but their speeds differ. Each speed is based on the rocket's speed, with -20, 0, or 20 added to
speed_x
and -10, 0, or 10 added tospeed_y
. That's nine possible combinations. - After detonation time, gravity starts to pull: With each time step, the gravitational constant, which happens to be 2 (two), is subtracted from every spark's
speed_y
. The horizontalspeed_x
stays constant. - For each time step after the detonation time, you first add the speed vector to the position, then subtract 2 from
speed_y
. - When a spark's
y
position drops below zero, you may forget about it.
Output
What we want is a picture of the firework the way it looks at the given point in time. We only look at the frame 0 <= x <= 789
and 0 <= y <= 239
, mapping it to a 79x24 character output.
So if a rocket or spark has the position (247, 130), we draw a character in column 24 (zero-based, so it's the 25th column), row 13 (zero-based and counting from the bottom, so it's line 23 - 13 = 10, the 11th line of the output).
Which character gets drawn depends on the current speed of the rocket / spark:
- If the movement is horizontal*, i.e.
speed_y == 0 or abs(speed_x) / abs(speed_y) > 2
, the character is "-
". - If the movement is vertical*, i.e.
speed_x == 0 or abs(speed_y) / abs(speed_x) > 2
, the character is "|
". - Otherwise the movement is diagonal, and the character is "
\
" or "/
" (you'll guess the right one). - If the same position gets drawn to more than once (even if it's the same character), we put "
X
" instead. So assuming you have a spark at(536, 119)
and one at(531, 115)
, you draw an "X
", regardless of their speeds.
* update: these are integer divisions, so the slope has to be at least 3, or at most 1/3, respectively
The output (written to standard output) is 24 lines, each terminated by a newline character. Trailing spaces are ignored, so you may, but don't need to, pad to a width of 79. The lines may not be longer than 79 characters (excluding the newline). All interior spacing must be space characters (ASCII 32).
Sample Data
Fireworks:
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)]
Output at time 33:
\ | / / \ - | / - | - / \
Output at time 77:
\ \ X \
Output at time 93:
\ | / \ / / - - - \ \ / \ \
Update: I have uploaded the expected output at the times 0 thru 99 to firework.ü-wie-geek.de/NUMBER.html, where NUMBER is the time. It includes debug information; click on a particle to see its current position, speed, etc. And yes, it's an umlaut domain. If your browser can't handle that (as obviously neither can Stack Overflow), try firework.xn---wie-geek-p9a.de.
Another update: As hinted at in the comments below, a longer firework is now available on YouTube. It was created with a modified version of MizardX' entry, with a total fireworks count of 170 (yes, that's more than the spec asked for, but the program handled it gracefully). Except for the color, the music, and the end screen, the animation can be recreated by any entry to this code golf. So, if you're geeky enough to enjoy an ASCII art firework (you know you are): Have fun, and a happy new year to all!