170 lines
3.1 KiB
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()
|
||
|
|
}
|