Как мы можем рассчитать пройденное расстояние с большими числами? - PullRequest
1 голос
/ 03 ноября 2019

Я сейчас решаю этот ката: «Как далеко я пойду?» !

В описании сказано:

Вы недавно обнаружили, что лошадипутешествуйте по уникальной схеме - они либо бегут (на максимальной скорости), либо отдыхают (стоят на месте).

Вот пример того, как может двигаться одна конкретная лошадь:

Лошадь Блейз можетбегите со скоростью 14 метров в секунду в течение 60 секунд, но затем должны отдыхать в течение 45 секунд.

Через 500 секунд Blaze пройдет 4200 метров.

Ваша задача - написать функцию, которая возвращаетдолго лошадь будет путешествовать через определенное время.

Ввод:
totalTime - How long the horse will be traveling (in seconds)

runTime - How long the horse can run for before having to rest (in seconds)

restTime - How long the horse have to rest for after running (in seconds)

speed - The max speed of the horse (in metres/second)

Я уже сделал исчисление вручную:

Дано: скорость = 14, runTime = 60,restTime = 45, totalTime = 500

-> Чтобы рассчитать, сколько времени бежит лошадь, мы рассчитываем следующее:

totalTime / (runTime + restTime) = 500 / (60 + 45)= 500/105 = 4.76 ... roundUp (totalTime) = 5

totalRunTime = 5* runTime = 5 * 60 = 300

-> Чтобы рассчитать расстояние, пройденное лошадью:

x = скорость * totalRunTime = 14 * 300 = 4200

Я перевел его как следующий код:

public class Kata {

    public static int travel(int totalTime, int runTime, int restTime, int speed) {
      int totalRunTime = 0;

      if(totalTime < runTime){
        totalRunTime = totalTime;
      }else{
        totalRunTime = (int)Math.ceil( (double)totalTime/(runTime + restTime) ) * runTime;
      }

      return speed * totalRunTime;
    }
}

Когда мы запускаем базовые тесты, он дает ожидаемый результат:

import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.junit.runners.JUnit4;


public class KataTest {

    @Test
    public void exampleTests() {
        assertEquals(4200, Kata.travel(500, 60, 45, 14));
        assertEquals(1120, Kata.travel(1000, 10, 127, 14));
        assertEquals(1000, Kata.travel(100, 10, 0, 10));
        assertEquals(1000, Kata.travel(100, 10, 0, 10));
        assertEquals(450, Kata.travel(25, 50, 120, 18));
    }
}

Однако, когда мы тестируем его с помощью расширенных примеров, сбольшие цифры показывают неточные результаты.

Например:

Дано: speed = 6, runTime = 34, restTime = 180, totalTime = 99094;ожидаемый результат - 94524, однако код, который я разместил, дает нам 94656

. Я написал трассировку от руки, чтобы понять, что делает мой код:

-> Чтобы рассчитать общее время, в течение которого работает эта лошадь:

totalTime / (runTime + restTime) = 99094 / (34 + 180) = 99094/214 = 463,05 ... roundUp (totalTime) = 464

totalRunTime = 464 * runTime = 464* 34 = 15776

-> Чтобы вычислить расстояние, пройденное лошадью:

x = скорость * totalRunTime = 6 * 15776 = 94656

Итак, тест, которыйтерпит неудачу:

import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.junit.runners.JUnit4;


public class KataTest {

    @Test
    public void biggerTests() {
        assertEquals(84954920, Kata.travel(35869784, 90, 100, 5));
    }
}

У меня есть интуиция, что код должен быть улучшен при преобразовании из double в int или при округлении с Math.ceil, но я не знаю, почему или как решитьЭто. Вот строка, которую, я думаю, мы могли бы улучшить:

totalRunTime = (int)Math.ceil( (double)totalTime/(runTime + restTime) ) * runTime;

Я также прочитал:

1 Ответ

2 голосов
/ 03 ноября 2019

Проблема не в округлении. Давайте рассмотрим пример travel(35869784, 90, 100, 5).

Согласно вашей формуле 35869784/(100+90) = 188788.336, округление дает нам 188789, умножение на runTime и speed дает нам 84,955,050 метров, в то время как правильный ответ составляет 84,954,920. ,Это не проблема округления. Формула неверна.

Почему? Рассмотрим пробег после последнего отдыха. Лошадь уже пробежала 188 788 полных итераций 90-х + 100-х, в течение которых она преодолела расстояние 84 954 600 метров за 35 869 720 секунд. После этих «полных» пробежек у лошади теперь есть только 64 секунды, что меньше, чем runTime!

Как далеко лошадь бежит за 64 секунды? 320 метровИтого всего 84,954,600 + 320 = 84,954,920 метров.

...