aoc-2022/day08/solution.go

149 lines
3.1 KiB
Go

package day08
type Solver struct {
input [][]byte
tallestFromLeft [][]int8
tallestFromRight [][]int8
tallestFromTop [][]int8
tallestFromBottom [][]int8
}
func (s *Solver) ParseInput(input []string) {
s.input = make([][]byte, len(input))
for i, line := range input {
s.input[i] = []byte(line)
for x := 0; x < len(s.input[i]); x++ {
s.input[i][x] -= '0'
}
}
}
func max(a, b int8) int8 {
if a > b {
return a
} else {
return b
}
}
func (s *Solver) SolvePart1() any {
s.tallestFromLeft = make([][]int8, len(s.input))
for r := 0; r < len(s.input); r++ {
s.tallestFromLeft[r] = make([]int8, len(s.input))
for c := 0; c < len(s.input); c++ {
if c == 0 {
s.tallestFromLeft[r][c] = -1
} else {
s.tallestFromLeft[r][c] = max(s.tallestFromLeft[r][c-1], int8(s.input[r][c-1]))
}
}
}
//fmt.Println(s.tallestFromLeft)
s.tallestFromRight = make([][]int8, len(s.input))
for r := 0; r < len(s.input); r++ {
s.tallestFromRight[r] = make([]int8, len(s.input))
for c := len(s.input) - 1; c >= 0; c-- {
if c == len(s.input)-1 {
s.tallestFromRight[r][c] = -1
} else {
s.tallestFromRight[r][c] = max(s.tallestFromRight[r][c+1], int8(s.input[r][c+1]))
}
}
}
//fmt.Println(s.tallestFromRight)
s.tallestFromBottom = make([][]int8, len(s.input))
for r := 0; r < len(s.input); r++ {
s.tallestFromBottom[r] = make([]int8, len(s.input))
}
for c := 0; c < len(s.input); c++ {
for r := len(s.input) - 1; r >= 0; r-- {
if r == len(s.input)-1 {
s.tallestFromBottom[r][c] = -1
} else {
s.tallestFromBottom[r][c] = max(s.tallestFromBottom[r+1][c], int8(s.input[r+1][c]))
}
}
}
//fmt.Println(s.tallestFromBottom)
s.tallestFromTop = make([][]int8, len(s.input))
for r := 0; r < len(s.input); r++ {
s.tallestFromTop[r] = make([]int8, len(s.input))
}
for c := 0; c < len(s.input); c++ {
for r := 0; r < len(s.input); r++ {
if r == 0 {
s.tallestFromTop[r][c] = -1
} else {
s.tallestFromTop[r][c] = max(s.tallestFromTop[r-1][c], int8(s.input[r-1][c]))
}
}
}
//fmt.Println(s.tallestFromTop)
var total int
for r := 0; r < len(s.input); r++ {
for c := 0; c < len(s.input[0]); c++ {
if s.isVisible(r, c) {
total += 1
}
}
}
return total
}
func (s *Solver) isVisible(r, c int) bool {
v := int8(s.input[r][c])
return v > s.tallestFromTop[r][c] || v > s.tallestFromBottom[r][c] || v > s.tallestFromLeft[r][c] || v > s.tallestFromRight[r][c]
}
type D struct {
dr, dc int
}
func (s *Solver) SolvePart2() any {
ds := []D{{-1, 0}, {1, 0}, {0, 1}, {0, -1}}
bestViewingDistance := 0
for r := 0; r < len(s.input); r++ {
for c := 0; c < len(s.input); c++ {
viewingDistance := 1
for _, d := range ds {
viewingDistance *= s.getViewingDistance(r, c, d)
}
if viewingDistance > bestViewingDistance {
bestViewingDistance = viewingDistance
}
}
}
return bestViewingDistance
}
func (s *Solver) getViewingDistance(r, c int, d D) int {
result := 0
v := s.input[r][c]
for {
r += d.dr
c += d.dc
if r < 0 || r == len(s.input) || c < 0 || c == len(s.input) {
break
}
result++
if s.input[r][c] >= v {
break
}
}
return result
}