diff --git a/README.md b/README.md index 6468c77..fd1c539 100644 --- a/README.md +++ b/README.md @@ -414,4 +414,5 @@ problems from * [Day 415](https://github.com/vaskoz/dailycodingproblem-go/issues/838) * [Day 416](https://github.com/vaskoz/dailycodingproblem-go/issues/840) * [Day 417](https://github.com/vaskoz/dailycodingproblem-go/issues/842) +* [Day 418](https://github.com/vaskoz/dailycodingproblem-go/issues/844) diff --git a/day418/problem.go b/day418/problem.go new file mode 100644 index 0000000..b22f869 --- /dev/null +++ b/day418/problem.go @@ -0,0 +1,63 @@ +package day418 + +// Bonuses determines how much bonus to give based on lines of code. +func Bonuses(loc []int) []int { + if len(loc) == 0 { + return nil + } else if len(loc) == 1 { + return []int{1} + } + + bonuses := make([]int, 0, len(loc)) + segs := segments(loc) + + for _, seg := range segs { + asc, run := seg.ascending, seg.run + segBonuses := make([]int, run) + + for i := range segBonuses { + segBonuses[i] = i + } + + if !asc { + for i := 0; i < len(segBonuses)/2; i++ { + segBonuses[i], segBonuses[len(segBonuses)-1-i] = segBonuses[len(segBonuses)-1-i], segBonuses[i] + } + } + + bonuses = append(bonuses, segBonuses...) + } + + for i := range bonuses { + bonuses[i]++ + } + + return bonuses +} + +type segment struct { + ascending bool + run int +} + +func segments(loc []int) []segment { + asc := loc[1] > loc[0] + prev := loc[0] + + var start int + + var segs []segment + + slice := loc[1:] + for i, num := range slice { + if (asc && num < prev) || (!asc && num > prev) { + segs = append(segs, segment{asc, i - start + 1}) + start = i + 1 + asc = !asc + } + + prev = num + } + + return append(segs, segment{asc, len(loc) - start}) +} diff --git a/day418/problem_test.go b/day418/problem_test.go new file mode 100644 index 0000000..ac3e71f --- /dev/null +++ b/day418/problem_test.go @@ -0,0 +1,36 @@ +package day418 + +import ( + "reflect" + "testing" +) + +// nolint +var testcases = []struct { + locs []int + bonuses []int +}{ + {[]int{10, 40, 200, 1000, 60, 30}, []int{1, 2, 3, 4, 2, 1}}, + {[]int{}, nil}, + {nil, nil}, + {[]int{1000}, []int{1}}, + {[]int{10, 40, 200, 1000, 900, 800, 30}, []int{1, 2, 3, 4, 3, 2, 1}}, +} + +func TestBonuses(t *testing.T) { + t.Parallel() + + for _, tc := range testcases { + if bonuses := Bonuses(tc.locs); !reflect.DeepEqual(bonuses, tc.bonuses) { + t.Errorf("Expected %v, got %v", tc.bonuses, bonuses) + } + } +} + +func BenchmarkBonuses(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, tc := range testcases { + Bonuses(tc.locs) + } + } +}