Skip to content

Commit

Permalink
Merge pull request #207 from vaskoz/day97
Browse files Browse the repository at this point in the history
Day97
  • Loading branch information
vaskoz committed Nov 30, 2018
2 parents 79b5caa + d56b053 commit 94c05f1
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,5 @@ problems from
* [Day 94](https://github.com/vaskoz/dailycodingproblem-go/issues/197)
* [Day 95](https://github.com/vaskoz/dailycodingproblem-go/issues/198)
* [Day 96](https://github.com/vaskoz/dailycodingproblem-go/issues/200)
* [Day 97](https://github.com/vaskoz/dailycodingproblem-go/issues/203)
* [Day 99](https://github.com/vaskoz/dailycodingproblem-go/issues/205)
42 changes: 42 additions & 0 deletions day97/problem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package day97

import (
"sort"
)

// TimestampedValue represents the value set at a particular time.
type TimestampedValue struct {
Time int
Value interface{}
}

// TimeMap is a map that is aware of changes over time.
type TimeMap struct {
data map[interface{}][]*TimestampedValue
}

// NewTimeMap returns a new timestamp aware map.
func NewTimeMap() *TimeMap {
return &TimeMap{make(map[interface{}][]*TimestampedValue)}
}

// Set a key-value pair with a particular timestamp.
func (tm *TimeMap) Set(key, value interface{}, time int) {
tm.data[key] = append(tm.data[key], &TimestampedValue{time, value})
sort.Slice(tm.data[key], func(i, j int) bool {
return tm.data[key][i].Time < tm.data[key][j].Time
})
}

// Get returns the value for a key at a particular time.
func (tm *TimeMap) Get(key interface{}, time int) interface{} {
pos := sort.Search(len(tm.data[key]), func(i int) bool {
return tm.data[key][i].Time > time
})
if pos <= 0 {
if len(tm.data[key]) == 0 || tm.data[key][0].Time > time {
return nil
}
}
return tm.data[key][pos-1].Value
}
50 changes: 50 additions & 0 deletions day97/problem_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package day97

import "testing"

func TestTimeMap(t *testing.T) {
t.Parallel()
d := NewTimeMap()
d.Set(1, 1, 0) // set key 1 to value 1 at time 0
d.Set(1, 2, 2) // set key 1 to value 2 at time 2
if result := d.Get(1, 1); result != 1 {
t.Errorf("get key 1 at time 1 should be 1")
}
if result := d.Get(1, 3); result != 2 {
t.Errorf("get key 1 at time 3 should be 2")
}
d.Set(1, 1, 5) // set key 1 to value 1 at time 5
if result := d.Get(1, 0); result != 1 {
t.Errorf("get key 1 at time 0 should be 1")
}
if result := d.Get(1, 10); result != 1 {
t.Errorf("get key 1 at time 10 should be 1")
}
d.Set(1, 1, 0) // set key 1 to value 1 at time 0
d.Set(1, 2, 0) // set key 1 to value 2 at time 0
if result := d.Get(1, 0); result != 2 {
t.Errorf("get key 1 at time 0 should be 2")
}
if result := d.Get(2, 0); result != nil {
t.Errorf("unused keys should return nil")
}
if result := d.Get(1, -1); result != nil {
t.Errorf("No value should be set back in time.")
}
}

func BenchmarkTimeMap(b *testing.B) {
d := NewTimeMap()
d.Set(1, 1, 0) // set key 1 to value 1 at time 0
d.Set(1, 2, 2) // set key 1 to value 2 at time 2
d.Set(1, 1, 5) // set key 1 to value 1 at time 5
for i := 0; i < b.N; i++ {
d.Get(1, 1)
d.Get(1, 3)
d.Get(1, 0)
d.Get(1, 10)
d.Get(1, 0)
d.Get(2, 0)
d.Get(1, -1)
}
}

0 comments on commit 94c05f1

Please sign in to comment.