From 1c3221e6713c46affb8d0a5feee7d5ac3fcd7ae0 Mon Sep 17 00:00:00 2001 From: Russell Champoux Date: Mon, 6 Dec 2021 13:13:15 -0500 Subject: [PATCH] add day 6 --- day-6/main.go | 120 +++++++++++++++++++++++++++++++++++++++++++++ day-6/main_test.go | 11 +++++ main.go.template | 27 +++++----- 3 files changed, 145 insertions(+), 13 deletions(-) create mode 100644 day-6/main.go create mode 100644 day-6/main_test.go diff --git a/day-6/main.go b/day-6/main.go new file mode 100644 index 0000000..adcf013 --- /dev/null +++ b/day-6/main.go @@ -0,0 +1,120 @@ +/* Day 6: Lanternfish */ +package main + +import ( + "AoC2021/utils/log" + "AoC2021/utils/timer" + "bufio" + "fmt" + "os" + "strconv" + "strings" +) + +const REPRODUCE_DAYS = 7 +const JUVINILE_DAYS = 2 + +func check(e error) { + if e != nil { + log.Println(log.DEBUG, "Oh snap!") + panic(e) + } +} + +func main() { + log.LOG_LEVEL = log.NORMAL + + log.Println(log.NORMAL, "--- Day 6: Lanternfish ---") + timer.Start() + part1() + timer.Tick() + log.Println(log.NORMAL) + + part2() + timer.Tick() + log.Println(log.NORMAL) +} + +func part1() { + log.Println(log.NORMAL, "* Part 1 *") + log.Println(log.NORMAL, " Goal: Find a way to simulate lanternfish.") + log.Println(log.NORMAL, " Answer: How many lanternfish would there be after 80 days?") + + justDoIt(80) +} + +func part2() { + log.Println(log.NORMAL, "* Part 2 *") + log.Println(log.NORMAL, " Goal: Would they take over the entire ocean?") + log.Println(log.NORMAL, " Answer: How many lanternfish would there be after 256 days?") + + justDoIt(256) +} + +func justDoIt(total_days int) { + input, err := os.Open("./input.txt") + check(err) + defer input.Close() + + scanner := bufio.NewScanner(input) + + // Keeping track of each individual fish is stupid + // Instead track how *many* fish are at each gestation period + groupCount := make([]uint, REPRODUCE_DAYS+JUVINILE_DAYS) + + startingCount := 0 + lines := 0 + + // Read in all the starting fish + for scanner.Scan() { + startingFish := strings.Split(scanner.Text(), ",") + startingCount += len(startingFish) + + lines++ + // A fish read in as day '3' will be counted at index '2' since day '0' is a valid day + for _, fish := range startingFish { + day, err := strconv.Atoi(fish) + check(err) + if day > REPRODUCE_DAYS { + panic(fmt.Sprintf("Read an invalid value for fish day: %d", day)) + } + groupCount[day] += 1 + } + } + log.Printf(log.NORMAL, "Parsed %d fish from %d lines from input\n", startingCount, lines) + log.Println(log.DEBUG, "Fishes group count", groupCount) + log.Println(log.DEBUG) + + // Begin the simulation + for day := 0; day < total_days; day++ { + // keep track of this for later + readyToReproduce := groupCount[0] + log.Printf(log.DEBUG, "Day %d starts with %d fish ", day+1, sumFish(groupCount)) + log.Print(log.DEBUG, groupCount) + // shift down ALL groups + for fishDay := 1; fishDay < REPRODUCE_DAYS+JUVINILE_DAYS; fishDay++ { + groupCount[fishDay-1] = groupCount[fishDay] + } + // Spawn new fish + groupCount[REPRODUCE_DAYS+JUVINILE_DAYS-1] = readyToReproduce + // Add the fish that reproduced back into the pool + groupCount[REPRODUCE_DAYS-1] += readyToReproduce + log.Printf(log.DEBUG, " and ends with %d fish ", sumFish((groupCount))) + log.Print(log.DEBUG, groupCount) + log.Println(log.DEBUG) + } + + // Add them all up and be sad that there is no map reduce in golang + totalCount := sumFish(groupCount) + + log.Printf(log.NORMAL, "At the end of %d days there were %d fish\n", total_days, totalCount) +} + +func sumFish(counts []uint) uint { + total := uint(0) + for _, count := range counts { + total += count + } + + return total +} diff --git a/day-6/main_test.go b/day-6/main_test.go new file mode 100644 index 0000000..298b3fd --- /dev/null +++ b/day-6/main_test.go @@ -0,0 +1,11 @@ +package main + +import ( + assert "AoC2021/utils/testing" + "testing" +) + +func TestDay6(t *testing.T) { + assert.IsTrue(t, true, "cool") + assert.StrEquals(t, "foo", "bar", "baz") +} diff --git a/main.go.template b/main.go.template index 056916b..fb07a0d 100644 --- a/main.go.template +++ b/main.go.template @@ -2,6 +2,7 @@ package main import ( + "AoC2021/utils/log" "AoC2021/utils/timer" "bufio" "fmt" @@ -10,31 +11,31 @@ import ( func check(e error) { if e != nil { - fmt.Println("Oh snap!") + log.Println(log.DEBUG, "Oh snap!") panic(e) } } func main() { - fmt.Println("--- Day #DAY#: #TITLE# ---") + log.Println(log.NORMAL, "--- Day #DAY#: #TITLE# ---") timer.Start() part1() timer.Tick() - fmt.Println() + log.Println(log.NORMAL) part2() timer.Tick() - fmt.Println() + log.Println(log.NORMAL) } func part1() { - fmt.Println("* Part 1 *") - fmt.Println(" Goal: ") - fmt.Println(" Answer: ") + log.Println(log.NORMAL, "* Part 1 *") + log.Println(log.NORMAL, " Goal: ") + log.Println(log.NORMAL, " Answer: ") input, err := os.Open("./input.txt") - defer input.Close() check(err) + defer input.Close() scanner := bufio.NewScanner(input) lines := 0 @@ -45,12 +46,12 @@ func part1() { lines++ } - fmt.Printf("Read %d lines from input\n", lines) - fmt.Printf("The solution is %d\n", answer) + log.Printf(log.NORMAL, "Read %d lines from input\n", lines) + log.Printf(log.NORMAL, "The solution is %d\n", answer) } func part2() { - fmt.Println("* Part 2 *") - fmt.Println(" Goal: ") - fmt.Println(" Answer: ") + log.Println(log.NORMAL, "* Part 2 *") + log.Println(log.NORMAL, " Goal: ") + log.Println(log.NORMAL, " Answer: ") }