advent2022

Advent of Code 2022 Solutions
git clone git://bsandro.tech/advent2022
Log | Files | Refs | README | LICENSE

main.go (2953B)


      1 package main
      2 
      3 import (
      4 	"fmt"
      5 	"log"
      6 	"os"
      7 	"strings"
      8 )
      9 
     10 type Instruction struct {
     11 	amount, from, to int
     12 }
     13 
     14 func main() {
     15 	if len(os.Args) > 1 {
     16 		day05(os.Args[1])
     17 	} else if len(os.Args) == 1 {
     18 		fmt.Printf("usage: %s inputfile.txt\n", os.Args[0])
     19 	} else {
     20 		fmt.Println("No input data")
     21 	}
     22 }
     23 
     24 func day05(input_file string) {
     25 	fmt.Printf("day 05 input filename: %s\n", input_file)
     26 	input, err := os.ReadFile(input_file)
     27 	if err != nil {
     28 		log.Fatal(err)
     29 	}
     30 	crates_in, instructions_in, _ := strings.Cut(string(input), "\n\n")
     31 	stacks := parseStacks(crates_in)
     32 	instructions := parseInstructions(instructions_in)
     33 
     34 	stacks1 := execInstructions1(stacks, instructions)
     35 	stacks2 := execInstructions2(stacks, instructions)
     36 
     37 	printTopContainers(stacks1)
     38 	printTopContainers(stacks2)
     39 }
     40 
     41 func cloneStacks(in [][]string) [][]string {
     42 	var out [][]string
     43 	for i, _ := range in {
     44 		out = append(out, nil)
     45 		out[i] = append(out[i], in[i]...)
     46 	}
     47 	return out
     48 }
     49 
     50 func execInstructions1(stacks [][]string, instructions []Instruction) [][]string {
     51 	var out [][]string = cloneStacks(stacks)
     52 	for _, in := range instructions {
     53 		for i := 0; i < in.amount; i++ {
     54 			c := len(out[in.from]) - 1
     55 			out[in.to] = append(out[in.to], out[in.from][c])
     56 			out[in.from] = out[in.from][:c]
     57 		}
     58 	}
     59 	return out
     60 }
     61 
     62 func execInstructions2(stacks [][]string, instructions []Instruction) [][]string {
     63 	var out [][]string = cloneStacks(stacks)
     64 	for _, in := range instructions {
     65 		t := len(out[in.from])
     66 		f := t - in.amount
     67 		out[in.to] = append(out[in.to], out[in.from][f:t]...)
     68 		out[in.from] = out[in.from][:f]
     69 	}
     70 	return out
     71 }
     72 
     73 func printTopContainers(stacks [][]string) {
     74 	for _, v := range stacks {
     75 		fmt.Print(v[len(v)-1])
     76 	}
     77 	fmt.Print("\n")
     78 }
     79 
     80 func parseStacks(crates_in string) [][]string {
     81 	var stacks [][]string
     82 	crates := reverseSlice(strings.Split(crates_in, "\n"))
     83 
     84 	// parse stack numbers/amount, line 1
     85 	stacks_ids := strings.Fields(crates[0])
     86 	for i := 0; i < len(stacks_ids); i++ {
     87 		stacks = append(stacks, nil)
     88 	}
     89 
     90 	// parse containers by iterating over symbols in strings
     91 	for i := 1; i < len(crates); i++ {
     92 		line := crates[i]
     93 		for j := 1; j < len(line); j++ {
     94 			if isLetter(rune(line[j])) {
     95 				stack := j / 4
     96 				stacks[stack] = append(stacks[stack], string(line[j]))
     97 			}
     98 		}
     99 	}
    100 	return stacks
    101 }
    102 
    103 func parseInstructions(text string) []Instruction {
    104 	var instructions []Instruction
    105 	lines := strings.Split(text, "\n")
    106 	for _, line := range lines {
    107 		var ins Instruction
    108 		parsed, err := fmt.Sscanf(line, "move %d from %d to %d", &ins.amount, &ins.from, &ins.to)
    109 		if parsed == 3 || err == nil {
    110 			// array correction
    111 			ins.from -= 1
    112 			ins.to -= 1
    113 			instructions = append(instructions, ins)
    114 		}
    115 	}
    116 	return instructions
    117 }
    118 
    119 func reverseSlice(in []string) []string {
    120 	var res []string
    121 	for i := len(in) - 1; i >= 0; i-- {
    122 		res = append(res, in[i])
    123 	}
    124 	return res
    125 }
    126 
    127 func isLetter(in rune) bool {
    128 	return (in >= 'a' && in <= 'z') || (in >= 'A' && in <= 'Z')
    129 }