advent2022

Advent of Code 2022 Solutions
git clone git://bsandro.tech/advent2022
Log | Files | Refs | README | LICENSE

main.go (3276B)


      1 package main
      2 
      3 import (
      4 	"bufio"
      5 	"fmt"
      6 	"log"
      7 	"os"
      8 )
      9 
     10 type Grid [][]int
     11 
     12 func (g Grid) IsEdge(row, col int) bool {
     13 	cols, rows := len(g[0]), len(g)
     14 	return col == 0 || row == 0 || col == cols-1 || row == rows-1
     15 }
     16 func (g Grid) CalcScore(row, col int) int {
     17 	cols, rows := len(g[0]), len(g)
     18 	height := g[row][col]
     19 	var left, right, top, bottom int
     20 	left = col
     21 	for c := col - 1; c >= 0; c-- {
     22 		if g[row][c] >= height {
     23 			left = col - c
     24 			break
     25 		}
     26 	}
     27 	right = cols - col - 1
     28 	for c := col + 1; c < cols; c++ {
     29 		if g[row][c] >= height {
     30 			right = c - col
     31 			break
     32 		}
     33 	}
     34 	top = row
     35 	for r := row - 1; r >= 0; r-- {
     36 		if g[r][col] >= height {
     37 			top = row - r
     38 			break
     39 		}
     40 	}
     41 	bottom = rows - row - 1
     42 	for r := row + 1; r < rows; r++ {
     43 		if g[r][col] >= height {
     44 			bottom = r - row
     45 			break
     46 		}
     47 	}
     48 
     49 	return left * right * top * bottom
     50 }
     51 
     52 type Tree struct {
     53 	row, col, height int
     54 }
     55 type Line struct {
     56 	trees []Tree
     57 	max   int
     58 }
     59 
     60 func (l *Line) TryAdd(row, col, height int) {
     61 	if height > l.max {
     62 		l.trees = append(l.trees, Tree{row: row, col: col, height: height})
     63 		l.max = height
     64 	}
     65 }
     66 func (l *Line) Has(row, col int) bool {
     67 	for _, t := range l.trees {
     68 		if t.row == row && t.col == col {
     69 			return true
     70 		}
     71 	}
     72 	return false
     73 }
     74 
     75 type Lines []Line
     76 
     77 func (lines *Lines) Add() *Line {
     78 	*lines = append(*lines, Line{max: -1})
     79 	return &(*lines)[len(*lines)-1]
     80 }
     81 func (lines *Lines) Has(row, col int) bool {
     82 	for _, l := range *lines {
     83 		if l.Has(row, col) {
     84 			return true
     85 		}
     86 	}
     87 	return false
     88 }
     89 
     90 func (t Tree) String() string {
     91 	return fmt.Sprintf("[r:%d,c:%d](h:%d)", t.row, t.col, t.height)
     92 }
     93 
     94 func main() {
     95 	if len(os.Args) > 1 {
     96 		day08(os.Args[1])
     97 	} else if len(os.Args) == 1 {
     98 		fmt.Printf("usage: %s inputfile.txt\n", os.Args[0])
     99 	} else {
    100 		fmt.Println("No input data")
    101 	}
    102 }
    103 
    104 func day08(input_file string) {
    105 	fmt.Printf("day 08 input filename: %s\n", input_file)
    106 	input, err := os.Open(input_file)
    107 	if err != nil {
    108 		log.Fatal(err)
    109 	}
    110 	defer input.Close()
    111 	scanner := bufio.NewScanner(input)
    112 	var grid Grid
    113 	row := 0
    114 	for scanner.Scan() {
    115 		in := scanner.Text()
    116 		grid = append(grid, make([]int, len(in)))
    117 		for col := 0; col < len(in); col++ {
    118 			grid[row][col] = int(in[col]) - 48 // wowee
    119 		}
    120 		row++
    121 	}
    122 	if err = scanner.Err(); err != nil {
    123 		log.Fatal(err)
    124 	}
    125 	rows := row
    126 	cols := len(grid[0])
    127 	var lefts, rights, tops, bottoms Lines
    128 
    129 	for r := 0; r < rows; r++ {
    130 		// row left to right
    131 		left := lefts.Add()
    132 		for c := 0; c < cols; c++ {
    133 			left.TryAdd(r, c, grid[r][c])
    134 		}
    135 		// row right to left
    136 		right := rights.Add()
    137 		for c := cols - 1; c >= 0; c-- {
    138 			right.TryAdd(r, c, grid[r][c])
    139 		}
    140 	}
    141 
    142 	for c := 0; c < cols; c++ {
    143 		// column top to bottom
    144 		top := tops.Add()
    145 		for r := 0; r < rows; r++ {
    146 			top.TryAdd(r, c, grid[r][c])
    147 		}
    148 		// column bottom to top
    149 		bottom := bottoms.Add()
    150 		for r := rows - 1; r >= 0; r-- {
    151 			bottom.TryAdd(r, c, grid[r][c])
    152 		}
    153 	}
    154 
    155 	sum := 0
    156 	maxScore := 0
    157 	for r := 0; r < rows; r++ {
    158 		for c := 0; c < cols; c++ {
    159 			if lefts.Has(r, c) ||
    160 				rights.Has(r, c) ||
    161 				tops.Has(r, c) ||
    162 				bottoms.Has(r, c) {
    163 				sum++
    164 				if !grid.IsEdge(r, c) {
    165 					score := grid.CalcScore(r, c)
    166 					if score > maxScore {
    167 						maxScore = score
    168 					}
    169 				}
    170 			}
    171 		}
    172 	}
    173 	fmt.Println("sum:", sum)
    174 	fmt.Println("score:", maxScore)
    175 }