@@ -2,7 +2,9 @@ package main
22
33import (
44 _ "embed"
5+ "math"
56 "os"
7+ "strings"
68)
79
810//go:embed input.txt
@@ -11,36 +13,118 @@ var input string
1113//go:embed input_test.txt
1214var inputTest string
1315
16+ type Race struct {
17+ time , distance int
18+ }
19+
20+ var races []Race
21+ var bigRace Race
22+
1423func main () {
1524 // Check argv if we use test input or not
1625 if len (os .Args ) > 1 && os .Args [1 ] == "test" {
1726 input = inputTest
1827 }
1928
20- answer := doPartOne (input )
29+ parseInput (input )
30+
31+ answer := doPartOne ()
2132 println (answer )
2233
23- answer = doPartTwo (input )
34+ answer = doPartTwo ()
2435 println (answer )
2536}
2637
27- type Race struct {
28- Time , Distance int
38+ func parseInput (input string ) {
39+ lines := strings .Split (strings .TrimSpace (input ), "\n " )
40+
41+ // Parse times and distances
42+ times := parseNumbers (lines [0 ])
43+ distances := parseNumbers (lines [1 ])
44+
45+ // Part 1: individual races
46+ races = make ([]Race , len (times ))
47+ for i := range races {
48+ races [i ] = Race {times [i ], distances [i ]}
49+ }
50+
51+ // Part 2: concatenated race
52+ bigRace = Race {concatenateNumbers (times ), concatenateNumbers (distances )}
2953}
3054
31- func getWays (r Race ) int {
32- max := getVal (r , r .Time , - 1 )
33- min := getVal (r , 0 , 1 )
34- return max - min + 1
55+ func parseNumbers (line string ) []int {
56+ var nums []int
57+ i := 0
58+ for i < len (line ) {
59+ if line [i ] >= '0' && line [i ] <= '9' {
60+ num := 0
61+ for i < len (line ) && line [i ] >= '0' && line [i ] <= '9' {
62+ num = num * 10 + int (line [i ]- '0' )
63+ i ++
64+ }
65+ nums = append (nums , num )
66+ } else {
67+ i ++
68+ }
69+ }
70+ return nums
3571}
3672
37- func getVal (r Race , S , M int ) int {
38- for i := 0 ; i < r .Time ; i ++ {
39- runtime := r .Time - (S + i * M )
40- D := (S + i * M ) * runtime
41- if D > r .Distance {
42- return (S + i * M )
73+ func concatenateNumbers (nums []int ) int {
74+ result := 0
75+ for _ , n := range nums {
76+ // Count digits in n
77+ temp := n
78+ multiplier := 1
79+ for temp > 0 {
80+ multiplier *= 10
81+ temp /= 10
4382 }
83+ result = result * multiplier + n
84+ }
85+ return result
86+ }
87+
88+ // Mathematical solution using quadratic formula
89+ // Distance d = h * (t - h) where h is hold time, t is total time
90+ // Need: h * (t - h) > record
91+ // Rearrange: -h² + t*h - record > 0
92+ // Solve: h² - t*h + record < 0
93+ // Using quadratic formula: h = (t ± sqrt(t² - 4*record)) / 2
94+ func getWays (r Race ) int {
95+ t := float64 (r .time )
96+ d := float64 (r .distance )
97+
98+ // Discriminant
99+ disc := t * t - 4 * d
100+ if disc < 0 {
101+ return 0
102+ }
103+
104+ sqrtDisc := math .Sqrt (disc )
105+
106+ // Two solutions from quadratic formula
107+ h1 := (t - sqrtDisc ) / 2
108+ h2 := (t + sqrtDisc ) / 2
109+
110+ // We need integer hold times strictly greater than the record
111+ // Round up h1, round down h2
112+ minHold := int (math .Floor (h1 + 1 ))
113+ maxHold := int (math .Ceil (h2 - 1 ))
114+
115+ // Edge case: if h1 is exactly an integer, we need strictly greater
116+ if h1 == math .Floor (h1 ) {
117+ minHold = int (h1 ) + 1
118+ }
119+
120+ // Edge case: if h2 is exactly an integer, we need strictly less
121+ if h2 == math .Ceil (h2 ) {
122+ maxHold = int (h2 ) - 1
44123 }
45- return r .Time - S
124+
125+ if maxHold < minHold {
126+ return 0
127+ }
128+
129+ return maxHold - minHold + 1
46130}
0 commit comments