mirror of
https://github.com/Threnklyn/advent-of-code-go.git
synced 2026-05-18 19:13:27 +02:00
127 lines
2.6 KiB
Go
127 lines
2.6 KiB
Go
package main
|
|
|
|
import (
|
|
_ "embed"
|
|
"flag"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/alexchao26/advent-of-code-go/util"
|
|
)
|
|
|
|
//go:embed input.txt
|
|
var input string
|
|
|
|
func init() {
|
|
// do this in init (not main) so test file has same input
|
|
input = strings.TrimRight(input, "\n")
|
|
if len(input) == 0 {
|
|
panic("empty input.txt file")
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
var part int
|
|
flag.IntVar(&part, "part", 1, "part 1 or 2")
|
|
flag.Parse()
|
|
fmt.Println("Running part", part)
|
|
|
|
if part == 1 {
|
|
ans := part1(input)
|
|
util.CopyToClipboard(fmt.Sprintf("%v", ans))
|
|
fmt.Println("Output:", ans)
|
|
} else {
|
|
ans := part2(input)
|
|
util.CopyToClipboard(fmt.Sprintf("%v", ans))
|
|
fmt.Println("Output:", ans)
|
|
}
|
|
}
|
|
|
|
func part1(input string) string {
|
|
stacks, steps := parseInput(input)
|
|
|
|
for _, step := range steps {
|
|
// move crates ONE AT A TIME
|
|
for q := 0; q < step.qty; q++ {
|
|
top := stacks[step.from][len(stacks[step.from])-1]
|
|
stacks[step.to] = append(stacks[step.to], top)
|
|
stacks[step.from] = stacks[step.from][:len(stacks[step.from])-1]
|
|
}
|
|
}
|
|
|
|
ans := ""
|
|
for _, stack := range stacks {
|
|
ans += stack[len(stack)-1]
|
|
}
|
|
return ans
|
|
}
|
|
|
|
func part2(input string) string {
|
|
stacks, steps := parseInput(input)
|
|
|
|
for _, step := range steps {
|
|
// move crates ONCE
|
|
fromIndex := len(stacks[step.from]) - step.qty
|
|
stacks[step.to] = append(stacks[step.to], stacks[step.from][fromIndex:]...)
|
|
stacks[step.from] = stacks[step.from][:fromIndex]
|
|
}
|
|
|
|
ans := ""
|
|
for _, stack := range stacks {
|
|
ans += stack[len(stack)-1]
|
|
}
|
|
return ans
|
|
}
|
|
|
|
// move 4 from 3 to 1
|
|
type step struct {
|
|
qty, from, to int
|
|
}
|
|
|
|
func (s step) String() string {
|
|
return fmt.Sprintf("move %d from %d to %d", s.qty, s.from, s.to)
|
|
}
|
|
|
|
func parseInput(input string) ([][]string, []step) {
|
|
parts := strings.Split(input, "\n\n")
|
|
|
|
state := parts[0]
|
|
oversized := [][]string{}
|
|
for _, row := range strings.Split(state, "\n") {
|
|
oversized = append(oversized, strings.Split(row, ""))
|
|
}
|
|
oRows, oCols := len(oversized), len(oversized[0])
|
|
|
|
actual := [][]string{}
|
|
|
|
for c := 0; c < oCols-1; c++ {
|
|
if oversized[oRows-1][c] != " " {
|
|
// hit a column with values... move up from here
|
|
stack := []string{}
|
|
for r := oRows - 2; r >= 0; r-- {
|
|
char := oversized[r][c]
|
|
if char != " " {
|
|
stack = append(stack, char)
|
|
}
|
|
}
|
|
actual = append(actual, stack)
|
|
}
|
|
}
|
|
|
|
stepsRaw := parts[1]
|
|
steps := []step{}
|
|
for _, row := range strings.Split(stepsRaw, "\n") {
|
|
inst := step{}
|
|
_, err := fmt.Sscanf(row, "move %d from %d to %d", &inst.qty, &inst.from, &inst.to)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
// subtract one so they're zero indexed...
|
|
inst.from--
|
|
inst.to--
|
|
steps = append(steps, inst)
|
|
}
|
|
|
|
return actual, steps
|
|
}
|