From 60ef7a055725566de9cc16354ef45652cec48a3b Mon Sep 17 00:00:00 2001 From: onyx-and-iris Date: Wed, 6 Dec 2023 15:56:20 +0000 Subject: [PATCH] day-6 --- day-6/go.mod | 3 +++ day-6/one.go | 39 ++++++++++++++++++++++++++++++++ day-6/one_test.go | 16 +++++++++++++ day-6/solution.go | 21 +++++++++++++++++ day-6/two.go | 34 ++++++++++++++++++++++++++++ day-6/util.go | 57 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 170 insertions(+) create mode 100644 day-6/go.mod create mode 100644 day-6/one.go create mode 100644 day-6/one_test.go create mode 100644 day-6/solution.go create mode 100644 day-6/two.go create mode 100644 day-6/util.go diff --git a/day-6/go.mod b/day-6/go.mod new file mode 100644 index 0000000..0127354 --- /dev/null +++ b/day-6/go.mod @@ -0,0 +1,3 @@ +module github.com/onyx-and-iris/aoc2023/day-6 + +go 1.20 diff --git a/day-6/one.go b/day-6/one.go new file mode 100644 index 0000000..0924e97 --- /dev/null +++ b/day-6/one.go @@ -0,0 +1,39 @@ +package main + +type data struct { + time int + distance int +} + +var datas = make([]data, 0) + +// calculate returns the number of different ways to win a single race +func calculate(time, recordDistance int) int { + distanceCovered := 0 + numWins := 0 + + f := func(x, time int) int { + return x * (time - x) + } + + for i := 1; i < time; i++ { + distanceCovered = f(i, time) + if distanceCovered > recordDistance { + numWins++ + } + } + return numWins +} + +// one returns the product of all race calculations +func one(lines []string) int { + parseLines(lines) + + product := 1 + for _, data := range datas { + n := calculate(data.time, data.distance) + product *= n + } + + return product +} diff --git a/day-6/one_test.go b/day-6/one_test.go new file mode 100644 index 0000000..5ce55e1 --- /dev/null +++ b/day-6/one_test.go @@ -0,0 +1,16 @@ +package main + +import ( + "testing" + + "github.com/go-playground/assert" +) + +func TestCalculate(t *testing.T) { + //t.Skip("skipping test") + res := calculate(7, 9) + + t.Run("Should produce an equal number of win possibilities", func(t *testing.T) { + assert.Equal(t, []int{2, 3, 4, 5}, res) + }) +} diff --git a/day-6/solution.go b/day-6/solution.go new file mode 100644 index 0000000..35ea384 --- /dev/null +++ b/day-6/solution.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + + log "github.com/sirupsen/logrus" +) + +func init() { + log.SetLevel(log.DebugLevel) +} + +func main() { + lines := readlines() + + ans := one(lines) + fmt.Printf("solution one: %d\n", ans) + + ans = two(lines) + fmt.Printf("solution two: %d\n", ans) +} diff --git a/day-6/two.go b/day-6/two.go new file mode 100644 index 0000000..18d24e2 --- /dev/null +++ b/day-6/two.go @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" + "math" + "strconv" +) + +// calculateFaster uses quadratic formula to calculate number of ways to win +func calculateFaster(time, recordDistance int) int { + a := float64(-1) + b := float64(time) + c := float64(-(recordDistance + 1)) + + x1 := (-b + math.Sqrt(math.Pow(b, 2)-4*a*c)) / (2 * a) + x2 := (-b - math.Sqrt(math.Pow(b, 2)-4*a*c)) / (2 * a) + + return int(math.Floor(x2) - math.Ceil(x1) + 1) +} + +func two(lines []string) int { + timeStr := "" + distStr := "" + for _, data := range datas { + timeStr += fmt.Sprintf("%d", data.time) + distStr += fmt.Sprintf("%d", data.distance) + } + time, _ := strconv.Atoi(timeStr) + distance, _ := strconv.Atoi(distStr) + + n := calculateFaster(time, distance) + + return n +} diff --git a/day-6/util.go b/day-6/util.go new file mode 100644 index 0000000..3d325ac --- /dev/null +++ b/day-6/util.go @@ -0,0 +1,57 @@ +package main + +import ( + "bufio" + "log" + "os" + "strconv" + "strings" + "unicode" +) + +// readlines reads lines from stdin. +// Then it returns them as an array of strings +func readlines() []string { + lines := []string{} + + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } + + if err := scanner.Err(); err != nil { + log.Fatal(err) + } + + return lines +} + +func parseLines(lines []string) { + f := func(c rune) bool { + return !unicode.IsDigit(c) + } + + times := []int{} + distances := []int{} + for _, line := range lines { + if strings.HasPrefix(line, "Time") { + times = convertToInts(strings.FieldsFunc(line, f)) + } else { + distances = convertToInts(strings.FieldsFunc(line, f)) + } + } + + for i := range times { + datas = append(datas, data{time: times[i], distance: distances[i]}) + } +} + +// convertToInts converts a string representing ints to an array of ints +func convertToInts(data []string) []int { + nums := []int{} + for _, elem := range data { + n, _ := strconv.Atoi(elem) + nums = append(nums, n) + } + return nums +}