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 }