Add solution to day 21 part 1

master
Nick Krichevsky 2023-12-21 19:03:05 -05:00
parent 044737353d
commit 3cb59b0c67
1 changed files with 113 additions and 0 deletions

113
day21/main.go Normal file
View File

@ -0,0 +1,113 @@
package main
import (
"errors"
"fmt"
"io"
"os"
"strings"
)
type Tile rune
const (
TileTypeGarden Tile = '.'
TileTypeRock = '#'
)
type Coordinate struct {
Row int
Col int
}
func main() {
if len(os.Args) != 2 && len(os.Args) != 3 {
fmt.Fprintf(os.Stderr, "Usage: %s inputfile\n", os.Args[0])
os.Exit(1)
}
inputFilename := os.Args[1]
inputFile, err := os.Open(inputFilename)
if err != nil {
panic(fmt.Sprintf("could not open input file: %s", err))
}
defer inputFile.Close()
inputBytes, err := io.ReadAll(inputFile)
if err != nil {
panic(fmt.Sprintf("could not read input file: %s", err))
}
input := strings.TrimSpace(string(inputBytes))
inputLines := strings.Split(input, "\n")
grid, start, err := parseGrid(inputLines)
if err != nil {
panic(fmt.Sprintf("failed to parse input: %s", err))
}
fmt.Printf("Part 1: %d\n", part1(grid, start))
}
func part1(tiles map[Coordinate]Tile, start Coordinate) int {
cursors := []Coordinate{start}
lastCount := 0
for i := 0; i < 64; i++ {
nextCursors := []Coordinate{}
visited := map[Coordinate]struct{}{}
for _, cursor := range cursors {
for _, neighbor := range neighbors(cursor) {
if tiles[neighbor] == TileTypeRock {
continue
} else if _, ok := visited[neighbor]; ok {
continue
}
visited[neighbor] = struct{}{}
nextCursors = append(nextCursors, neighbor)
}
}
cursors = nextCursors
lastCount = len(visited)
}
return lastCount
}
func neighbors(coord Coordinate) []Coordinate {
return []Coordinate{
{Row: coord.Row + 1, Col: coord.Col},
{Row: coord.Row - 1, Col: coord.Col},
{Row: coord.Row, Col: coord.Col + 1},
{Row: coord.Row, Col: coord.Col - 1},
}
}
func parseGrid(inputLines []string) (map[Coordinate]Tile, Coordinate, error) {
tiles := map[Coordinate]Tile{}
start := Coordinate{}
startFound := false
for row, line := range inputLines {
for col, char := range line {
coordinate := Coordinate{Row: row, Col: col}
switch char {
case 'S':
startFound = true
start = coordinate
tiles[coordinate] = TileTypeGarden
case '.', '#':
tiles[coordinate] = Tile(char)
default:
return nil, Coordinate{}, fmt.Errorf("invalid tile char %c", char)
}
}
}
if !startFound {
return nil, Coordinate{}, errors.New("no start tile found")
}
return tiles, start, nil
}