From fcdf31150bf201472f54c9852699418bc339ba97 Mon Sep 17 00:00:00 2001 From: Alex Chao Date: Tue, 7 Dec 2021 00:24:41 -0500 Subject: [PATCH] 2021 day7: oof integer rounding killed me... but thank goodness for a bit of tdd --- 2021/day07/main.go | 84 +++++++++++++++++++++++++++++++++++++++++ 2021/day07/main_test.go | 81 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 2021/day07/main.go create mode 100644 2021/day07/main_test.go diff --git a/2021/day07/main.go b/2021/day07/main.go new file mode 100644 index 0000000..d382d68 --- /dev/null +++ b/2021/day07/main.go @@ -0,0 +1,84 @@ +package main + +import ( + _ "embed" + "flag" + "fmt" + "math" + "strings" + + "github.com/alexchao26/advent-of-code-go/cast" + "github.com/alexchao26/advent-of-code-go/util" +) + +//go:embed input.txt +var input string + +func init() { + // do this in init (not main) so test file has same input + input = strings.TrimRight(input, "\n") + if len(input) == 0 { + panic("empty input.txt file") + } +} + +func main() { + var part int + flag.IntVar(&part, "part", 1, "part 1 or 2") + flag.Parse() + fmt.Println("Running part", part) + + ans := calcMinFuel(input, part) + util.CopyToClipboard(fmt.Sprintf("%v", ans)) + fmt.Println("Output:", ans) +} + +func calcMinFuel(input string, part int) int { + var startingPositions []int + for _, val := range strings.Split(input, ",") { + startingPositions = append(startingPositions, cast.ToInt(val)) + } + + // horizontal positions of each crab + // limited fuel, so all horizontal positions need to match + // part1: 1 fuel to move 1 space + // part2: 1 fuel to move 1st space, 2 for 2nd, 3 for 3rd, etc... + + // find bounds to run loop through + lowest, highest := startingPositions[0], startingPositions[0] + for _, v := range startingPositions { + if v < lowest { + lowest = v + } + if v > highest { + highest = v + } + } + + bestFuelCost := math.MaxInt64 + for finalIndex := lowest; finalIndex <= highest; finalIndex++ { + // calculate diffs to all + cost := 0 + for _, startIndex := range startingPositions { + horizDiff := int(math.Abs(float64(startIndex - finalIndex))) + if part == 1 { + cost += horizDiff + } else { + cost += calcSummationFromOneToEnd(horizDiff) + } + } + + if cost < bestFuelCost { + bestFuelCost = cost + } + } + + return bestFuelCost +} + +func calcSummationFromOneToEnd(end int) int { + // 1 2 3 4 5 + // (1 + 5) * 2.5 + ans := float64(end+1) * float64(end) / 2 + return int(ans) +} diff --git a/2021/day07/main_test.go b/2021/day07/main_test.go new file mode 100644 index 0000000..b134212 --- /dev/null +++ b/2021/day07/main_test.go @@ -0,0 +1,81 @@ +package main + +import ( + _ "embed" + "testing" +) + +var example = `16,1,2,0,4,2,7,1,2,14` + +func Test_calcMinFuel(t *testing.T) { + tests := []struct { + name string + input string + part int + want int + }{ + { + name: "example", + input: example, + part: 1, + want: 37, + }, + { + name: "actual", + input: input, + part: 1, + want: 329389, + }, + { + name: "example", + input: example, + part: 2, + want: 168, + }, + { + name: "actual", + input: input, + part: 2, + want: 86397080, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := calcMinFuel(tt.input, tt.part); got != tt.want { + t.Errorf("calcMinFuel() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_calcSummationFromOneToEnd(t *testing.T) { + // auto generated these tests because math is rough... + type args struct { + end int + } + tests := []struct { + name string + args args + want int + }{ + { + args: args{end: 4}, + want: 10, + }, + { + args: args{end: 5}, + want: 15, + }, + { + args: args{end: 6}, + want: 21, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := calcSummationFromOneToEnd(tt.args.end); got != tt.want { + t.Errorf("calcSummationFromOneToEnd() = %v, want %v", got, tt.want) + } + }) + } +}