jimi
9 years ago
commit
58d0d37b6e
4 changed files with 225 additions and 0 deletions
-
23README.md
-
78cases_test.go
-
41clock.go
-
83clock_test.go
@ -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) |
@ -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, |
|||
}, |
|||
} |
@ -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 |
|||
} |
@ -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) |
|||
} |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue