From e8b6c9cbde2218515aea99dcfa9b5321165781e5 Mon Sep 17 00:00:00 2001 From: alexchao26 Date: Sat, 26 Dec 2020 21:52:22 -0500 Subject: [PATCH] 2015-day17: recursive backtrack to valid combinations --- 2015/day17/main.go | 67 +++++++++++++++++++++++++++++++++++++++++ 2015/day17/main_test.go | 38 +++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 2015/day17/main.go create mode 100644 2015/day17/main_test.go diff --git a/2015/day17/main.go b/2015/day17/main.go new file mode 100644 index 0000000..bbf3a05 --- /dev/null +++ b/2015/day17/main.go @@ -0,0 +1,67 @@ +package main + +import ( + "flag" + "fmt" + "math" + "strings" + + "github.com/alexchao26/advent-of-code-go/cast" + "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) + + ans := eggnogCombinations(util.ReadFile("./input.txt"), 150, part) + fmt.Println("Output:", ans) +} + +func eggnogCombinations(input string, target int, part int) int { + var nums []int + for _, line := range strings.Split(input, "\n") { + nums = append(nums, cast.ToInt(line)) + } + + allIndexCombinations := backtrack(nums, 0, target, []int{}) + // part 1, just return len + if part == 1 { + return len(allIndexCombinations) + } + + // part 2, get the number of combinations w/ the lowest length + minLen := math.MaxInt32 + for _, comb := range allIndexCombinations { + minLen = mathutil.MinInt(minLen, len(comb)) + } + + var count int + for _, comb := range allIndexCombinations { + if len(comb) == minLen { + count++ + } + } + + return count +} + +func backtrack(nums []int, startingIndex, remaining int, usedIndices []int) [][]int { + if remaining == 0 { + return [][]int{append([]int{}, usedIndices...)} + } + if remaining < 0 { + return nil + } + + var validReturns [][]int + for i := startingIndex; i < len(nums); i++ { + usedIndices = append(usedIndices, i) + validReturns = append(validReturns, backtrack(nums, i+1, remaining-nums[i], usedIndices)...) + usedIndices = usedIndices[:len(usedIndices)-1] + } + return validReturns +} diff --git a/2015/day17/main_test.go b/2015/day17/main_test.go new file mode 100644 index 0000000..286ebde --- /dev/null +++ b/2015/day17/main_test.go @@ -0,0 +1,38 @@ +package main + +import ( + "testing" + + "github.com/alexchao26/advent-of-code-go/util" +) + +var example = `20 +15 +10 +5 +5` + +func Test_eggnogCombinations(t *testing.T) { + type args struct { + input string + target int + part int + } + tests := []struct { + name string + args args + want int + }{ + {"part1 example", args{example, 25, 1}, 4}, + {"part1 actual", args{util.ReadFile("input.txt"), 150, 1}, 1304}, + {"part2 example", args{example, 25, 2}, 3}, + {"part2 actual", args{util.ReadFile("input.txt"), 150, 2}, 18}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := eggnogCombinations(tt.args.input, tt.args.target, tt.args.part); got != tt.want { + t.Errorf("eggnogCombinations() = %v, want %v", got, tt.want) + } + }) + } +}