Sniff is a "Scratch-like" programming language that's designed to help Scratchers move gently from Scratch to more conventional languages. They can start writing programs, without having to learn a new language because Sniff is based on Scratch. They learn a little more about variables, compiling, syntax errors (!), and they can have fun controlling real hardware while they're doing it.

Monday, 5 October 2015

XKCD Velociraptor Problem

I'm always looking for fun problems to solve in Sniff, and I recently came across post on Wired,
which in turn stole its idea from XKCD. So I'm going to steal it and do it in Sniff! (seriously read the others first).

The question is how long can you survive a velociraptor attack, given a 40m head start? Velociraptors have a top speed of 25m/s and accelerate at 4m/s/s. You have a top speed of 6m/s and accelerate "quickly".

This is a fun question... not just because it has dinosaurs in it, because it ends in inevitable carnage, or even that it parodies typical maths/physics questions, but because it's actually something we can code easily - as they do in the wired article. The code actually demonstrates some of the basics of physics sims, as used for both science and games (so I get to tag this post as Algorithms, Science and Games!). 

make vX number
make hX number
make vV number
make hV number
make vVmax number
make hVmax number
make vA number
make hA number

make dt number
make t number

when start
.set vX to -40
.set hX to 0
.set vV to 0
.set hV to 0
.set vVmax to 25
.set hVmax to 6
.set vA to 4
.set hA to 1000
.set dt to 0.1
.set t to 0

We start by putting all of the information in the question into variables. Not only does this make things clearer in the code, but it means we can tweak them to try out different scenarios. Variables beginning h mean human, while variables beginning v mean velociraptor. The velociraptor starts 40 to the left, everyone starts at 0 speed. We set Vmax as per the question.

In the Wired article the interpret the human "quickly reaching your top speed" to mean an arbitrary 3m/s/s. I've chosen to interpret "quickly" in the spirit of physics textbooks where "light" is a code word for massless, "smooth" really means frictionless, and "quickly" really means "instantly". I've there for made hA=1000.

t for time, starts at zero. The standard "numeric" way to handle these kinds of problems is simply to use small time steps, so dt is 0.1.

Now the fun bit:
.repeat until not vX<hX
..change t by dt
..change vV by vA*dt
..if vV>vVmax
...set vV to vVmax
..change hV by hA*dt
..if hV>hVmax
...set hV to hVmax
..change vX by vV*dt
..change hX by hV*dt
.say [vX]

We're going to keep going while the velociraptors position is less then the humans. Each time round the loop represents a tiny fraction of a second.

Acceleration is rate of change of velocity so vV increases by vA each second. We're not looking at a whole second, so vV changes by vA*dt each time around. However vV can't be bigger than vVmax, so if it is we set it back.

Now we know the new velocity, we can calculate how far we move: vV*dt, and similarly or hV. 

With that in place we find we survive in impressive  38 seconds. Using the more conservative acceleration of 3m/s for the human the Wired use you only survive about 30 seconds. This code and the wired python code disagree very slightly as the wired code lets vV become greater than vVmax! However the answers get closer together as we make dt smaller.

This is an important point - this sort of code is only an approximation but even with simple code we get good results if we make dt small enough. Making dt bigger makes it less accurate, but your code runs faster.  The trick is to find ways to make dt bigger without sacrificing accuracy, but thats getting a bit advanced.

One of the main ways you might use this kind of code is in a game to simulate some kind of object being fired. In that case you have velocity and accretion in X and Y directions.

.set accX to 0
.set accY to -9.8
.repeat until posY<0
..change posX by velX*dt
..change posY by velY*dt
..change velX bu accX*dt
..change velY by accY*dt

Typically the acceleration in X is negligible, while the acceleration in Y is due to gravity. Drop this into a game and you've got your first physics engine!

No comments:

Post a Comment