ðŸŽ‰ Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io ðŸŽ‰

# domnikl's solution

## to Clock in the Kotlin Track

Published at Nov 16 2019 · 0 comments
Instructions
Test suite
Solution

#### Note:

This exercise has changed since this solution was written.

Implement a clock that handles times without dates.

You should be able to add and subtract minutes to it.

Two clocks that represent the same time should be equal to each other.

## Setup

Go through the setup instructions for Kotlin to install the necessary dependencies:

https://exercism.io/tracks/kotlin/installation

## Making the test suite pass

Execute the tests with:

``````\$ gradlew test
``````

Use `gradlew.bat` if you're on Windows

In the test suites all tests but the first have been skipped.

Once you get a test passing, you can enable the next one by removing the `@Ignore` annotation.

## Source

Pairing session with Erin Drummond https://twitter.com/ebdrummond

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

``````import org.junit.Ignore
import org.junit.Test
import kotlin.test.assertEquals

@Ignore
@Test
val clock = Clock(10, 0)
assertEquals("10:03", clock.toString())
}

@Ignore
@Test
val clock = Clock(6, 41)
assertEquals("06:41", clock.toString())
}

@Ignore
@Test
val clock = Clock(0, 45)
assertEquals("01:25", clock.toString())
}

@Ignore
@Test
val clock = Clock(10, 0)
assertEquals("11:01", clock.toString())
}

@Ignore
@Test
val clock = Clock(0, 45)
assertEquals("03:25", clock.toString())
}

@Ignore
@Test
val clock = Clock(23, 59)
assertEquals("00:01", clock.toString())
}

@Ignore
@Test
val clock = Clock(5, 32)
assertEquals("06:32", clock.toString())
}

@Ignore
@Test
val clock = Clock(1, 1)
assertEquals("11:21", clock.toString())
}

}``````

### ClockCreationTest.kt

``````import org.junit.Ignore
import org.junit.Test
import kotlin.test.assertEquals

class ClockCreationTest {

@Test
fun canPrintTimeOnTheHour() {
assertEquals("08:00", Clock(8, 0).toString())
}

@Ignore
@Test
fun canPrintTimeWithMinutes() {
assertEquals("11:09", Clock(11, 9).toString())
}

@Ignore
@Test
fun midnightPrintsAsZero() {
assertEquals("00:00", Clock(24, 0).toString())
}

@Ignore
@Test
fun hourRollsOver() {
assertEquals("01:00", Clock(25, 0).toString())
}

@Ignore
@Test
fun hourRollsOverContinuously() {
assertEquals("04:00", Clock(100, 0).toString())
}

@Ignore
@Test
fun sixtyMinutesIsNextHour() {
assertEquals("02:00", Clock(1, 60).toString())
}

@Ignore
@Test
fun minutesRollOver() {
assertEquals("02:40", Clock(0, 160).toString())
}

@Ignore
@Test
fun minutesRollOverContinuously() {
assertEquals("04:43", Clock(0, 1723).toString())
}

@Ignore
@Test
fun hourAndMinutesRollOver() {
assertEquals("03:40", Clock(25, 160).toString())
}

@Ignore
@Test
fun hourAndMinutesRollOverContinuously() {
assertEquals("11:01", Clock(201, 3001).toString())
}

@Ignore
@Test
fun hourAndMinutesRollOverToExactlyMidnight() {
assertEquals("00:00", Clock(72, 8640).toString())
}

@Ignore
@Test
fun negativeHour() {
assertEquals("23:15", Clock(-1, 15).toString())
}

@Ignore
@Test
fun negativeHourRollsOver() {
assertEquals("23:00", Clock(-25, 0).toString())
}

@Ignore
@Test
fun negativeHourRollsOverContinuously() {
assertEquals("05:00", Clock(-91, 0).toString())
}

@Ignore
@Test
fun negativeMinutes() {
assertEquals("00:20", Clock(1, -40).toString())
}

@Ignore
@Test
fun negativeMinutesRollOver() {
assertEquals("22:20", Clock(1, -160).toString())
}

@Ignore
@Test
fun negativeMinutesRollOverContinuously() {
assertEquals("16:40", Clock(1, -4820).toString())
}

@Ignore
@Test
fun negativeHourAndMinutesBothRollOver() {
assertEquals("20:20", Clock(-25, -160).toString())
}

@Ignore
@Test
fun negativeHourAndMinutesBothRollOverContinuously() {
assertEquals("22:10", Clock(-121, -5810).toString())
}

@Ignore
@Test
fun fullClockAndZeroedClock(){
val first = Clock(24,0)
val second = Clock(0,0)
assertEquals(first, second)
}

}``````

### ClockEqualTest.kt

``````import org.junit.Ignore
import org.junit.Test
import kotlin.test.assertNotEquals
import kotlin.test.assertEquals

class ClockEqualTest {

@Ignore
@Test
fun clocksWithSameTimeAreEqual() {
assertEquals(Clock(15, 37), Clock(15, 37))
}

@Ignore
@Test
fun clocksAMinuteApartAreNotEqual() {
assertNotEquals(Clock(15, 36), Clock(15, 37))
}

@Ignore
@Test
fun clocksAnHourApartAreNotEqual() {
assertNotEquals(Clock(14, 37), Clock(15, 37))
}

@Ignore
@Test
fun clocksWithHourOverflow() {
assertEquals(Clock(10, 37), Clock(34, 37))
}

@Ignore
@Test
fun clocksWithHourOverflowBySeveralDays() {
assertEquals(Clock(3, 11), Clock(99, 11))
}

@Ignore
@Test
fun clocksWithNegateHour() {
assertEquals(Clock(22, 40), Clock(-2, 40))
}

@Ignore
@Test
fun clocksWithNegativeHourThatWraps() {
assertEquals(Clock(17, 3), Clock(-31, 3))
}

@Ignore
@Test
fun clocksWithNegativeHourThatWrapsMultipleTimes() {
assertEquals(Clock(13, 49), Clock(-83, 49))
}

@Ignore
@Test
fun clocksWithMinuteOverflow() {
assertEquals(Clock(0, 1), Clock(0, 1441))
}

@Ignore
@Test
fun clocksWithMinuteOverflowBySeveralDays() {
assertEquals(Clock(2, 2), Clock(2, 4322))
}

@Ignore
@Test
fun clocksWithNegativeMinutes() {
assertEquals(Clock(2, 40), Clock(3, -20))
}

@Ignore
@Test
fun clocksWithNegativeMinutesThatWraps() {
assertEquals(Clock(4, 10), Clock(5, -1490))
}

@Ignore
@Test
fun clocksWithNegativeMinutesThatWrapsMultipleTimes() {
assertEquals(Clock(6, 15), Clock(6, -4305))
}

@Ignore
@Test
fun clocksWithNegativeHoursAndMinutes() {
assertEquals(Clock(7, 32), Clock(-12, -268))
}

@Ignore
@Test
fun clocksWithNegativeHoursAndMinutesThatWrap() {
assertEquals(Clock(18, 7), Clock(-54, -11513))
}

}``````

### ClockSubtractTest.kt

``````import org.junit.Ignore
import org.junit.Test
import kotlin.test.assertEquals

class ClockSubtractTest{

@Ignore
@Test
fun subtractMinutes() {
val clock = Clock(10, 3)
clock.subtract(3)
assertEquals("10:00", clock.toString())
}

@Ignore
@Test
fun subtractToPreviousHour() {
val clock = Clock(10, 3)
clock.subtract(30)
assertEquals("09:33", clock.toString())
}

@Ignore
@Test
fun subtractAcrossMidnight() {
val clock = Clock(0, 3)
clock.subtract(4)
assertEquals("23:59", clock.toString())
}

@Ignore
@Test
fun subtractMoreThanTwoHours() {
val clock = Clock(0, 0)
clock.subtract(160)
assertEquals("21:20", clock.toString())
}

@Ignore
@Test
fun subtractMoreThanTwoHoursWithBorrow() {
val clock = Clock(6, 15)
clock.subtract(160)
assertEquals("03:35", clock.toString())
}

@Ignore
@Test
fun subtractMoreThanOneDay() {
val clock = Clock(5, 32)
clock.subtract(1500)
assertEquals("04:32", clock.toString())
}

@Ignore
@Test
fun subtractMoreThanTwoDays() {
val clock = Clock(2, 20)
clock.subtract(3000)
assertEquals("00:20", clock.toString())
}
}``````
``````import kotlin.math.abs

class Clock(private var hours: Int, private var minutes: Int) {
init {
normalize()
}

override fun equals(other: Any?) = when(other) {
is Clock -> hours == other.hours && minutes == other.minutes
else -> false
}

override fun toString(): String {
return "%02d:%02d".format(hours, minutes)
}

fun subtract(minutes: Int) {
this.minutes -= minutes
normalize()
}

this.minutes += minutes
normalize()
}

private fun normalize() {
if (abs(minutes) >= 60) {
hours += minutes / 60
minutes %= 60
}

if (minutes < 0) {
hours -= 1
minutes += 60
}

if (abs(hours) >= 24) {
hours %= 24
}

if (hours < 0) {
hours += 24
}
}
}``````