Browse Source

Initial commit...

fails to roll back hour when required by negative minutes
master
jimi 9 years ago
commit
58d0d37b6e
  1. 23
      README.md
  2. 78
      cases_test.go
  3. 41
      clock.go
  4. 83
      clock_test.go

23
README.md

@ -0,0 +1,23 @@
# 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 [view source](https://twitter.com/ebdrummond)

78
cases_test.go

@ -0,0 +1,78 @@
package clock
// Source: exercism/x-common
// Commit: 269f498 Merge pull request #48 from soniakeys/custom-set-json
// Test creating a new clock with an initial time.
var timeTests = []struct {
h, m int
want string
}{
{8, 0, "08:00"}, // on the hour
{9, 0, "09:00"}, // on the hour
{11, 9, "11:09"}, // past the hour
{11, 19, "11:19"}, // past the hour
{24, 0, "00:00"}, // midnight is zero hours
{25, 0, "01:00"}, // hour rolls over
{1, 60, "02:00"}, // sixty minutes is next hour
{0, 160, "02:40"}, // minutes roll over
{25, 160, "03:40"}, // hour and minutes roll over
{-1, 15, "23:15"}, // negative hour
{-25, 0, "23:00"}, // negative hour rolls over
{1, -40, "00:20"}, // negative minutes
{1, -160, "22:20"}, // negative minutes roll over
{-25, -160, "20:20"}, // negative hour and minutes both roll over
}
// Test adding and subtracting minutes.
var addTests = []struct {
h, m, a int
want string
}{
{10, 0, 3, "10:03"}, // add minutes
{0, 45, 40, "01:25"}, // add to next hour
{10, 0, 61, "11:01"}, // add more than one hour
{23, 59, 2, "00:01"}, // add across midnight
{5, 32, 1500, "06:32"}, // add more than one day (1500 min = 25 hrs)
{0, 45, 160, "03:25"}, // add more than two hours with carry
{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
{5, 32, -1500, "04:32"}, // subtract more than one day (1500 min = 25 hrs)
{6, 15, -160, "03:35"}, // subtract more than two hours with borrow
}
// 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 set 24 hours apart
{
hm{10, 37},
hm{34, 37},
true,
},
}

41
clock.go

@ -0,0 +1,41 @@
package clock
import "fmt"
const (
testVersion = 3
minutesPerHour = 60
hoursPerDay = 24
)
type Clock struct {
hour int
minutes int
}
func New(hour, minute int) Clock {
h, m := adjustTime(hour, minute)
return Clock{h, m}
}
func (c Clock) String() string {
return fmt.Sprintf("%02d:%02d", c.hour, c.minutes)
}
func (c Clock) Add(minutes int) Clock {
min := c.minutes + minutes
c.hour, c.minutes = adjustTime(c.hour, min)
return c
}
func adjustTime(h, m int) (int, int) {
h = (h + (m / minutesPerHour)) % hoursPerDay
if h < 0 {
h += hoursPerDay
}
m = m % minutesPerHour
if m < 0 {
m += minutesPerHour
}
return h, m
}

83
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 = 3
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)
}
}
}
Loading…
Cancel
Save