149 lines
3.1 KiB
Go
149 lines
3.1 KiB
Go
package day8
|
|
|
|
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
|
|
}
|