@@ -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
5368func 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 }
0 commit comments