Help Notwen simulate gravity!

9

1

Notwen wants to study the kinematics of bodies thrown from big heights in a uniform gravitational field but unfortunately he doesn't have the technical possibility to go to sufficiently high places and observe the objects while falling. But who doesn't want to see advances in science so... Let's help Notwen build a gravity simulator!

Physical Background

An object dropped from a height \$h\$ (without initial velocity) in a uniform gravitational field, neglecting atmospheric effects such as drag or wind gains velocity and speeds up towards the ground with time. This "rate of change" of velocity in a unit of time is called gravitational acceleration. Near the surface of Earth, it is approximately equal to \$g\approx9.8\frac{m}{s^2}\$, but for the purposes of this challenge we will use the value \$10\frac{m}{s^2}\$, meaning that in a single second, an object increases its velocity by about \$10 \frac{m}{s}\$. Consider having a height \$h\$, which is a multiple of \$100m\$ and imagine dividing that height into equal intervals, each \$100\$ meters long. Notwen wants to measure how long it takes for the object to fall through each of those intervals, so that's what we aim to compute as well. Modern kinematics – skipping technicalities – tells us that: $$\Delta h_k=v_kt_k+\dfrac{1}{2}gt_k^2$$ where \$\Delta h_k\equiv\Delta h=100m\$ for all values of \$k\$ in our case, \$v_k\$ is the initial velocity at the beginning of our \$k^\text{th}\$ interval and \$t_k\$ is the duration of the \$k^\text{th}\$ time interval (for reference, indexing starts at \$0\$ with \$v_0=0\$). We also know that \$v_k\$ has the following expression: $$v_k=\sqrt{2g(\Delta h_0+\Delta h_1+\cdots+\Delta h_{k-1})}=\sqrt{2gk\Delta h}$$ Numerically, we get \$v_k=\sqrt{2000k}\frac{m}{s}\$ and plugging into the first equation and solving for \$t_k\$ gives $$\color{red}{\boxed{t_k=2\sqrt{5}\left(\sqrt{k+1}-\sqrt{k}\right)s}}\tag{*}$$ So the object travels the first interval (\$k=0\$) in \$4.4721s\$, the second interval (\$k=1\$) in \$1.8524s\$ and so on (pastebin with more values).

The challenge

Input: The height \$h\$ from which the object is thrown as either: a positive integer multiple of \$100\$, \$h\$ or the number of intervals \$N=\frac{h}{100}\$ (so either \$700\$ or \$7\$ would mean that \$h=700m\$) – which one is up to you.

Output: An ASCII art animation of a falling object, dropped from a height \$h\$ (details below).

The structure of an output frame must be as follows:

  • \$N\$ newlines preceding the "ground", represented by at least one non-whitespace character (e.g. @). At least one of the characters of the ground must lie on the vertical that the object falls on.
  • Another non-whitespace character representing the object (e.g. X), other than the one you chose for the ground.
  • Optionally, a character at the beginning of each line representing the vertical axis or the wall made on \$N\$ lines. Any amount of leading and trailing spaces are fine as long as they are consistent between frames, as well as any amount of spaces between the wall and the object. Examples of valid frames include1 (for \$h=700m\$ or \$N=7\$):
    | X                                       >
    |                             @           >   A
    |                                         >
    |        or            or           or    > 
    |               O                         >
    |                                         >
    |                                         >
    @@@             ^           -----            &&&
    

The object must start on the first line of the first frame, then after \$t_0\approx 4.47s\$ the output should be flushed and your program should display the object on the same vertical but on the next line in the second frame; then after \$t_1\approx 1.85s\$ the output should be flushed again and your program should display the object on the same vertical but on the next line in the third frame and so on, until the object reaches the line right above the ground. Example:

Animation Example

Rules

  • The output should be some text written to an interactive (flushable) console, a GIF, a separate file for each frame or some other reasonable technique of output.
  • Each frame should completely overwrite the last frame and be in the same location.
  • You can assume that the time required for the compiler / interpreter to output the text is negligible and the minimum precision permitted for computing the square roots is to 2 decimal places.
  • You can take input and provide output through any standard method, while taking note that these loopholes are forbidden by default. This is , so try to complete the task in the least bytes you can manage in your language of choice.

1: I'm lenient about what constitutes a valid frame because I want to allow whatever suits your solution best and I'm not trying to add superfluous stuff to the challenge. If anything is unclear, ask in the comments.

Mr. Xcoder

Posted 2019-02-08T15:30:42.213

Reputation: 39 774

Answers

3

JavaScript (ES7) + CSS + HTML, 340 bytes

f=n=>{o.style.height=n+'em';x.style.animationDuration=(n*20)**.5+'s';o.appendChild(x,x.remove())}
pre{position:relative;border:1px solid;height:5em;overflow:hidden}span{position:absolute;top:0;animation:x 10s cubic-bezier(0.33,0,0.67,0.33)both}@keyframes x{to{top:100%}}
<input type=number value=5 oninput=f(this.value)><pre id=o><span id=x>X

If I've got my sums right then the animation duration is \$ \sqrt { 20 N } \$ and then the CSS cubic-bezier does the rest.

Neil

Posted 2019-02-08T15:30:42.213

Reputation: 95 035

2

Charcoal, 28 bytes

Nθ↓θ⁴Fθ«J²ιPXR⌊×φ×₂²⁰⁻₂⊕ι₂ι 

Try it online! Link is to verbose version of code. Note: trailing space. You can observe the delay on TIO but you can't watch the animation so you'll have to imagine that from the output. Takes N as input. Explanation:

