88using System . Security ;
99using static AdventOfCode . Solutions . Utilities ;
1010using System . Runtime . CompilerServices ;
11+ using System . Numerics ;
12+ using System . Net . Http . Headers ;
1113
1214namespace AdventOfCode . Solutions . Year2023
1315{
14- [ DayInfo ( 24 , 2023 , "" ) ]
16+ [ DayInfo ( 24 , 2023 , "Never Tell Me The Odds " ) ]
1517 class Day24 : ASolution
1618 {
19+ List < Hailstone > Hailstones = new ( ) ;
20+
21+ const long min = 200000000000000L ;
22+ const long max = 400000000000000L ;
23+
1724 public Day24 ( ) : base ( )
1825 {
26+ foreach ( var l in Input . SplitByNewline ( ) )
27+ {
28+ var nums = l . ExtractLongs ( ) . ToList ( ) ;
1929
30+ Hailstones . Add ( new ( nums [ 0 ] , nums [ 1 ] , nums [ 2 ] , nums [ 3 ] , nums [ 4 ] , nums [ 5 ] ) ) ;
31+ }
2032 }
2133
2234 protected override object SolvePartOne ( )
2335 {
24- return null ;
36+
37+ long valid = 0 ;
38+ foreach ( var combo in Hailstones . Combinations ( 2 ) ) {
39+ Hailstone h1 = combo . First ( ) ;
40+ Hailstone h2 = combo . Last ( ) ;
41+
42+ ( var x1 , var y1 , var z1 ) = ( h1 . X , h1 . Y , h1 . Z ) ;
43+ ( var x2 , var y2 , var z2 ) = ( h1 . p2 . X , h1 . p2 . Y , h1 . p2 . Z ) ;
44+ ( var x3 , var y3 , var z3 ) = ( h2 . X , h2 . p2 . Y , h2 . p2 . Z ) ;
45+ ( var x4 , var y4 , var z4 ) = ( h2 . p2 . X , h2 . p2 . Y , h2 . p2 . Z ) ;
46+
47+ var xNumerator = ( ( x1 * y2 - y1 * x2 ) * ( x3 - x4 ) ) - ( ( x1 - x2 ) * ( x3 * y4 - y3 * x4 ) ) ;
48+ var xDenominator = ( x1 - x2 ) * ( y3 - y4 ) - ( y1 - y2 ) * ( x3 - x4 ) ;
49+
50+ var yNumerator = ( ( x1 * y2 - y1 * x2 ) * ( y3 - y4 ) ) - ( ( y1 - y2 ) * ( x3 * y4 - y3 * x4 ) ) ;
51+ var yDenominator = ( x1 - x2 ) * ( y3 - y4 ) - ( y1 - y2 ) * ( x3 - x4 ) ;
52+
53+ if ( xDenominator == 0 || yDenominator == 0 ) continue ; //Lines are parralel
54+ else
55+ {
56+ decimal xPos = ( decimal ) xNumerator / ( decimal ) xDenominator ;
57+ decimal yPos = ( decimal ) yNumerator / ( decimal ) yDenominator ;
58+
59+ if ( min <= xPos && xPos <= max && min <= yPos && yPos <= max )
60+ {
61+ if ( h1 . TimeAtXYPosition ( xPos , yPos ) < 0 || h2 . TimeAtXYPosition ( xPos , yPos ) < 0 )
62+ {
63+ continue ; //Occurred in someones past
64+ }
65+ else
66+ {
67+ valid ++ ;
68+ }
69+ }
70+ }
71+ }
72+ return valid ;
2573 }
2674
2775 protected override object SolvePartTwo ( )
2876 {
29- return null ;
77+ HashSet < long > possibleXV = null ;
78+ HashSet < long > possibleYV = null ;
79+ HashSet < long > possibleZV = null ;
80+
81+ foreach ( var c in Hailstones . Combinations ( 2 ) . Where ( a => a . First ( ) . dX == a . Last ( ) . dX ) )
82+ {
83+ HashSet < long > tmp = new ( ) ;
84+ long hailVelocity = ( long ) c . First ( ) . dX ;
85+ long distanceDiff = ( long ) ( c . Last ( ) . X - c . First ( ) . X ) ;
86+ for ( long i = - 1000 ; i <= 1000 ; i ++ )
87+ {
88+ try
89+ {
90+ if ( distanceDiff % ( i - hailVelocity ) == 0 ) tmp . Add ( i ) ;
91+ } catch ( Exception e ) { }
92+ }
93+
94+
95+ if ( possibleXV == null )
96+ {
97+ possibleXV = new ( tmp ) ;
98+ } else
99+ {
100+ possibleXV = possibleXV . Intersect ( tmp ) . ToHashSet < long > ( ) ;
101+ }
102+
103+ if ( possibleXV . Count == 1 ) break ;
104+ }
105+
106+ foreach ( var c in Hailstones . Combinations ( 2 ) . Where ( a => a . First ( ) . dY == a . Last ( ) . dY ) )
107+ {
108+ HashSet < long > tmp = new ( ) ;
109+ long hailVelocity = ( long ) c . First ( ) . dY ;
110+ long distanceDiff = ( long ) ( c . Last ( ) . Y - c . First ( ) . Y ) ;
111+ for ( long i = - 1000 ; i <= 1000 ; i ++ )
112+ {
113+ try
114+ {
115+ if ( distanceDiff % ( i - hailVelocity ) == 0 ) tmp . Add ( i ) ;
116+ }
117+ catch ( Exception e ) { }
118+ }
119+
120+
121+ if ( possibleYV == null )
122+ {
123+ possibleYV = new ( tmp ) ;
124+ }
125+ else
126+ {
127+ possibleYV = possibleYV . Intersect ( tmp ) . ToHashSet < long > ( ) ;
128+ }
129+
130+ if ( possibleYV . Count == 1 ) break ;
131+ }
132+
133+ foreach ( var c in Hailstones . Combinations ( 2 ) . Where ( a => a . First ( ) . dZ == a . Last ( ) . dZ ) )
134+ {
135+ HashSet < long > tmp = new ( ) ;
136+ long hailVelocity = ( long ) c . First ( ) . dZ ;
137+ long distanceDiff = ( long ) ( c . Last ( ) . Z - c . First ( ) . Z ) ;
138+ for ( long i = - 1000 ; i <= 1000 ; i ++ )
139+ {
140+ try
141+ {
142+ if ( distanceDiff % ( i - hailVelocity ) == 0 ) tmp . Add ( i ) ;
143+ }
144+ catch ( Exception e ) { }
145+ }
146+
147+
148+ if ( possibleZV == null )
149+ {
150+ possibleZV = new ( tmp ) ;
151+ }
152+ else
153+ {
154+ possibleZV = possibleZV . Intersect ( tmp ) . ToHashSet < long > ( ) ;
155+ }
156+
157+ if ( possibleZV . Count == 1 ) break ;
158+ }
159+
160+ long dXi = possibleXV . Single ( ) ;
161+ long dYi = possibleYV . Single ( ) ;
162+ long dZi = possibleZV . Single ( ) ;
163+
164+ Hailstone h1 = Hailstones . First ( ) ;
165+ Hailstone h2 = Hailstones . Skip ( 10 ) . Take ( 1 ) . Single ( ) ;
166+
167+ h1 . dX = h1 . dX - dXi ;
168+ h2 . dX = h2 . dX - dXi ;
169+ h1 . dY = h1 . dY - dXi ;
170+ h2 . dY = h2 . dY - dXi ;
171+ h1 . dZ = h1 . dZ - dXi ;
172+ h2 . dZ = h2 . dZ - dXi ;
173+
174+
175+ var slopA = ( decimal ) h1 . dY / ( decimal ) h1 . dX ;
176+ var slopeB = ( decimal ) h2 . dY / ( decimal ) h2 . dX ;
177+
178+ var intersectA = ( decimal ) h1 . Y - ( slopA * ( decimal ) h1 . X ) ;
179+ var interesectB = ( decimal ) h2 . Y - ( slopeB * ( decimal ) h2 . X ) ;
180+
181+ long xPos = ( ( long ) ( ( interesectB - intersectA ) / ( slopA - slopeB ) ) ) ;
182+ long yPos = ( long ) ( slopA * xPos + intersectA ) ;
183+ long time = ( long ) ( ( xPos - h1 . X ) / h1 . dX ) ;
184+
185+ long zPos = ( long ) ( h1 . Z + ( dZi * time ) ) ;
186+
187+ Console . WriteLine ( $ "{{{dXi}}}, {{{dYi}}}, {{{dZi}}}") ;
188+ Console . WriteLine ( $ "{{{xPos}}}, {{{yPos}}}, {{{zPos}}}") ;
189+
190+
191+ return xPos + yPos + zPos ;
192+ }
193+
194+ private class Hailstone
195+ {
196+ public BigInteger X ;
197+ public BigInteger Y ;
198+ public BigInteger Z ;
199+
200+ public BigInteger dX ;
201+ public BigInteger dY ;
202+ public BigInteger dZ ;
203+
204+ public Hailstone ( long x , long y , long z , long dX , long dY , long dZ )
205+ {
206+ X = x ;
207+ Y = y ;
208+ Z = z ;
209+ this . dX = dX ;
210+ this . dY = dY ;
211+ this . dZ = dZ ;
212+ }
213+
214+ public ( BigInteger X , BigInteger Y , BigInteger Z ) PositionAtTime ( long t ) => ( this . X + ( t * dX ) , this . Y + ( t * dY ) , this . Z + ( t * dZ ) ) ;
215+ public ( BigInteger X , BigInteger Y , BigInteger Z ) p2 => ( X + dX , Y + dY , Z + dZ ) ;
216+ public decimal TimeAtXYPosition ( decimal x , decimal y )
217+ {
218+ if ( dX != 0 )
219+ {
220+ return ( x - ( decimal ) X ) / ( decimal ) dX ;
221+ }
222+
223+ return ( y - ( decimal ) Y ) / ( decimal ) dY ;
224+ }
30225 }
31226 }
32- }
227+ }
0 commit comments