Я сейчас решаю этот ката: «Как далеко я пойду?» !
В описании сказано:
Вы недавно обнаружили, что лошадипутешествуйте по уникальной схеме - они либо бегут (на максимальной скорости), либо отдыхают (стоят на месте).
Вот пример того, как может двигаться одна конкретная лошадь:
Лошадь Блейз можетбегите со скоростью 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;
Я также прочитал: