mirror of
https://github.com/RussellChamp/advent-of-code-2021.git
synced 2026-10-27 21:52:32 +00:00
150 lines
3.4 KiB
Go
150 lines
3.4 KiB
Go
/* Day 25: Sea Cucumber */
|
|
package main
|
|
|
|
import (
|
|
"AoC2021/utils/args"
|
|
"AoC2021/utils/log"
|
|
"AoC2021/utils/timer"
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
)
|
|
|
|
func check(e error) {
|
|
if e != nil {
|
|
log.Println(log.DEBUG, "Oh snap!")
|
|
panic(e)
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
argMap := args.Parse(os.Args)
|
|
log.SetLogLevelFromArgs(argMap)
|
|
selectedPart, partSpecified := argMap["part"]
|
|
|
|
log.Println(log.NORMAL, "--- Day 25: Sea Cucumber ---")
|
|
timer.Start()
|
|
|
|
if !partSpecified || selectedPart == "" || selectedPart == "1" {
|
|
part1()
|
|
timer.Tick()
|
|
log.Println(log.NORMAL)
|
|
}
|
|
|
|
if !partSpecified || selectedPart == "" || selectedPart == "2" {
|
|
part2()
|
|
timer.Tick()
|
|
log.Println(log.NORMAL)
|
|
}
|
|
}
|
|
|
|
func part1() {
|
|
log.Println(log.NORMAL, "* Part 1 *")
|
|
log.Println(log.NORMAL, " Goal: Find somewhere safe to land your submarine.")
|
|
log.Println(log.NORMAL, " Answer: What is the first step on which no sea cucumbers move?")
|
|
|
|
grid := readData()
|
|
|
|
round, hCukes, vCukes := 0, 0, 0
|
|
for cukesMoved := 0; round == 0 || cukesMoved > 0; round++ {
|
|
hCukes, vCukes = grid.Move()
|
|
cukesMoved = hCukes + vCukes
|
|
if log.LOG_LEVEL >= log.DEBUG && round%1000 == 0 {
|
|
log.Printf(log.DEBUG, "After %d rounds, %d hCukes and %d vCukes moved...\n", round, hCukes, vCukes)
|
|
}
|
|
}
|
|
log.Printf(log.NORMAL, "Everything settled on round %d\n", round)
|
|
}
|
|
|
|
func part2() {
|
|
log.Println(log.NORMAL, "* Part 2 *")
|
|
log.Println(log.NORMAL, " Goal: ")
|
|
log.Println(log.NORMAL, " Answer: ")
|
|
}
|
|
|
|
func readData() Grid {
|
|
input, err := os.Open("./input.txt")
|
|
check(err)
|
|
defer input.Close()
|
|
|
|
scanner := bufio.NewScanner(input)
|
|
lines := 0
|
|
hCukes, vCukes, blanks := 0, 0, 0
|
|
|
|
var grid Grid
|
|
|
|
for scanner.Scan() {
|
|
line := scanner.Bytes()
|
|
for _, b := range line {
|
|
switch b {
|
|
case '>':
|
|
hCukes++
|
|
case 'v':
|
|
vCukes++
|
|
case '.':
|
|
blanks++
|
|
default:
|
|
panic(fmt.Sprintf("got invalid byte! %b", b))
|
|
}
|
|
}
|
|
grid = append(grid, line)
|
|
lines++
|
|
}
|
|
|
|
log.Printf(log.DEBUG, "Made a %dx%d grid from %d lines from input\n", len(grid[0]), len(grid), lines)
|
|
log.Printf(log.DEBUG, "Grid contains %d hCukes and %d vCukes and %d blanks\n", hCukes, vCukes, blanks)
|
|
|
|
return grid
|
|
}
|
|
|
|
type Grid [][]byte
|
|
type Point struct{ rIdx, cIdx int }
|
|
|
|
func (g *Grid) Move() (int, int) {
|
|
// NOPE! not moving right!!
|
|
|
|
// find horizontal movers
|
|
var hMovers []Point
|
|
for rIdx, row := range *g {
|
|
for cIdx, value := range row {
|
|
newCIdx := (cIdx + 1) % len(row)
|
|
if value == '>' && row[newCIdx] == '.' {
|
|
hMovers = append(hMovers, Point{rIdx: rIdx, cIdx: cIdx})
|
|
}
|
|
}
|
|
}
|
|
// move them
|
|
for _, p := range hMovers {
|
|
newCIdx := (p.cIdx + 1) % len((*g)[p.rIdx])
|
|
log.Printf(log.DIAGNOSTIC, "Moving hCuke from (%d,%d) to (%d,%d)...\n", p.rIdx, p.cIdx, p.rIdx, newCIdx)
|
|
(*g)[p.rIdx][p.cIdx] = '.'
|
|
(*g)[p.rIdx][newCIdx] = '>'
|
|
}
|
|
|
|
// find vertical movers
|
|
var vMovers []Point
|
|
for rIdx, row := range *g {
|
|
for cIdx, value := range row {
|
|
newRIdx := (rIdx + 1) % len(*g)
|
|
if value == 'v' && (*g)[newRIdx][cIdx] == '.' {
|
|
vMovers = append(vMovers, Point{rIdx: rIdx, cIdx: cIdx})
|
|
}
|
|
}
|
|
}
|
|
// move them
|
|
for _, p := range vMovers {
|
|
newRIdx := (p.rIdx + 1) % len(*g)
|
|
log.Printf(log.DIAGNOSTIC, "Moving vCuke from (%d,%d) to (%d,%d)...\n", p.rIdx, p.cIdx, newRIdx, p.cIdx)
|
|
(*g)[p.rIdx][p.cIdx] = '.'
|
|
(*g)[newRIdx][p.cIdx] = 'v'
|
|
}
|
|
|
|
return len(hMovers), len(vMovers)
|
|
}
|
|
|
|
func (g Grid) Print() {
|
|
for _, row := range g {
|
|
log.Println(log.DEBUG, string(row))
|
|
}
|
|
}
|