summaryrefslogtreecommitdiff
path: root/go/clock
diff options
context:
space:
mode:
Diffstat (limited to 'go/clock')
-rw-r--r--go/clock/README.md27
-rw-r--r--go/clock/cases_test.go152
-rw-r--r--go/clock/clock.go29
-rw-r--r--go/clock/clock_test.go83
4 files changed, 291 insertions, 0 deletions
diff --git a/go/clock/README.md b/go/clock/README.md
new file mode 100644
index 0000000..84f1f51
--- /dev/null
+++ b/go/clock/README.md
@@ -0,0 +1,27 @@
+# Clock
+
+Implement a clock that handles times without dates.
+
+Create a clock that is independent of date.
+
+You should be able to add and subtract minutes to it.
+
+Two clocks that represent the same time should be equal to each other.
+
+To run the tests simply run the command `go test` in the exercise directory.
+
+If the test suite contains benchmarks, you can run these with the `-bench`
+flag:
+
+ go test -bench .
+
+For more detailed info about the Go track see the [help
+page](http://exercism.io/languages/go).
+
+## Source
+
+Pairing session with Erin Drummond [https://twitter.com/ebdrummond](https://twitter.com/ebdrummond)
+
+## Submitting Incomplete Problems
+It's possible to submit an incomplete solution so you can see how others have completed the exercise.
+
diff --git a/go/clock/cases_test.go b/go/clock/cases_test.go
new file mode 100644
index 0000000..3884510
--- /dev/null
+++ b/go/clock/cases_test.go
@@ -0,0 +1,152 @@
+package clock
+
+// Source: exercism/x-common
+// Commit: 180638f Merge pull request #217 from ErikSchierboom/patch-2
+
+// Test creating a new clock with an initial time.
+var timeTests = []struct {
+ h, m int
+ want string
+}{
+ {8, 0, "08:00"}, // on the hour
+ {11, 9, "11:09"}, // past the hour
+ {24, 0, "00:00"}, // midnight is zero hours
+ {25, 0, "01:00"}, // hour rolls over
+ {100, 0, "04:00"}, // hour rolls over continuously
+ {1, 60, "02:00"}, // sixty minutes is next hour
+ {0, 160, "02:40"}, // minutes roll over
+ {0, 1723, "04:43"}, // minutes roll over continuously
+ {25, 160, "03:40"}, // hour and minutes roll over
+ {201, 3001, "11:01"}, // hour and minutes roll over continuously
+ {72, 8640, "00:00"}, // hour and minutes roll over to exactly midnight
+ {-1, 15, "23:15"}, // negative hour
+ {-25, 0, "23:00"}, // negative hour rolls over
+ {-91, 0, "05:00"}, // negative hour rolls over continuously
+ {1, -40, "00:20"}, // negative minutes
+ {1, -160, "22:20"}, // negative minutes roll over
+ {1, -4820, "16:40"}, // negative minutes roll over continuously
+ {-25, -160, "20:20"}, // negative hour and minutes both roll over
+ {-121, -5810, "22:10"}, // negative hour and minutes both roll over continuously
+}
+
+// Test adding and subtracting minutes.
+var addTests = []struct {
+ h, m, a int
+ want string
+}{
+ {10, 0, 3, "10:03"}, // add minutes
+ {6, 41, 0, "06:41"}, // add no minutes
+ {0, 45, 40, "01:25"}, // add to next hour
+ {10, 0, 61, "11:01"}, // add more than one hour
+ {0, 45, 160, "03:25"}, // add more than two hours with carry
+ {23, 59, 2, "00:01"}, // add across midnight
+ {5, 32, 1500, "06:32"}, // add more than one day (1500 min = 25 hrs)
+ {1, 1, 3500, "11:21"}, // add more than two days
+ {10, 3, -3, "10:00"}, // subtract minutes
+ {10, 3, -30, "09:33"}, // subtract to previous hour
+ {10, 3, -70, "08:53"}, // subtract more than an hour
+ {0, 3, -4, "23:59"}, // subtract across midnight
+ {0, 0, -160, "21:20"}, // subtract more than two hours
+ {6, 15, -160, "03:35"}, // subtract more than two hours with borrow
+ {5, 32, -1500, "04:32"}, // subtract more than one day (1500 min = 25 hrs)
+ {2, 20, -3000, "00:20"}, // subtract more than two days
+}
+
+// Construct two separate clocks, set times, test if they are equal.
+type hm struct{ h, m int }
+
+var eqTests = []struct {
+ c1, c2 hm
+ want bool
+}{
+ // clocks with same time
+ {
+ hm{15, 37},
+ hm{15, 37},
+ true,
+ },
+ // clocks a minute apart
+ {
+ hm{15, 36},
+ hm{15, 37},
+ false,
+ },
+ // clocks an hour apart
+ {
+ hm{14, 37},
+ hm{15, 37},
+ false,
+ },
+ // clocks with hour overflow
+ {
+ hm{10, 37},
+ hm{34, 37},
+ true,
+ },
+ // clocks with hour overflow by several days
+ {
+ hm{3, 11},
+ hm{99, 11},
+ true,
+ },
+ // clocks with negative hour
+ {
+ hm{22, 40},
+ hm{-2, 40},
+ true,
+ },
+ // clocks with negative hour that wraps
+ {
+ hm{17, 3},
+ hm{-31, 3},
+ true,
+ },
+ // clocks with negative hour that wraps multiple times
+ {
+ hm{13, 49},
+ hm{-83, 49},
+ true,
+ },
+ // clocks with minute overflow
+ {
+ hm{0, 1},
+ hm{0, 1441},
+ true,
+ },
+ // clocks with minute overflow by several days
+ {
+ hm{2, 2},
+ hm{2, 4322},
+ true,
+ },
+ // clocks with negative minute
+ {
+ hm{2, 40},
+ hm{3, -20},
+ true,
+ },
+ // clocks with negative minute that wraps
+ {
+ hm{4, 10},
+ hm{5, -1490},
+ true,
+ },
+ // clocks with negative minute that wraps multiple times
+ {
+ hm{6, 15},
+ hm{6, -4305},
+ true,
+ },
+ // clocks with negative hours and minutes
+ {
+ hm{7, 32},
+ hm{-12, -268},
+ true,
+ },
+ // clocks with negative hours and minutes that wrap
+ {
+ hm{18, 7},
+ hm{-54, -11513},
+ true,
+ },
+}
diff --git a/go/clock/clock.go b/go/clock/clock.go
new file mode 100644
index 0000000..036a69b
--- /dev/null
+++ b/go/clock/clock.go
@@ -0,0 +1,29 @@
+package clock
+
+import "fmt"
+
+const testVersion = 4
+
+type Clock struct {
+ hour, minute int
+}
+
+func New(hour, minute int) Clock {
+ for minute < 0 {
+ minute += 60
+ hour -= 1
+ }
+ hour += minute / 60
+ for hour < 0 {
+ hour += 24
+ }
+ return Clock{hour % 24, minute % 60}
+}
+
+func (c Clock) String() string {
+ return fmt.Sprintf("%02d:%02d", c.hour, c.minute)
+}
+
+func (c Clock) Add(minutes int) Clock {
+ return New(c.hour, c.minute+minutes)
+}
diff --git a/go/clock/clock_test.go b/go/clock/clock_test.go
new file mode 100644
index 0000000..7642c41
--- /dev/null
+++ b/go/clock/clock_test.go
@@ -0,0 +1,83 @@
+package clock
+
+import (
+ "reflect"
+ "testing"
+)
+
+// Clock type API:
+//
+// New(hour, minute int) Clock // a "constructor"
+// (Clock) String() string // a "stringer"
+// (Clock) Add(minutes int) Clock
+//
+// The Add method should also handle subtraction by accepting negative values.
+// To satisfy the readme requirement about clocks being equal, values of
+// your Clock type need to work with the == operator.
+//
+// It might help to study the time.Time type in the standard library
+// (https://golang.org/pkg/time/#Time) as a model. See how constructors there
+// (Date and Now) return Time values rather than pointers. Note also how
+// most time.Time methods have value receivers rather than pointer receivers.
+// For more background on this read
+// https://github.com/golang/go/wiki/CodeReviewComments#receiver-type.
+
+const targetTestVersion = 4
+
+func TestCreateClock(t *testing.T) {
+ if testVersion != targetTestVersion {
+ t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
+ }
+ for _, n := range timeTests {
+ if got := New(n.h, n.m); got.String() != n.want {
+ t.Fatalf("New(%d, %d) = %q, want %q", n.h, n.m, got, n.want)
+ }
+ }
+ t.Log(len(timeTests), "test cases")
+}
+
+func TestAddMinutes(t *testing.T) {
+ for _, a := range addTests {
+ if got := New(a.h, a.m).Add(a.a); got.String() != a.want {
+ t.Fatalf("New(%d, %d).Add(%d) = %q, want %q",
+ a.h, a.m, a.a, got, a.want)
+ }
+ }
+ t.Log(len(addTests), "test cases")
+}
+
+func TestCompareClocks(t *testing.T) {
+ for _, e := range eqTests {
+ clock1 := New(e.c1.h, e.c1.m)
+ clock2 := New(e.c2.h, e.c2.m)
+ got := clock1 == clock2
+ if got != e.want {
+ t.Log("Clock1:", clock1)
+ t.Log("Clock2:", clock2)
+ t.Logf("Clock1 == Clock2 is %t, want %t", got, e.want)
+ if reflect.DeepEqual(clock1, clock2) {
+ t.Log("(Hint: see comments in clock_test.go.)")
+ }
+ t.FailNow()
+ }
+ }
+ t.Log(len(eqTests), "test cases")
+}
+
+func BenchmarkAddMinutes(b *testing.B) {
+ c := New(12, 0)
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ for _, a := range addTests {
+ c.Add(a.a)
+ }
+ }
+}
+
+func BenchmarkCreateClocks(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ for _, n := range timeTests {
+ New(n.h, n.m)
+ }
+ }
+}