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