Stream Video
soon.
Code
package aoc
import (
"fmt"
"io"
"strconv"
"mono3/advent/lib/grid"
"mono3/advent/lib/lineio"
"mono3/common/log"
)
type tree struct {
x, y int
height int
isVisible bool
scenicScore int
}
func (t tree) String() string {
return fmt.Sprintf("%d", t.height)
}
// Each part gets the same input with reader pointing at the start of input.
var PuzzleParts = []func(r io.Reader) error{
PuzzlePart1,
PuzzlePart2,
}
func PuzzlePart1(r io.Reader) error {
return solveit(r, 1, func(g *grid.GridArray[tree]) int {
count := 0
g.ForEachCell(func(x, y int, me *tree) {
good := false
for i := 0; i < x; i++ {
you, _ := g.GetCell(i, y)
if you.height >= me.height {
good = true
break
}
}
if !good {
count += 1
return
}
good = false
for i := x + 1; i < g.Width(); i++ {
you, _ := g.GetCell(i, y)
if you.height >= me.height {
good = true
break
}
}
if !good {
count += 1
return
}
good = false
for j := 0; j < y; j++ {
you, _ := g.GetCell(x, j)
if you.height >= me.height {
good = true
break
}
}
if !good {
count += 1
return
}
good = false
for j := y + 1; j < g.Height(); j++ {
you, _ := g.GetCell(x, j)
if you.height >= me.height {
good = true
break
}
}
if !good {
count += 1
return
}
})
return count
})
}
func PuzzlePart2(r io.Reader) error {
return solveit(r, 2, func(g *grid.GridArray[tree]) int {
var best *tree
g.ForEachCell(func(x, y int, me *tree) {
dirScore := 0
for i := x - 1; i >= 0; i-- {
you, _ := g.GetCell(i, y)
dirScore++
if you.height >= me.height {
break
}
}
me.scenicScore *= dirScore
dirScore = 0
for i := x + 1; i < g.Width(); i++ {
you, _ := g.GetCell(i, y)
dirScore++
if you.height >= me.height {
break
}
}
me.scenicScore *= dirScore
dirScore = 0
for j := y - 1; j >= 0; j-- {
you, _ := g.GetCell(x, j)
dirScore++
if you.height >= me.height {
break
}
}
me.scenicScore *= dirScore
dirScore = 0
for j := y + 1; j < g.Height(); j++ {
you, _ := g.GetCell(x, j)
dirScore++
if you.height >= me.height {
break
}
}
me.scenicScore *= dirScore
if best == nil || me.scenicScore > best.scenicScore {
best = me
}
})
log.Infof("(%d,%d) has best scenic score: %d", best.x, best.y, best.scenicScore)
return best.scenicScore
})
}
func solveit(r io.Reader, part int, fun func(g *grid.GridArray[tree]) int) error {
log.Info("Running")
g := grid.NewDynamicSize[tree]()
y := 0
if err := lineio.ForEach(r, func(ln int, line string) error {
//log.Infof("[%3d] %s", ln, line)
for x, r := range line {
n, err := strconv.ParseInt(string(r), 10, 32)
if err != nil {
return fmt.Errorf("(%d,%d) ParseInterr(%v): %w", x, y, string(r), err)
}
//log.Infof("(%d, %d) = %d", x, y, n)
newTree := tree{
x: x,
y: y,
height: int(n),
scenicScore: 1,
}
if err := g.SetCell(x, y, &newTree); err != nil {
return fmt.Errorf("(%d,%d) Set(%d) error: %w", x, y, n, err)
}
}
y++
return nil
}); err != nil {
return err
}
w := log.Writer()
fmt.Fprintf(w, "%s", g.String())
w.Close()
score := fun(g)
log.Infof("Score part %d = %d", part, score)
return nil
}