package main import ( "fmt" "sort" "aoc/helper" ) type reports []report type report struct { levels []int } func main() { // generate reports var reports reports for _, val := range helper.ReadLinesToIntSlices() { reports = append(reports, report{levels: val}) } // part 1 save_count := 0 for _, r := range reports { if r.isSave() { save_count++ } } fmt.Printf("Save reports: %d\n", save_count) // part 2 save_count = 0 for _, r := range reports { if r.isSaveWithDamper() { save_count++ } } fmt.Printf("Save reports (with damper): %d\n", save_count) } func (r report) isSave() bool { if !r.isSorted() { return false } for i := range len(r.levels) - 1 { // iterate til second last level if !isValidLevelDifference(r.levels[i], r.levels[i+1]) { return false } } return true } func (r report) isSorted() bool { ascSorted := sort.SliceIsSorted( r.levels, func(i, j int) bool { return r.levels[i] < r.levels[j] }, ) descSorted := sort.SliceIsSorted( r.levels, func(i, j int) bool { return r.levels[i] > r.levels[j] }, ) return ascSorted || descSorted } func isValidLevelDifference(i int, j int) bool { if i == j { return false } if helper.Abs(i-j) > 3 { return false } return true } 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 // create new slice w/o passed index position newlevels = append(newlevels, r.levels[:dropIndex]...) newlevels = append(newlevels, r.levels[dropIndex+1:]...) return report{levels: newlevels} }