package day09 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() }