From 7b59c510d8bac669861f24727eee867d8e744ec8 Mon Sep 17 00:00:00 2001 From: alexchao26 Date: Sun, 13 Dec 2020 21:18:16 -0500 Subject: [PATCH] 2017-day6: cycling until state repeats itself --- 2017/day06/main.go | 77 +++++++++++++++++++++++++++++++++++++++++ 2017/day06/main_test.go | 27 +++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 2017/day06/main.go create mode 100644 2017/day06/main_test.go diff --git a/2017/day06/main.go b/2017/day06/main.go new file mode 100644 index 0000000..83e07ef --- /dev/null +++ b/2017/day06/main.go @@ -0,0 +1,77 @@ +package main + +import ( + "flag" + "fmt" + "strings" + + "github.com/alexchao26/advent-of-code-go/mathutil" + "github.com/alexchao26/advent-of-code-go/util" +) + +func main() { + var part int + flag.IntVar(&part, "part", 1, "part 1 or 2") + flag.Parse() + fmt.Println("Running part", part) + + if part == 1 { + ans := memoryReallocation(util.ReadFile("./input.txt"), 1) + fmt.Println("Output:", ans) + } else { + ans := memoryReallocation(util.ReadFile("./input.txt"), 2) + fmt.Println("Output:", ans) + } +} + +func memoryReallocation(input string, part int) int { + banks := parseInput(input) + + // [16]int arrays are comparable by values so can be used as map keys + seenBanks := map[[16]int]int{banks: 0} + var cycles int + for { + // find largest bank + var index, maxVal int + for i, val := range banks { + if val > maxVal { + index = i + maxVal = val + } + } + + // run a cycle + blocksToDistribute := banks[index] + banks[index] = 0 + // unoptimized but works just fine + for i := index + 1; blocksToDistribute > 0; i++ { + if blocksToDistribute == 0 { + break + } + banks[i%16]++ + blocksToDistribute-- + } + cycles++ + + // check if this set of banks has been seen before, if so return here + if val, ok := seenBanks[banks]; ok { + if part == 1 { + return cycles + } + // for part 2 take the difference with cycles when it was last seen + return cycles - val + } + // set the number of cycles that correspond to this state of banks + seenBanks[banks] = cycles + } + + panic("should resolve in for loop") +} + +func parseInput(input string) (ans [16]int) { + nums := strings.Split(input, "\t") + for i, num := range nums { + ans[i] = mathutil.StrToInt(num) + } + return ans +} diff --git a/2017/day06/main_test.go b/2017/day06/main_test.go new file mode 100644 index 0000000..f0bd7d0 --- /dev/null +++ b/2017/day06/main_test.go @@ -0,0 +1,27 @@ +package main + +import ( + "testing" + + "github.com/alexchao26/advent-of-code-go/util" +) + +func Test_memoryReallocation(t *testing.T) { + tests := []struct { + name string + input string + part int + want int + }{ + {"actual", util.ReadFile("input.txt"), 1, 6681}, + {"actual", util.ReadFile("input.txt"), 2, 2392}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := memoryReallocation(tt.input, tt.part); got != tt.want { + t.Errorf("memoryReallocation() = %v, want %v", got, tt.want) + } + }) + } + +}