Inhalt
Die Fakten:
Plattform: | codewars.com |
Name: | Ball Upwards |
Level: | 6 kyu |
Sprache: | TypeScript |
Beschreibung:
You throw a ball vertically upwards with an initial speed v (in km per hour)
. The height h
of the ball at each time t
is given by h = v*t - 0.5*g*t*t
where g
is Earth's gravity (g ~ 9.81 m/s**2)
. A device is recording at every tenth of second the height of the ball.
For example with v = 15 km/h
the device gets something of the following form:
(0, 0.0), (1, 0.367...), (2, 0.637...), (3, 0.808...), (4, 0.881..) ...
where the first number is the time in tenth of second and the second number the height in meter.
Task
Write a function max_ball
with parameter v (in km per hour)
that returns the time in tenth of second
of the maximum height recorded by the device.
Examples:
max_ball(15) should return 4
max_ball(25) should return 7
Notes
- Remember to convert the velocity from km/h to m/s or from m/s in km/h when necessary.
- The maximum height recorded by the device is not necessarily the maximum height reached by the ball.
Quelle: codewars.com
Lösung
Pseudo-Code
Wie immer gibt's reichlich Varianten, hier ist eine meiner.
Erst die Lösungsschritte in Pseudo-Code. Los geht’s:
Lösungsschritte
Schritt 1
Zuerst können wir uns eine Helfer-Funktion erstellen.
Schritt 2
Da tue ich einfach die gegebene Formel (s. Beschreibung) rein.
Schritt 3
Für die Hauptfunktion brauchen wir einen Loop.
Schritt 4
Für jede Zehntelsekunde berechnen wir die aktuelle Höhe.
Schritt 5
Sobald die aktuelle Höhe kleiner wird als die vorige, können wir die vorige Zehntelsekunde zurückgeben.
Schritt 6
Wenn nicht, setzen wir die vorige Höhe gleich der aktuellen und gehen in die nächste Iteration.
Code
Geil. Übersetzen wir unseren Pseudo-Code in TypeScript:
Lösungsschritte
Die erste Zeile meines Helferleins:
function calcHeightAtTenthOfSec(speed: number, time: number): number {
Da tue ich jetzt einfach die gegebene Formel aus der Beschreibung rein:
const gravity = 9.81;
return speed * time - 0.5 * gravity * time ** 2;
}
Für die Schwerkraft erstelle ich eine extra Variable. Ist aber absolut optional und dient hier nur ein bisl der besseren Lesbarkeit.
Das wars auch schon fürs Helferlein, weiter gehts mit der Hauptfunktion.
Die erste Zeile meiner Hauptfunktion:
export function maxBall(v0: number): number {
Als Erstes initalisiere ich mir die vorige Höhe:
let prevHeight = 0;
Dann der Loop:
for (let t = 0; ; t++) {
Ich entscheide mich hier für einen unendlichen for
-Loop. Also ohne End-Bedingung.
Dann berechnen wir die aktuelle Höhe:
const currHeight = calcHeightAtTenthOfSec(v0 / 3.6, t / 10);
Indem wir die Geschwindigkeit durch 3,6
teilen, rechnen wir sie in m/s
um.
Dabei hilft uns unser Helferlein.
Sobald die aktuelle Höhe kleiner wird als die vorige, können wir die vorige Zehntelsekunde zurückgeben:
if (currHeight < prevHeight) return t - 1;
Und damit die Funktion und den unendlichen Loop beenden.
Ansonsten setzen wir die vorige Höhe gleich der aktuellen:
prevHeight = currHeight;
}
}
Voilá! 💪
Komplettlösung
export function maxBall(v0: number): number {
let prevHeight = 0;
for (let t = 0; ; t++) {
const currHeight = calcHeightAtTenthOfSec(v0 / 3.6, t / 10);
if (currHeight < prevHeight) return t - 1;
prevHeight = currHeight;
}
}
function calcHeightAtTenthOfSec(speed: number, time: number): number {
const gravity = 9.81;
return speed * time - 0.5 * gravity * time ** 2;
}