Add day 14 part 1 solution

This is a bit messy but I was expecting a twist in part 2
master
Nick Krichevsky 2023-12-17 20:00:30 -05:00
parent 7ff46673da
commit 4723a2d384
1 changed files with 133 additions and 0 deletions

133
day14/main.go Normal file
View File

@ -0,0 +1,133 @@
package main
import (
"errors"
"fmt"
"io"
"os"
"slices"
"strings"
)
type Tile int
const (
TileEmpty Tile = iota
TileRoundRock
TileCubeRock
)
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, err := parseTileGrid(inputLines)
if err != nil {
panic(fmt.Sprintf("failed to parse input: %s", err))
}
fmt.Printf("Part 1: %d\n", part1(Clone2D(grid)))
}
func part1(inputGrid [][]Tile) int {
rollNorth(inputGrid)
load := 0
for row, rowItems := range inputGrid {
for _, tile := range rowItems {
if tile == TileRoundRock {
load += len(inputGrid) - row
}
}
}
return load
}
func rollNorth(inputGrid [][]Tile) {
for row, line := range inputGrid {
if row == 0 {
continue
}
for col, tile := range line {
if tile != TileRoundRock {
continue
}
lastEmptyRow := row
for candidateRow := row - 1; candidateRow >= 0; candidateRow-- {
if inputGrid[candidateRow][col] == TileEmpty {
lastEmptyRow = candidateRow
} else {
break
}
}
inputGrid[row][col] = TileEmpty
inputGrid[lastEmptyRow][col] = TileRoundRock
}
}
}
func Clone2D[T any, S ~[][]T](grid S) S {
clone := make(S, len(grid))
for i, row := range grid {
clone[i] = slices.Clone(row)
}
return clone
}
func parseTileGrid(inputLines []string) ([][]Tile, error) {
if len(inputLines) == 0 {
return [][]Tile{}, nil
}
grid := make([][]Tile, len(inputLines))
for i, line := range inputLines {
if len(line) != len(inputLines[0]) {
return nil, errors.New("lines have uneven lengths")
}
for _, char := range line {
tile, err := tileForRune(char)
if err != nil {
return nil, err
}
grid[i] = append(grid[i], tile)
}
}
return grid, nil
}
func tileForRune(r rune) (Tile, error) {
switch r {
case '.':
return TileEmpty, nil
case 'O':
return TileRoundRock, nil
case '#':
return TileCubeRock, nil
default:
return TileEmpty, fmt.Errorf("invalid tile char %c", r)
}
}