Skip to content

Commit 3b5530c

Browse files
committedNov 19, 2020
Add golang solution for 008, 009, 010
1 parent e78ca44 commit 3b5530c

File tree

9 files changed

+308
-46
lines changed

9 files changed

+308
-46
lines changed
 

‎001-050/008/go/code.go

+53-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,57 @@
66
// TestSolution for test cases
77
package _008
88

9-
// Solution for 008
10-
func Solution() interface{} {
11-
return nil
9+
// Node implements binary tree
10+
type Node struct {
11+
value int // value of Node
12+
isUnival bool // is unival tree (having universal value)
13+
14+
left, right *Node // left and right children
15+
16+
count int // no. of unival subtrees in the node (including itself)
17+
}
18+
19+
func NewNode(value int) *Node {
20+
return &Node{value: value}
21+
}
22+
23+
func (n *Node) GetValue() int {
24+
return n.value
25+
}
26+
27+
func (n *Node) AddChild(ch *Node) *Node {
28+
if n == nil {
29+
panic("nil node")
30+
}
31+
if n.left == nil {
32+
n.left = ch
33+
return ch
34+
}
35+
if n.right == nil {
36+
n.right = ch
37+
return ch
38+
}
39+
panic("binary tree node can only have two nodes")
40+
}
41+
42+
// CountUnivals is solution for 008
43+
func (n *Node) CountUnivals() int {
44+
if n == nil {
45+
return 0
46+
}
47+
if n.left == nil && n.right == nil {
48+
// leaf Node is unival
49+
n.isUnival = true
50+
return 1
51+
}
52+
n.count += n.left.CountUnivals()
53+
n.count += n.right.CountUnivals()
54+
if n.left != nil && n.right != nil &&
55+
n.left.isUnival && n.right.isUnival &&
56+
n.left.value == n.right.value && n.value == n.left.value {
57+
// n.value is universal value
58+
n.isUnival = true
59+
n.count++
60+
}
61+
return n.count
1262
}

‎001-050/008/go/code_test.go

+52-11
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,66 @@ package _008
66

77
import (
88
"reflect"
9+
"strconv"
910
"testing"
1011
)
1112

12-
func TestSolution(t *testing.T) {
13-
type args struct {
13+
func buildTree(values []int, edges map[int][]int) *Node {
14+
if len(values) < 1 {
15+
panic("root => 1")
1416
}
15-
type want struct {
17+
root := NewNode(values[1])
18+
19+
nodeMp := map[int]*Node{1: root}
20+
newNode := func(val int) *Node {
21+
kn, ok := nodeMp[val]
22+
if !ok {
23+
kn = NewNode(values[val])
24+
nodeMp[val] = kn
25+
}
26+
return kn
27+
}
28+
29+
for key, list := range edges {
30+
kn := newNode(key)
31+
if len(list) >= 1 {
32+
kn.AddChild(newNode(list[0]))
33+
}
34+
if len(list) >= 2 {
35+
kn.AddChild(newNode(list[1]))
36+
}
1637
}
38+
return root
39+
}
40+
41+
func TestOne(t *testing.T) {
1742
tests := []struct {
18-
name string
19-
args args
20-
want want
43+
values []int
44+
edges map[int][]int
45+
noOfUnivals int
2146
}{
22-
// TODO: Add test cases.
47+
{
48+
values: []int{-1, 0, 1, 0, 1, 0, 1, 1},
49+
edges: map[int][]int{
50+
1: {2, 3},
51+
3: {4, 5},
52+
4: {6, 7},
53+
},
54+
noOfUnivals: 5,
55+
},
56+
{
57+
values: []int{-1, 0, 1},
58+
edges: map[int][]int{
59+
1: {2},
60+
},
61+
noOfUnivals: 1,
62+
},
2363
}
24-
for _, tt := range tests {
25-
t.Run(tt.name, func(t *testing.T) {
26-
if got := Solution(); !reflect.DeepEqual(got, tt.want) {
27-
t.Errorf("Solution() = %v, want %v", got, tt.want)
64+
for i, tt := range tests {
65+
t.Run(strconv.Itoa(i), func(t *testing.T) {
66+
tree := buildTree(tt.values, tt.edges)
67+
if got := tree.CountUnivals(); !reflect.DeepEqual(got, tt.noOfUnivals) {
68+
t.Errorf("tree.CountUnivals() = %v, want %v", got, tt.noOfUnivals)
2869
}
2970
})
3071
}

‎001-050/009/c++/code.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ void second() {
5757
cin >> cur;
5858
if (i == 0) {
5959
b = max(a, cur);
60+
ans = b;
6061
continue;
6162
}
6263
ans = max(b, max(cur, a + cur));

‎001-050/009/c++/in.txt

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
7
1+
10
22
5
33
2 4 6 2 5
44
4
@@ -13,3 +13,9 @@
1313
-2 -4 -6 -1 -5
1414
5
1515
-2 -4 -6 -1 5
16+
1
17+
1
18+
2
19+
1 2
20+
1
21+
-1

‎001-050/009/c++/out.txt

+3
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@
55
0
66
0
77
5
8+
1
9+
2
10+
0

‎001-050/009/go/code.go

+18-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,22 @@
77
package _009
88

99
// Solution for 009
10-
func Solution() interface{} {
11-
return nil
10+
func Solution(in []int) int {
11+
n := len(in)
12+
if n == 0 {
13+
return 0
14+
}
15+
max := func(a, b int) int {
16+
if a > b {
17+
return a
18+
}
19+
return b
20+
}
21+
// answers: current, till last index, till last second index
22+
ans, lastAns, lastSecAns := 0, 0, 0
23+
for _, cur := range in {
24+
ans = max(max(lastAns, lastSecAns), max(cur, lastSecAns+cur))
25+
lastAns, lastSecAns = ans, lastAns
26+
}
27+
return ans
1228
}

‎001-050/009/go/code_test.go

+46-11
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,59 @@ package _009
66

77
import (
88
"reflect"
9+
"strconv"
910
"testing"
1011
)
1112

1213
func TestSolution(t *testing.T) {
13-
type args struct {
14-
}
15-
type want struct {
16-
}
1714
tests := []struct {
18-
name string
19-
args args
20-
want want
15+
args []int
16+
want int
2117
}{
22-
// TODO: Add test cases.
18+
{
19+
args: []int{2, 4, 6, 2, 5},
20+
want: 13,
21+
},
22+
{
23+
args: []int{5, 1, 1, 5},
24+
want: 10,
25+
},
26+
{
27+
args: []int{-5, -1, -1, -5},
28+
want: 0,
29+
},
30+
{
31+
args: []int{5, 5, 10, 100, 10, 5, 5, 5, 10, 100, 10, 5, 5, 5, 10, 100, 10, 5, 5, 5, 10, 100, 10, 5, 5, 5, 10, 100, 10, 5, 5, 5, 10, 100, 10, 5, 5, 5, 10, 100, 10, 5, 5, 5, 10, 100, 10, 5, 5, 5, 10, 100, 10, 5, 5, 5, 10, 100, 10, 5},
32+
want: 1100,
33+
},
34+
{
35+
args: []int{-2, -4, -6, -2, -5},
36+
want: 0,
37+
},
38+
{
39+
args: []int{-2, -4, -6, -1, -5},
40+
want: 0,
41+
},
42+
{
43+
args: []int{-2, -4, -6, -1, 5},
44+
want: 5,
45+
},
46+
{
47+
args: []int{1},
48+
want: 1,
49+
},
50+
{
51+
args: []int{1, 2},
52+
want: 2,
53+
},
54+
{
55+
args: []int{-1},
56+
want: 0,
57+
},
2358
}
24-
for _, tt := range tests {
25-
t.Run(tt.name, func(t *testing.T) {
26-
if got := Solution(); !reflect.DeepEqual(got, tt.want) {
59+
for i, tt := range tests {
60+
t.Run(strconv.Itoa(i), func(t *testing.T) {
61+
if got := Solution(tt.args); !reflect.DeepEqual(got, tt.want) {
2762
t.Errorf("Solution() = %v, want %v", got, tt.want)
2863
}
2964
})

‎001-050/010/go/code.go

+83-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,87 @@
66
// TestSolution for test cases
77
package _010
88

9-
// Solution for 010
10-
func Solution() interface{} {
11-
return nil
9+
import (
10+
"errors"
11+
"sync"
12+
"time"
13+
)
14+
15+
var ErrSchedulerStopped = errors.New("scheduler has been stopped")
16+
17+
type Scheduler interface {
18+
// Schedule schedules fn after dur time with returned id until
19+
// it is not stopped using StopScheduling
20+
Schedule(fn func(), dur time.Duration) (int, error)
21+
// StopScheduling: stops Scheduler from scheduling any more, using
22+
// Schedule after StopScheduling() will return ErrSchedulerStopped
23+
StopScheduling()
24+
// Ack: helps acknowledge that the Schedule function is finished
25+
// using the int::id provided at time of Schedule()
26+
Ack() <-chan int
27+
}
28+
29+
// NewScheduler creates a new scheduler
30+
func NewScheduler() Scheduler {
31+
return newRunner()
32+
}
33+
34+
type runner struct {
35+
wg sync.WaitGroup
36+
list chan *job
37+
ack chan int
38+
size int // if -1 means closed
39+
}
40+
41+
func (r *runner) Schedule(fn func(), dur time.Duration) (int, error) {
42+
if r.size == -1 {
43+
return 0, ErrSchedulerStopped
44+
}
45+
r.size++
46+
r.list <- &job{dur: dur, fn: fn, id: r.size}
47+
return r.size, nil
48+
}
49+
50+
func (r *runner) StopScheduling() {
51+
defer close(r.ack)
52+
r.size = -1
53+
close(r.list)
54+
r.wg.Done() // self runner goroutine
55+
r.wg.Wait()
56+
}
57+
58+
func (r *runner) Ack() <-chan int {
59+
return r.ack
60+
}
61+
62+
func newRunner() *runner {
63+
rn := &runner{
64+
wg: sync.WaitGroup{},
65+
list: make(chan *job),
66+
ack: make(chan int),
67+
}
68+
rn.run()
69+
return rn
70+
}
71+
72+
func (r *runner) run() {
73+
r.wg.Add(1)
74+
go func() {
75+
for job := range r.list {
76+
job := job
77+
r.wg.Add(1)
78+
go func() {
79+
defer r.wg.Done()
80+
time.Sleep(job.dur)
81+
job.fn()
82+
r.ack <- job.id
83+
}()
84+
}
85+
}()
86+
}
87+
88+
type job struct {
89+
id int
90+
fn func()
91+
dur time.Duration
1292
}

‎001-050/010/go/code_test.go

+45-15
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,57 @@
55
package _010
66

77
import (
8-
"reflect"
98
"testing"
9+
"time"
1010
)
1111

12-
func TestSolution(t *testing.T) {
13-
type args struct {
12+
func nilError(t *testing.T, err error) {
13+
t.Helper()
14+
if err != nil {
15+
t.Error(err, "error should be nil")
1416
}
15-
type want struct {
17+
}
18+
19+
func TestScheduler(t *testing.T) {
20+
fn := func(d time.Duration) (func(), time.Duration) {
21+
return func() { t.Log("ran after", d) }, d
1622
}
17-
tests := []struct {
18-
name string
19-
args args
20-
want want
21-
}{
22-
// TODO: Add test cases.
23+
24+
mp, cnt := map[int]struct{}{}, 0
25+
check := func(id int, err error) {
26+
cnt++
27+
nilError(t, err)
28+
if _, ok := mp[id]; ok {
29+
t.Error("scheduled fn id must be unique")
30+
}
31+
mp[id] = struct{}{}
2332
}
24-
for _, tt := range tests {
25-
t.Run(tt.name, func(t *testing.T) {
26-
if got := Solution(); !reflect.DeepEqual(got, tt.want) {
27-
t.Errorf("Solution() = %v, want %v", got, tt.want)
33+
34+
// scheduler
35+
sch := NewScheduler()
36+
37+
// acknowledgement
38+
done := make(chan struct{})
39+
go func() {
40+
for id := range sch.Ack() {
41+
if id > cnt || id < 0 {
42+
t.Error("acknowledged id must be among the ids of scheduler", "id", id)
2843
}
29-
})
44+
}
45+
done <- struct{}{}
46+
}()
47+
48+
check(sch.Schedule(fn(time.Second)))
49+
check(sch.Schedule(fn(time.Millisecond)))
50+
check(sch.Schedule(fn(100 * time.Nanosecond)))
51+
52+
// stop scheduling
53+
sch.StopScheduling()
54+
55+
// try adding again
56+
if _, err := sch.Schedule(fn(time.Second)); err != ErrSchedulerStopped {
57+
t.Error("ErrSchedulerStopped error should be returned")
3058
}
59+
60+
<-done
3161
}

0 commit comments

Comments
 (0)
Please sign in to comment.