Codewars Lösung | Buying a car


coden
Codewars. Achieve mastery through challenge.
Daniel Kaser|24. Februar 2024
3 min.

Inhalt

  1. Die Fakten
  2. Beschreibung
  3. Lösung
    1. Pseudo-Code
    2. Code
  4. Feedback

Die Fakten:

Plattform:codewars.com
Name:Buying a car
Level:6 kyu
Sprache:TypeScript

Beschreibung:

Let us begin with an example:

A man has a rather old car being worth $2000. He saw a secondhand car being worth $8000. He wants to keep his old car until he can buy the secondhand one.

He thinks he can save $1000 each month but the prices of his old car and of the new one decrease of 1.5 percent per month. Furthermore this percent of loss increases of 0.5 percent at the end of every two months. Our man finds it difficult to make all these calculations.

Can you help him?

How many months will it take him to save up enough money to buy the car he wants, and how much money will he have left over?

Parameters and return of function:

parameter (positive int or float, guaranteed) start_price_old (Old car price)
parameter (positive int or float, guaranteed) start_price_new (New car price)
parameter (positive int or float, guaranteed) saving_per_month 
parameter (positive float or int, guaranteed) percent_loss_by_month

nbMonths(2000, 8000, 1000, 1.5) should return [6, 766] or (6, 766)

Detail of the above example:

end month 1: percent_loss 1.5 available -4910.0
end month 2: percent_loss 2.0 available -3791.7999...
end month 3: percent_loss 2.0 available -2675.964
end month 4: percent_loss 2.5 available -1534.06489...
end month 5: percent_loss 2.5 available -395.71327...
end month 6: percent_loss 3.0 available 766.158120825...
return [6, 766] or (6, 766)

where 6 is the number of months at the end of which he can buy the new car and 766 is the nearest integer to 766.158... (rounding 766.158 gives 766).

Note:

Selling, buying and saving are normally done at end of month. Calculations are processed at the end of each considered month but if, by chance from the start, the value of the old car is bigger than the value of the new one or equal there is no saving to be made, no need to wait so he can at the beginning of the month buy the new car:

nbMonths(12000, 8000, 1000, 1.5) should return [0, 4000]
nbMonths(8000, 8000, 1000, 1.5) should return [0, 0]

We don't take care of a deposit of savings in a bank:-)

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

Wir brauchen einen Loop!

Schritt 2

Wir müssen solange loopen, wie der aktuelle “Kontostand” (aus Preisdifferenz und Erspartem) negativ ist.

Schritt 3

Für jede Iteration müssen wir den neuen Kontostand berechnen.

Schritt 4

Dafür müssen wir erst mal in geraden Monaten den Preisverfall-Prozentsatz um 0.5 erhöhen.

Schritt 5

Dann können wir den Preisverfall für den aktuellen Monat berechnen.

Schritt 6

Und dann den aktuellen Preisunterschied beider Autos.

Schritt 7

Dann noch die Sparrate dazu addieren und wir haben unseren neuen Kontostand.

Code

Geil. Übersetzen wir unseren Pseudo-Code in TypeScript:

Lösungsschritte
Meine erste Zeile:
export function nbMonths(startPriceOld: number, startPriceNew: number, savingPerMonth: number, percentLossByMonth: number): number[] {
Dann lege ich mir ein paar Variablen an:
let currPercentLossByMonth = percentLossByMonth;
let currPriceDiffCars = startPriceOld - startPriceNew;
let balance = currPriceDiffCars;
let numMonths = 0;
let savings = 0;

balance steht hier für unseren aktuellen “Kontostand”.

Jetzt unser Loop:
  while (balance < 0) {

Ich entscheide mir hier für eine while-Schleife.

Erst mal erhöhe ich die Gesamt-Sparsumme und den aktuellen Monat:
savings += savingPerMonth;
numMonths++;
Dann können wir kucken, ob wir die aktuelle Preisverfallrate erhöhen müssen:
if (numMonths % 2 === 0) currPercentLossByMonth += 0.5;

Wenn ja, tun wir das.

Mir der aktuellen Preisverfallrate können wir dann den aktuellen Preisverfall beider Autos berechnen:
const currPriceLossCars = (currPriceDiffCars * currPercentLossByMonth) / 100;
Und damit dann den aktuellen Preisunterschied beider Autos berechnen:
currPriceDiffCars -= currPriceLossCars;
Jetzt noch den neuen Kontostand berechnen:
    balance = currPriceDiffCars + savings;
  }

Wir addieren einfach unsere Gesamtsparsumme zum aktuellen Preisunterschied hinzu.

Und nach dem Loop unser Ergebnis zurückgeben:
  return [numMonths, Math.round(balance)];
}
Voilá! 💪

Fragen?

Komplettlösung
export function nbMonths(
  startPriceOld: number,
  startPriceNew: number,
  savingPerMonth: number,
  percentLossByMonth: number,
): number[] {
  let currPercentLossByMonth = percentLossByMonth;
  let currPriceDiffCars = startPriceOld - startPriceNew;
  let balance = currPriceDiffCars;
  let numMonths = 0;
  let savings = 0;

  while (balance < 0) {
    savings += savingPerMonth;
    numMonths++;

    if (numMonths % 2 === 0) currPercentLossByMonth += 0.5;

    const currPriceLossCars =
      (currPriceDiffCars * currPercentLossByMonth) / 100;
    currPriceDiffCars -= currPriceLossCars;

    balance = currPriceDiffCars + savings;
  }

  return [numMonths, Math.round(balance)];
}

Feedback

Schreib mir!