Nθ

Input N.

↓θ⁴

Print the wall and the ground, so that the output's shape is consistent.

Fθ«

Loop over each interval.

J²ιPX

Place an X at the appropriate height.

R⌊×φ×₂²⁰⁻₂⊕ι₂ι

Output the current canvas contents and wait for the appropriate amount of time (truncated to the nearest millisecond).

 

Overwrite the X with a space.

Neil

Posted 2019-02-08T15:30:42.213

Reputation: 95 035

2

Perl 6, 81 bytes

{say "\e[s{"\n"x$_}-";map {say "\e[u{" \n"x 4.9e-6*$_²}o";sleep .01},^452*.sqrt}

"Try it online!", but TIO cannot handle the animation.

Explanation

I chose a bit different approach (and I think it's for the better, though I don't know for sure). Instead of sleeping for times given by the formula in the OP, I just draw the appropriate situation "every 10 ms" (± errors induced by sleep).

That means that there are 100 frames a second, so if we denote the frame number by \$k\$, it must be \$t=k/100\$. And since we divide the vertical distance into 100 meter blocks, we can write the height as \$h = 100n\$, where \$n\$ is the number of blocks (given as an input). The height traveled in time \$t\$ is given by \$h = gt^2/2\$, so the number of blocks traveled is $$ n = \frac{1}{100} \tfrac 1 2 g t^2 = \tfrac 1 2 g \times 10^{-6} k^2 \approx 4.905\times 10^{-6} k^2. $$ We can invert it to get the total number of frames we need to render: $$ k = \frac{\sqrt n}{\sqrt{4.905\times 10^{-6}}} \approx 452 \times \sqrt n.$$

This suffices to write the function. It takes one argument, the number of blocks to render, i. e. \$n\$. First, we do say "\e[s{"\n"x$_}-". That prints an ANSI escape sequence called Save Cursor, then it prints \$n\$ newlines, and after that, it prints a dash (the ground) and a newline. (This uses the cool feature of double quotes in Perl 6: you can inline result of any code right into the string by writing that code inside curly braces.)

After that, we make a sequence from 0 to \$452\sqrt n\$ (automatically truncated to integer) with ^452*.sqrt, and we map over it. In each iteration, we print an Unsave Cursor ANSI sequence (which puts the cursor at the position where it was last saved), write \$4.9\times 10^{-6} k^2\$ strings "space+newline" (automatically truncated once again) and finally an o that denotes the object. Then we sleep for 10 ms, rinse and repeat.

Due to the automatic truncation, it just Does The Right Thing™ and moves the "o" only after each full 100 m of the fall.

resulting animation

Ramillies

Posted 2019-02-08T15:30:42.213

Reputation: 1 923

1

Python 2, 117 120 123 bytes

-3 bytes Thanks to "Don't be a x-triple dot" and "Jonathan Frech"

import time
h=input()
for k in range(h):print'\33[2J'+'\n'*k+'O'+'\n'*(h-k)+'^';time.sleep(2*5**.5*((k+1)**.5-k**.5))

Try it online!

enter image description here

mdahmoune

Posted 2019-02-08T15:30:42.213

Reputation: 2 605

1+1 from me, good solution! Wouldn't using the actual unprintable character save a couple of bytes rather than chr(27)? – Mr. Xcoder – 2019-02-08T16:55:28.560

@Don'tbeax-tripledot And if one does not get ahold of the character itself, '\33' should still be shorter. – Jonathan Frech – 2019-02-09T15:31:42.183

Also, 2*5**.5 is 20**.5. – Jonathan Frech – 2019-02-09T15:33:33.750

@JonathanFrech Square root of 20 replaced by 4.47 – mdahmoune – 2019-02-09T16:08:31.170

@mdahmoune Well ... If that accuracy is good enough, then yes. – Jonathan Frech – 2019-02-09T20:54:20.917

Why not chr(27)+'[2J' ~> '\33[2J'? – Jonathan Frech – 2019-02-09T20:54:40.513

1

C# (.NET Core), 201, 180+13 = 193 bytes

Needs using System; for 13 additional bytes.

Strangely, Console.Clear() does not seem to be working for me on TIO. However, this runs perfectly in a console app under VS2017.

EDIT: Thanks to Embodiment of Ignorance for shortening up the loop, pointing out my unnecessary variable assign and unnecessary using System.Threading; statement (leftover from VS copying), and pointing out that the ground was required! Total of 8 bytes golfed thus far with the addition of the ground. Ty Ty!

x=>{for(var j=x;j>0;System.Threading.Thread.Sleep((int)(4470*(Math.Sqrt(x-j+1)-Math.Sqrt(x-j--))))){Console.Clear();Console.Write("X".PadLeft(x-j+1,'\n').PadRight(x+1,'\n')+"-");}}

Try it online!

Destroigo

Posted 2019-02-08T15:30:42.213

Reputation: 401

1

Haskell, 145 bytes

import Control.Concurrent
a!b=[a..b]>>"\n"
f h=mapM(\k->putStr("\27[2J"++1!k++'O':k!h++"-")>>threadDelay(round$4472135*(sqrt(k+1)-sqrt k)))[1..h]

Needs to be run in an ANSI terminal. The input is the number of intervals.

threadDelay's parameter is in nanoseconds, so a literal 4472135 is shorter than 2*sqrt 5*10^6. Unfortunately 46**4 = 4477456 is not within the limit of the required precision.

nimi

Posted 2019-02-08T15:30:42.213

Reputation: 34 639