Advent of Code 2022: Day8

Back up

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
}

aimeeble@blog

the blog of aimeeble


By Aimee, 2022-12-08


Table of Contents: