Skip to content

Commit 0dccba2

Browse files
committed
fix: Implement a dynamic programming solution for Day 2 (#1)
1 parent 1d713b4 commit 0dccba2

File tree

2 files changed

+46
-23
lines changed

2 files changed

+46
-23
lines changed

‎day_02/main.go‎

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,35 +26,50 @@ func main() {
2626
fmt.Println("Part 2 result", partTwo(processedInput))
2727
}
2828

29-
func isSafe(values []int, startingValue int) int {
30-
previousValue := values[0]
31-
isIncreasing := values[startingValue] > values[0]
32-
33-
errors := 0
34-
35-
for _, value := range values[startingValue:] {
36-
difference := int(math.Abs(float64(value - previousValue)))
37-
if difference > 3 || difference < 1 {
38-
errors += 1
39-
continue
29+
// I know it's overkill for this task,
30+
// but i wanted to solve it in O(N),
31+
// so I used *dynamic programming*!
32+
func dpCheck(height []int) int {
33+
n := len(height)
34+
35+
increasing := make([]int, n)
36+
decreasing := make([]int, n)
37+
for i := range increasing {
38+
increasing[i] = math.MaxInt32
39+
decreasing[i] = math.MaxInt32
40+
}
41+
increasing[0], decreasing[0] = 0, 0
42+
43+
for i := 1; i < n; i++ {
44+
if diff := utils.Abs(height[i] - height[i-1]); diff >= 1 && diff <= 3 {
45+
if height[i] > height[i-1] {
46+
increasing[i] = min(increasing[i], increasing[i-1])
47+
} else if height[i] < height[i-1] {
48+
decreasing[i] = min(decreasing[i], decreasing[i-1])
49+
}
4050
}
4151

42-
if isIncreasing != (value > previousValue) {
43-
errors += 1
44-
continue
45-
}
52+
if i > 1 {
53+
if diff := utils.Abs(height[i] - height[i-2]); diff < 1 || diff > 3 {
54+
continue
55+
}
4656

47-
previousValue = value
57+
if height[i] > height[i-2] {
58+
increasing[i] = min(increasing[i], increasing[i-2]+1)
59+
} else if height[i] < height[i-2] {
60+
decreasing[i] = min(decreasing[i], decreasing[i-2]+1)
61+
}
62+
}
4863
}
4964

50-
return errors
65+
return min(increasing[n-1], decreasing[n-1])
5166
}
5267

5368
func partOne(input [][]int) int {
5469
var result int
5570

5671
for _, report := range input {
57-
if isSafe(report, 1) == 0 {
72+
if dpCheck(report) == 0 {
5873
result += 1
5974
}
6075
}
@@ -67,12 +82,13 @@ func partTwo(input [][]int) int {
6782

6883
for _, report := range input {
6984
// Probably there's a better solution to this,
70-
// But I just implemented specific checks for edge cases 0 and 1
71-
isSafeWhenZeroRemoved := isSafe(report, 2) == 0
72-
isSafeWhenOneRemoved := isSafe(report[1:], 1) == 0
73-
isSafeInOtherCases := isSafe(report, 1) <= 1
85+
// But I just implemented specific checks for edge cases
86+
isSafeWhenFirstValueRemoved := dpCheck(report[1:]) == 0
87+
isSafeWhenLastValueRemoved := dpCheck(report[:len(report)-1]) == 0
88+
otherCasesResult := dpCheck(report)
89+
isSafeInOtherCases := otherCasesResult == 0 || otherCasesResult == 1
7490

75-
if isSafeWhenZeroRemoved || isSafeWhenOneRemoved || isSafeInOtherCases {
91+
if isSafeWhenFirstValueRemoved || isSafeWhenLastValueRemoved || isSafeInOtherCases {
7692
result += 1
7793
}
7894
}

‎utils/utils.go‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,10 @@ func ToInt(arg string) int {
1111
}
1212
return val
1313
}
14+
15+
func Abs(x int) int {
16+
if x < 0 {
17+
return -x
18+
}
19+
return x
20+
}

0 commit comments

Comments
 (0)