2024-12-02 12:30:04 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"sort"
|
2024-12-02 19:51:34 +00:00
|
|
|
|
|
|
|
"aoc/helper"
|
2024-12-02 12:30:04 +00:00
|
|
|
)
|
|
|
|
|
2024-12-02 17:19:40 +00:00
|
|
|
type reports []report
|
|
|
|
type report struct {
|
|
|
|
levels []int
|
|
|
|
}
|
2024-12-02 12:30:04 +00:00
|
|
|
|
|
|
|
func main() {
|
2024-12-02 17:19:40 +00:00
|
|
|
// generate reports
|
|
|
|
var reports reports
|
|
|
|
for _, val := range helper.ReadLinesToIntSlices() {
|
|
|
|
reports = append(reports, report{levels: val})
|
|
|
|
}
|
2024-12-02 12:30:04 +00:00
|
|
|
|
|
|
|
// part 1
|
|
|
|
save_count := 0
|
|
|
|
for _, r := range reports {
|
2024-12-02 17:19:40 +00:00
|
|
|
if r.isSave() {
|
2024-12-02 12:30:04 +00:00
|
|
|
save_count++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fmt.Printf("Save reports: %d\n", save_count)
|
|
|
|
|
|
|
|
// part 2
|
|
|
|
save_count = 0
|
|
|
|
for _, r := range reports {
|
2024-12-02 17:19:40 +00:00
|
|
|
if r.isSaveWithDamper() {
|
2024-12-02 12:30:04 +00:00
|
|
|
save_count++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fmt.Printf("Save reports (with damper): %d\n", save_count)
|
|
|
|
}
|
|
|
|
|
2024-12-02 17:19:40 +00:00
|
|
|
func (r report) isSave() bool {
|
|
|
|
if !r.isSorted() {
|
2024-12-02 12:30:04 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2024-12-05 15:15:54 +00:00
|
|
|
for i := range len(r.levels) - 1 { // iterate til second last level
|
2024-12-02 17:19:40 +00:00
|
|
|
if !isValidLevelDifference(r.levels[i], r.levels[i+1]) {
|
|
|
|
return false
|
2024-12-02 12:30:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2024-12-02 17:19:40 +00:00
|
|
|
func (r report) isSorted() bool {
|
2024-12-02 12:30:04 +00:00
|
|
|
ascSorted := sort.SliceIsSorted(
|
2024-12-02 17:19:40 +00:00
|
|
|
r.levels,
|
|
|
|
func(i, j int) bool { return r.levels[i] < r.levels[j] },
|
2024-12-02 12:30:04 +00:00
|
|
|
)
|
|
|
|
descSorted := sort.SliceIsSorted(
|
2024-12-02 17:19:40 +00:00
|
|
|
r.levels,
|
|
|
|
func(i, j int) bool { return r.levels[i] > r.levels[j] },
|
2024-12-02 12:30:04 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
return ascSorted || descSorted
|
|
|
|
}
|
|
|
|
|
2024-12-02 17:19:40 +00:00
|
|
|
func isValidLevelDifference(i int, j int) bool {
|
|
|
|
if i == j {
|
2024-12-02 12:30:04 +00:00
|
|
|
return false
|
|
|
|
}
|
2024-12-02 17:19:40 +00:00
|
|
|
|
|
|
|
if helper.Abs(i-j) > 3 {
|
2024-12-02 12:30:04 +00:00
|
|
|
return false
|
|
|
|
}
|
2024-12-02 17:19:40 +00:00
|
|
|
|
2024-12-02 12:30:04 +00:00
|
|
|
return true
|
|
|
|
}
|
2024-12-02 17:19:40 +00:00
|
|
|
|
|
|
|
func (r report) isSaveWithDamper() bool {
|
|
|
|
if r.isSave() {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := range r.levels {
|
|
|
|
// remove one item from report and try to validate
|
|
|
|
if r.removeLevelByIndex(i).isSave() {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r report) removeLevelByIndex(dropIndex int) report {
|
|
|
|
var newlevels []int
|
2024-12-04 14:33:55 +00:00
|
|
|
// create new slice w/o passed index position
|
2024-12-02 17:19:40 +00:00
|
|
|
newlevels = append(newlevels, r.levels[:dropIndex]...)
|
|
|
|
newlevels = append(newlevels, r.levels[dropIndex+1:]...)
|
|
|
|
|
|
|
|
return report{levels: newlevels}
|
|
|
|
}
|