github.com/frodejac/aoc-2022@v0.0.0-20221213081734-037c741b1c89/internal/aoc/day04/day04.go (about) 1 package day04 2 3 import ( 4 "regexp" 5 "strconv" 6 "strings" 7 8 "github.com/frodejac/aoc-2022/pkg/datastructures/stack" 9 ) 10 11 type Day04 struct { 12 input string 13 } 14 15 type cargoBay struct { 16 stacks []*stack.Stack[string] 17 } 18 19 type move struct { 20 from, to int 21 count int 22 } 23 24 func (c *cargoBay) move9000(from, to, count int) { 25 for i := 0; i < count; i++ { 26 c.stacks[to].Push(c.stacks[from].Pop()) 27 } 28 } 29 30 func (c *cargoBay) move9001(from, to, count int) { 31 values := c.stacks[from].PopN(count) 32 c.stacks[to].PushN(values) 33 } 34 35 func (c *cargoBay) toString() string { 36 var sb strings.Builder 37 for _, stack := range c.stacks { 38 sb.WriteString(stack.Peek()) 39 } 40 return sb.String() 41 } 42 43 func newCargoBay(stackCount int) *cargoBay { 44 stacks := make([]*stack.Stack[string], stackCount) 45 for i := 0; i < stackCount; i++ { 46 stacks[i] = stack.New([]string{}) 47 } 48 return &cargoBay{stacks: stacks} 49 } 50 51 func parseCargoBay(input string) *cargoBay { 52 lines := strings.SplitAfter(input, "\n") 53 stackCount := len(lines[0]) / 4 54 cb := newCargoBay(stackCount) 55 56 for _, line := range lines[:len(lines)-1] { 57 for i := 0; i < stackCount; i++ { 58 char := line[i*4 : i*4+4] 59 char = strings.TrimSpace(char) 60 char = strings.TrimLeft(char, "[") 61 char = strings.TrimRight(char, "]") 62 if char != "" { 63 cb.stacks[i].PushLeft(char) 64 } 65 } 66 } 67 return cb 68 } 69 70 func parseMoves(input string) []move { 71 r := regexp.MustCompile(`move (\d+) from (\d+) to (\d+)`) 72 matches := r.FindAllStringSubmatch(input, -1) 73 moves := make([]move, len(matches)) 74 for i, match := range matches { 75 count, _ := strconv.Atoi(match[1]) 76 from, _ := strconv.Atoi(match[2]) 77 to, _ := strconv.Atoi(match[3]) 78 moves[i] = move{from: from - 1, to: to - 1, count: count} 79 } 80 return moves 81 } 82 83 func (d *Day04) parseInput() (*cargoBay, []move) { 84 sections := strings.Split(d.input, "\n\n") 85 cargoBay := parseCargoBay(sections[0]) 86 moves := parseMoves(sections[1]) 87 return cargoBay, moves 88 } 89 90 func Solver(input []byte) *Day04 { 91 return &Day04{input: string(input)} 92 } 93 94 func (d *Day04) SolvePart1() string { 95 cb, moves := d.parseInput() 96 for _, move := range moves { 97 cb.move9000(move.from, move.to, move.count) 98 } 99 return cb.toString() 100 } 101 102 func (d *Day04) SolvePart2() string { 103 cb, moves := d.parseInput() 104 for _, move := range moves { 105 cb.move9001(move.from, move.to, move.count) 106 } 107 return cb.toString() 108 }