1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . IO ;
4+ using System . Linq ;
5+ using System . Text ;
6+ using System . Text . RegularExpressions ;
7+ using AdventOfCode . Util ;
8+
9+ namespace AdventOfCode2024
10+ {
11+ internal class Day17
12+ {
13+ private static ( long [ ] Registers , List < int > Program ) Load ( )
14+ {
15+ Regex regA = new Regex ( "^Register A: (-?\\ d+)$" ) ;
16+ Regex regB = new Regex ( "^Register B: (-?\\ d+)$" ) ;
17+ Regex regC = new Regex ( "^Register C: (-?\\ d+)$" ) ;
18+
19+ long a = 0 ;
20+ long b = 0 ;
21+ long c = 0 ;
22+
23+ foreach ( string data in Data . Enumerate ( ) )
24+ {
25+ if ( string . IsNullOrEmpty ( data ) )
26+ {
27+ continue ;
28+ }
29+
30+ Match m = regA . Match ( data ) ;
31+
32+ if ( m . Success )
33+ {
34+ a = int . Parse ( m . Groups [ 1 ] . ValueSpan ) ;
35+ continue ;
36+ }
37+
38+ m = regB . Match ( data ) ;
39+
40+ if ( m . Success )
41+ {
42+ b = int . Parse ( m . Groups [ 1 ] . ValueSpan ) ;
43+ continue ;
44+ }
45+
46+ m = regC . Match ( data ) ;
47+
48+ if ( m . Success )
49+ {
50+ c = int . Parse ( m . Groups [ 1 ] . ValueSpan ) ;
51+ continue ;
52+ }
53+
54+ return ( [ a , b , c ] , data . Substring ( "Program: " . Length ) . Split ( ',' ) . Select ( int . Parse ) . ToList ( ) ) ;
55+ }
56+
57+ throw new InvalidDataException ( ) ;
58+ }
59+
60+ internal static void Problem1 ( )
61+ {
62+ ( long [ ] registers , List < int > program ) = Load ( ) ;
63+
64+ int ip = 0 ;
65+
66+ while ( true )
67+ {
68+ int inc = Compute ( ip , registers , program ) ;
69+
70+ if ( inc == int . MinValue )
71+ {
72+ break ;
73+ }
74+
75+ ip += inc ;
76+ }
77+
78+ Console . WriteLine ( ) ;
79+ }
80+
81+ internal static void Problem2 ( )
82+ {
83+ ( long [ ] registers , List < int > program ) = Load ( ) ;
84+ long [ ] originalRegisters = registers . AsSpan ( ) . ToArray ( ) ;
85+ string programStr = string . Join ( "," , program . Select ( i=> i . ToString ( ) ) ) + "," ;
86+
87+ StringBuilder builder = new ( ) ;
88+ Queue < long > aValues = new ( ) ;
89+ aValues . Enqueue ( 0 ) ;
90+
91+ while ( aValues . TryDequeue ( out long a ) )
92+ {
93+ a <<= 3 ;
94+
95+ for ( int i = 0 ; i <= 7 ; i ++ )
96+ {
97+ a = ( a >> 3 << 3 ) | i ;
98+ builder . Clear ( ) ;
99+ long saveA = a ;
100+
101+ originalRegisters . AsSpan ( ) . CopyTo ( registers ) ;
102+ registers [ 0 ] = a ;
103+
104+ int ip = 0 ;
105+
106+ while ( true )
107+ {
108+ int inc = Compute ( ip , registers , program , builder ) ;
109+
110+ if ( inc == int . MinValue )
111+ {
112+ break ;
113+ }
114+
115+ ip += inc ;
116+ }
117+
118+ string output = builder . ToString ( ) ;
119+ if ( programStr . EndsWith ( output ) )
120+ {
121+ Console . WriteLine ( saveA ) ;
122+
123+ Console . WriteLine ( output ) ;
124+
125+ if ( programStr . Equals ( output ) )
126+ {
127+ Console . WriteLine ( $ "Submit{ saveA } ") ;
128+ return ;
129+ }
130+
131+ aValues . Enqueue ( a ) ;
132+ }
133+ }
134+ }
135+ }
136+
137+ private static int Compute ( int ip , long [ ] registers , List < int > program , StringBuilder builder = default )
138+ {
139+ if ( ip > program . Count - 1 )
140+ {
141+ return int . MinValue ;
142+ }
143+
144+ int op = program [ ip ] ;
145+ int arg = program [ ip + 1 ] ;
146+ int inc = 2 ;
147+
148+ switch ( op )
149+ {
150+ case 0 :
151+ // adv
152+ registers [ 0 ] /= ( int ) double . Pow ( 2 , ComboReg ( arg , registers ) ) ;
153+ break ;
154+ case 1 :
155+ // bxl
156+ registers [ 1 ] ^= arg ;
157+ break ;
158+ case 2 :
159+ // bst
160+ registers [ 1 ] = ComboReg ( arg , registers ) & 7 ;
161+ break ;
162+ case 3 :
163+ // jnz
164+ if ( registers [ 0 ] != 0 )
165+ {
166+ int delta = arg - ip ;
167+ inc = delta ;
168+ }
169+
170+ break ;
171+ case 4 :
172+ // bxc
173+ registers [ 1 ] ^= registers [ 2 ] ;
174+ break ;
175+ case 5 :
176+ // out
177+ string output = $ "{ ComboReg ( arg , registers ) & 7 } ,";
178+
179+ if ( builder is notnull )
180+ {
181+ builder . Append ( output ) ;
182+ }
183+ else
184+ {
185+ Console . Write ( output ) ;
186+ }
187+
188+ break ;
189+ case 6 :
190+ // bdv
191+ registers [ 1 ] = registers [ 0 ] / ( int ) double . Pow ( 2 , ComboReg ( arg , registers ) ) ;
192+ break ;
193+ case 7 :
194+ registers [ 2 ] = registers [ 0 ] / ( int ) double . Pow ( 2 , ComboReg ( arg , registers ) ) ;
195+ break ;
196+ default :
197+ throw new InvalidDataException ( ) ;
198+ }
199+
200+ return inc ;
201+
202+ static long ComboReg ( int arg , long [ ] registers )
203+ {
204+ return arg switch
205+ {
206+ < 4 => arg ,
207+ < 6 => registers [ arg - 4 ] ,
208+ } ;
209+ }
210+ }
211+ }
212+ }