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  }