@@ -4,102 +4,98 @@ namespace AdventOfCode.Y2024.Day24;
4
4
using System . Collections . Generic ;
5
5
using System . Linq ;
6
6
using System . Text . RegularExpressions ;
7
+ using Circuit = System . Collections . Generic . Dictionary < string , Gate > ;
7
8
8
- record struct Rule ( string in1 , string in2 , string kind , string output ) ;
9
+ record struct Gate ( string in1 , string kind , string in2 ) ;
9
10
10
11
[ ProblemName ( "Crossed Wires" ) ]
11
12
class Solution : Solver {
12
13
13
14
public object PartOne ( string input ) {
14
- var gate = Parse ( input ) ;
15
- var bits = gate . Keys . Where ( k => k . StartsWith ( "z" ) ) . OrderByDescending ( x => x ) . ToArray ( ) ;
15
+ var ( inputs , circuit ) = Parse ( input ) ;
16
+
17
+ var outputs = from label in circuit . Keys where label . StartsWith ( "z" ) select label ;
18
+
16
19
var res = 0L ;
17
- foreach ( var b in bits ) {
18
- res = res * 2 + gate [ b ] ( ) ;
20
+ foreach ( var label in outputs . OrderByDescending ( label => label ) ) {
21
+ res = res * 2 + Evaluate ( label , circuit , inputs ) ;
19
22
}
20
23
return res ;
21
24
}
22
25
26
+ int Evaluate ( string label , Circuit circuit , Dictionary < string , int > inputs ) {
27
+ if ( inputs . TryGetValue ( label , out var res ) ) {
28
+ return res ;
29
+ } else {
30
+ return circuit [ label ] switch {
31
+ Gate ( var in1 , "AND" , var in2 ) => Evaluate ( in1 , circuit , inputs ) & Evaluate ( in2 , circuit , inputs ) ,
32
+ Gate ( var in1 , "OR" , var in2 ) => Evaluate ( in1 , circuit , inputs ) | Evaluate ( in2 , circuit , inputs ) ,
33
+ Gate ( var in1 , "XOR" , var in2 ) => Evaluate ( in1 , circuit , inputs ) ^ Evaluate ( in2 , circuit , inputs ) ,
34
+ _ => throw new Exception ( circuit [ label ] . ToString ( ) ) ,
35
+ } ;
36
+ }
37
+ }
38
+
23
39
public object PartTwo ( string input ) {
24
- var swaps = Fix ( ParseRules ( input . Split ( " \n \n " ) [ 1 ] ) ) ;
25
- return string . Join ( "," , swaps . OrderBy ( x => x ) ) ;
40
+ var circuit = Parse ( input ) . circuit ;
41
+ return string . Join ( "," , Fix ( circuit ) . OrderBy ( label => label ) ) ;
26
42
}
27
43
28
- // the rules should define a full adder for two 44 bit numbers
44
+ // the circuit should define a full adder for two 44 bit numbers
29
45
// this fixer is specific to my input.
30
- IEnumerable < string > Fix ( List < Rule > rules ) {
31
- var cin = Output ( rules , "x00" , "AND" , "y00" ) ;
46
+ IEnumerable < string > Fix ( Circuit circuit ) {
47
+ var cin = Output ( circuit , "x00" , "AND" , "y00" ) ;
32
48
for ( var i = 1 ; i < 45 ; i ++ ) {
33
49
var x = $ "x{ i : D2} ";
34
50
var y = $ "y{ i : D2} ";
35
51
var z = $ "z{ i : D2} ";
36
52
37
- var xor1 = Output ( rules , x , "XOR" , y ) ;
38
- var and1 = Output ( rules , x , "AND" , y ) ;
39
-
40
- var and2 = Output ( rules , cin , "AND" , xor1 ) ;
41
- var xor2 = Output ( rules , cin , "XOR" , xor1 ) ;
53
+ var xor1 = Output ( circuit , x , "XOR" , y ) ;
54
+ var and1 = Output ( circuit , x , "AND" , y ) ;
55
+ var xor2 = Output ( circuit , cin , "XOR" , xor1 ) ;
56
+ var and2 = Output ( circuit , cin , "AND" , xor1 ) ;
42
57
43
58
if ( xor2 == null && and2 == null ) {
44
- return Swap ( rules , xor1 , and1 ) ;
59
+ return SwapAndFix ( circuit , xor1 , and1 ) ;
45
60
}
46
61
47
- var carry = Output ( rules , and1 , "OR" , and2 ) ;
62
+ var carry = Output ( circuit , and1 , "OR" , and2 ) ;
48
63
if ( xor2 != z ) {
49
- return Swap ( rules , z , xor2 ) ;
64
+ return SwapAndFix ( circuit , z , xor2 ) ;
50
65
} else {
51
66
cin = carry ;
52
67
}
53
68
}
54
69
return [ ] ;
55
70
}
56
71
57
- string Output ( IEnumerable < Rule > rules , string x , string gate , string y ) =>
58
- rules . SingleOrDefault ( rule =>
59
- ( rule . in1 == x && rule . kind == gate && rule . in2 == y ) ||
60
- ( rule . in1 == y && rule . kind == gate && rule . in2 == x )
61
- ) . output ;
62
-
63
- IEnumerable < string > Swap ( List < Rule > rules , string out1 , string out2 ) {
64
- rules = rules . Select ( rule =>
65
- rule . output == out1 ? rule with { output = out2 } :
66
- rule . output == out2 ? rule with { output = out1 } :
67
- rule
68
- ) . ToList ( ) ;
69
-
70
- return Fix ( rules ) . Concat ( [ out1 , out2 ] ) ;
72
+ IEnumerable < string > SwapAndFix ( Circuit circuit , string out1 , string out2 ) {
73
+ ( circuit [ out1 ] , circuit [ out2 ] ) = ( circuit [ out2 ] , circuit [ out1 ] ) ;
74
+ return Fix ( circuit ) . Concat ( [ out1 , out2 ] ) ;
71
75
}
72
76
73
- List < Rule > ParseRules ( string input ) => input
74
- . Split ( "\n " )
75
- . Select ( line => {
76
- var parts = line . Split ( " " ) ;
77
- return new Rule ( in1 : parts [ 0 ] , in2 : parts [ 2 ] , kind : parts [ 1 ] , output : parts [ 4 ] ) ;
78
- } )
79
- . ToList ( ) ;
80
- Dictionary < string , Gate > Parse ( string input ) {
77
+ string Output ( Circuit circuit , string x , string kind , string y ) =>
78
+ circuit . SingleOrDefault ( pair =>
79
+ ( pair . Value . in1 == x && pair . Value . kind == kind && pair . Value . in2 == y ) ||
80
+ ( pair . Value . in1 == y && pair . Value . kind == kind && pair . Value . in2 == x )
81
+ ) . Key ;
81
82
82
- var res = new Dictionary < string , Gate > ( ) ;
83
+ ( Dictionary < string , int > inputs , Circuit circuit ) Parse ( string input ) {
84
+ var inputs = new Dictionary < string , int > ( ) ;
85
+ var circuit = new Circuit ( ) ;
83
86
84
87
var blocks = input . Split ( "\n \n " ) ;
85
88
86
89
foreach ( var line in blocks [ 0 ] . Split ( "\n " ) ) {
87
90
var parts = line . Split ( ": " ) ;
88
- res . Add ( parts [ 0 ] , ( ) => int . Parse ( parts [ 1 ] ) ) ;
91
+ inputs . Add ( parts [ 0 ] , int . Parse ( parts [ 1 ] ) ) ;
89
92
}
90
93
91
94
foreach ( var line in blocks [ 1 ] . Split ( "\n " ) ) {
92
95
var parts = Regex . Matches ( line , "[a-zA-z0-9]+" ) . Select ( m => m . Value ) . ToArray ( ) ;
93
- Gate gate = ( parts [ 0 ] , parts [ 1 ] , parts [ 2 ] ) switch {
94
- ( var in1 , "AND" , var in2 ) => ( ) => res [ in1 ] ( ) & res [ in2 ] ( ) ,
95
- ( var in1 , "OR" , var in2 ) => ( ) => res [ in1 ] ( ) | res [ in2 ] ( ) ,
96
- ( var in1 , "XOR" , var in2 ) => ( ) => res [ in1 ] ( ) ^ res [ in2 ] ( ) ,
97
- _ => throw new Exception ( ) ,
98
- } ;
99
- res . Add ( parts [ 3 ] , gate ) ;
96
+ circuit . Add ( parts [ 3 ] , new Gate ( in1 : parts [ 0 ] , kind : parts [ 1 ] , in2 : parts [ 2 ] ) ) ;
100
97
}
101
- return res ;
98
+ return ( inputs , circuit ) ;
102
99
}
103
100
104
- delegate int Gate ( ) ;
105
101
}
0 commit comments