From a44fa890c7d8a8c9a829e445ddfbd02dcb891f33 Mon Sep 17 00:00:00 2001 From: Araozu Date: Mon, 11 Mar 2024 17:55:13 -0500 Subject: [PATCH] day 7 part 1 --- main.go | 3 ++ solutions/day07.go | 108 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 solutions/day07.go diff --git a/main.go b/main.go index a5b51ef..418ebe6 100644 --- a/main.go +++ b/main.go @@ -24,6 +24,9 @@ func main() { runAndBenchmark("06", "1", false, solutions.Day06Part01) runAndBenchmark("06", "2", false, solutions.Day06Part02) + + runAndBenchmark("07", "1", false, solutions.Day07Part01) + runAndBenchmark("07", "2", true, solutions.Day07Part02) } type execute func(bool) int diff --git a/solutions/day07.go b/solutions/day07.go new file mode 100644 index 0000000..c1a0045 --- /dev/null +++ b/solutions/day07.go @@ -0,0 +1,108 @@ +package solutions + +import ( + "strconv" + "strings" +) + +type Bag struct { + color string + contents []BagContent + containsShinyGold bool +} + +type BagContent struct { + count int + color string +} + +// Given a bag statement string, returns its contents +func parseBagStatement(bagStatement string) Bag { + bagEndIndex := strings.Index(bagStatement, " bags contain ") + bagColor := bagStatement[:bagEndIndex] + bagContentsStr := bagStatement[bagEndIndex+14:] + + // if no aditional bags + if bagContentsStr[:2] == "no" { + return Bag{color: bagColor, contents: make([]BagContent, 0)} + } + + // parse remainder bags + bagsContained := strings.Split(bagContentsStr, ", ") + bagContents := make([]BagContent, len(bagsContained)) + + for idx, bag := range bagsContained { + bagCount, err := strconv.Atoi(bag[:1]) + if err != nil { + panic("expected a number, got `" + bag + "`") + } + + bagStrIndex := strings.Index(bag, " bag") + bagColor2 := bag[2:bagStrIndex] + + bagContents[idx] = BagContent{count: bagCount, color: bagColor2} + } + + /* + grammar for bag statements: + + statement = bag color, "bags contain", (bag list | empty bag), "." + empty bag = "no other bags" + bag list = bag declaration, bag declaration+ + bag declaration = number, bag color, "bag", "s"? + bag color = word, word + */ + + return Bag{color: bagColor, contents: bagContents} +} + +func bagContainsShinyGold(bag *Bag, bagMap map[string]Bag) bool { + if bag.containsShinyGold { + return true + } + + // recursively search + for _, bagName := range bag.contents { + if bagName.color == "shiny gold" { + bag.containsShinyGold = true + return true + } + + nextBag := bagMap[bagName.color] + + if bagContainsShinyGold(&nextBag, bagMap) { + bag.containsShinyGold = true + return true + } + } + + return false +} + +func Day07Part01(isTest bool) int { + input := ReadInput("07", isTest) + groups := strings.Split(input, "\n") + + bags := make(map[string]Bag) + + // parse and collect the bags + for _, statement := range groups { + parsedBag := parseBagStatement(statement) + bags[parsedBag.color] = parsedBag + } + + shinyGoldContainers := 0 + + // process the bags + for _, bag := range bags { + if bagContainsShinyGold(&bag, bags) { + shinyGoldContainers += 1 + } + } + + return shinyGoldContainers +} + +func Day07Part02(isTest bool) int { + return -1 +}