aoc-2022/day9/solution.go

170 lines
3.1 KiB
Go

package day9
import (
"fmt"
"math"
"strconv"
"strings"
)
type Solver struct {
moves []Move
}
type Location struct {
r, c int
}
func (l *Location) String() string {
return fmt.Sprintf("[%3d,%3d]", l.r, l.c)
}
type Move struct {
direction string
count int
}
func (s *Solver) ParseInput(input []string) {
s.moves = make([]Move, len(input))
for i, l := range input {
x := strings.Split(l, " ")
v, _ := strconv.Atoi(x[1])
s.moves[i] = Move{x[0], v}
}
//fmt.Println(s.moves)
}
func sign(i int) int {
if i == 0 {
return 0
} else if i > 0 {
return 1
} else {
return -1
}
}
func (s *Solver) SolvePart1() any {
headLoc := Location{0, 0}
tailLoc := Location{0, 0}
locMap := make(map[Location]bool)
locMap[tailLoc] = true
for _, m := range s.moves {
for i := 0; i < m.count; i++ {
switch m.direction {
case "R":
headLoc = Location{headLoc.r, headLoc.c + 1}
case "L":
headLoc = Location{headLoc.r, headLoc.c - 1}
case "U":
headLoc = Location{headLoc.r + 1, headLoc.c}
case "D":
headLoc = Location{headLoc.r - 1, headLoc.c}
}
dr, dc := tailLoc.r-headLoc.r, tailLoc.c-headLoc.c
if math.Abs(float64(dr)) > 1 || math.Abs(float64(dc)) > 1 {
tailLoc = Location{tailLoc.r - sign(dr), tailLoc.c - sign(dc)}
}
locMap[tailLoc] = true
//fmt.Printf("dr: %d, dc: %d\n", dr, dc)
//fmt.Printf("H: %v, T: %v\n", headLoc, tailLoc)
}
}
return len(locMap)
}
func (s *Solver) SolvePart2() any {
ropeLocs := make([]*Location, 10)
for i := 0; i < len(ropeLocs); i++ {
ropeLocs[i] = &Location{}
}
locMap := make(map[Location]bool)
locMap[*ropeLocs[len(ropeLocs)-1]] = true
//fmt.Printf("%s\n", ropeLocs)
for _, m := range s.moves {
for i := 0; i < m.count; i++ {
switch m.direction {
case "R":
ropeLocs[0].c++
case "L":
ropeLocs[0].c--
case "U":
ropeLocs[0].r--
case "D":
ropeLocs[0].r++
}
for ropeSegmentInd := 1; ropeSegmentInd < len(ropeLocs); ropeSegmentInd++ {
this := ropeLocs[ropeSegmentInd]
parent := ropeLocs[ropeSegmentInd-1]
dr, dc := this.r-parent.r, this.c-parent.c
if math.Abs(float64(dr)) > 1 || math.Abs(float64(dc)) > 1 {
this.r -= sign(dr)
this.c -= sign(dc)
}
}
locMap[*ropeLocs[len(ropeLocs)-1]] = true
//fmt.Printf("dr: %d, dc: %d\n", dr, dc)
}
//printRope(ropeLocs)
//fmt.Printf("%s\n", ropeLocs)
}
return len(locMap)
}
func printRope(locs []*Location) {
//minC, maxC, minR, maxR := -15, 15, -15, 15
minC, maxC, minR, maxR := 0, 0, 0, 0
for _, l := range locs {
if l.c < minC {
minC = l.c
}
if l.c > maxC {
maxC = l.c
}
if l.r < minR {
minR = l.r
}
if l.r > maxR {
maxR = l.r
}
}
//println(maxR, minR, maxC, minC)
field := make([][]byte, maxR-minR+1)
for i := 0; i < len(field); i++ {
field[i] = make([]byte, maxC-minC+1)
for j := 0; j < len(field[i]); j++ {
field[i][j] = '.'
}
}
field[-minR][-minC] = 's'
for i := len(locs) - 1; i >= 0; i-- {
loc := locs[i]
if i == 0 {
field[loc.r-minR][loc.c-minC] = 'H'
} else {
field[loc.r-minR][loc.c-minC] = '0' + byte(i)
}
}
for _, l := range field {
fmt.Println(string(l))
}
fmt.Println()
}