summaryrefslogtreecommitdiff
path: root/day3.go
diff options
context:
space:
mode:
Diffstat (limited to 'day3.go')
-rw-r--r--day3.go102
1 files changed, 102 insertions, 0 deletions
diff --git a/day3.go b/day3.go
new file mode 100644
index 0000000..98357dc
--- /dev/null
+++ b/day3.go
@@ -0,0 +1,102 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "log"
+ "os"
+)
+
+// Returns two slices of the input array representing both backpacks
+func ruckSacks(inputline []byte) ([]byte, []byte) {
+ split := len(inputline) / 2
+ return inputline[:split], inputline[split:]
+}
+
+// Gets the priority based on the character byte
+func itemPriority(item byte) byte {
+ if 'a' <= item && item <= 'z' {
+ return (item - 'a')
+ }
+ if 'A' <= item && item <= 'Z' {
+ return (item - 'A' + 26)
+ }
+ return 0
+}
+
+// Makes an array of 52 flags indicating with 0 or 1 if an item is in a rucksack
+func insideFlags(ruckSack []byte) []byte {
+ flags := make([]byte, 52)
+ for _, item := range ruckSack {
+ if flags[item] != 1 {
+ flags[item] = 1
+ }
+ }
+ return flags
+}
+
+// Checks if one of the items in a rucksacks is flagged in another rucksack
+func inBoth(ruckSack []byte, insideFlags []byte) byte {
+ for _, item := range ruckSack {
+ if insideFlags[item] == 1 {
+ return item
+ }
+ }
+ return 0
+}
+
+// Finds the item that is in all rucksacks
+func inAll(elfGroup []byte, groupSize int) int {
+ for i, itemCount := range elfGroup {
+ if int(itemCount) == groupSize {
+ return i + 1
+ }
+ }
+ return 0
+}
+
+// Solves the rucksack problem in linear time (since we don't have nested loops to check for the presence in the rucksacks),
+// could be more efficient with memory i think? But that would involve more bookkeeping
+func main() {
+ f, err := os.Open("day3.txt")
+ if err != nil {
+ log.Fatal("Could not open inputfile")
+ }
+ // Part 1
+ runningSum := 0
+ scanner := bufio.NewScanner(f)
+ for scanner.Scan() {
+ priorities := make([]byte, len(scanner.Bytes()))
+ for i, item := range scanner.Bytes() {
+ priorities[i] = itemPriority(item)
+ }
+ r1, r2 := ruckSacks(priorities)
+ insideR2 := insideFlags(r2)
+ duplicate := inBoth(r1, insideR2)
+ runningSum += int(duplicate) + 1
+ }
+ fmt.Println("part 1:", runningSum)
+
+ // Part 2
+ runningSum = 0
+ elfGroup := make([]byte, 52)
+ groupSize := 3
+ elf := 0
+ f.Seek(0, 0)
+ scanner = bufio.NewScanner(f)
+ for scanner.Scan() {
+ priorities := make([]byte, len(scanner.Bytes()))
+ for i, item := range scanner.Bytes() {
+ priorities[i] = itemPriority(item)
+ }
+ for i, flag := range insideFlags(priorities) {
+ elfGroup[i] += flag
+ }
+ if elf == (groupSize - 1) {
+ runningSum += inAll(elfGroup, groupSize)
+ elfGroup = make([]byte, 52)
+ }
+ elf = (elf + 1) % groupSize
+ }
+ fmt.Println("part 2:", runningSum)
+}