@@ -2,135 +2,129 @@ namespace AdventOfCode.Y2024.Day21;
2
2
3
3
using System ;
4
4
using System . Collections . Generic ;
5
- using System . Collections . Immutable ;
6
5
using System . Linq ;
7
- using System . Text . RegularExpressions ;
8
- using System . Text ;
9
6
using System . Numerics ;
10
- using System . Security . AccessControl ;
11
7
using AngleSharp . Common ;
12
- using AdventOfCode . Y2021 . Day11 ;
13
- using System . Security . Cryptography ;
8
+ using Cache = System . Collections . Concurrent . ConcurrentDictionary < ( char , System . Numerics . Complex , int , System . Numerics . Complex ) , ( long , System . Numerics . Complex ) > ;
9
+
14
10
15
11
[ ProblemName ( "Keypad Conundrum" ) ]
16
12
class Solution : Solver {
17
13
18
14
public object PartOne ( string input ) {
19
- return input . Split ( "\n " ) . Sum ( Solve ) ;
15
+ return input . Split ( "\n " ) . Sum ( line => Solve2 ( line , 2 ) ) ;
20
16
}
21
-
22
17
public object PartTwo ( string input ) {
23
- return 0 ;
18
+ // 24: 156944425344350 low
19
+ // 25: 400827838993176 high
20
+ return input . Split ( "\n " ) . Sum ( line => Solve2 ( line , 24 ) ) ;
24
21
}
25
22
26
23
static readonly Complex Left = - 1 ;
27
24
static readonly Complex Right = 1 ;
28
25
static readonly Complex Up = Complex . ImaginaryOne ;
29
26
static readonly Complex Down = - Complex . ImaginaryOne ;
30
27
31
- int Solve ( string line ) {
28
+ long Solve2 ( string line , int depth ) {
32
29
var keypad1 = ParseKeypad ( "789\n 456\n 123\n 0A" ) ;
33
30
var keypad2 = ParseKeypad ( " ^A\n <v>" ) ;
34
31
35
- Console . WriteLine ( "========" ) ;
36
- // var q = "<v<A>>^AvA^A<vA<AA>>^AAvA<^A>AAvA^A<vA>^AA<A>A<v<A>A>^AAAvA<^A>A";
37
- // Console.WriteLine(q);
38
- // q = Decode(q, keypad2);
39
- // Console.WriteLine(q);
40
- // q = Decode(q, keypad2);
41
- // Console.WriteLine(q);
42
- // q = Decode(q, keypad1);
43
- // Console.WriteLine(q);
44
-
45
- // Console.WriteLine();
46
-
47
- var xs = Encode ( line , keypad1 , keypad1 [ 'A' ] ) . ToList ( ) ;
48
- var ys = xs . SelectMany ( x => Encode ( x , keypad2 , keypad2 [ 'A' ] ) ) . ToList ( ) ;
49
- foreach ( var y in ys ) {
50
- Console . WriteLine ( Decode ( Decode ( y , keypad2 ) , keypad1 ) ) ;
32
+ Cache cache = new Cache ( ) ;
33
+ var res = long . MaxValue ;
34
+ foreach ( var plan in Encode ( line , keypad1 , keypad1 [ 'A' ] ) ) {
35
+ var ( length , _) = EncodeString ( plan , keypad2 , depth , cache , keypad2 [ 'A' ] ) ;
36
+ res = Math . Min ( res , length ) ;
37
+ }
38
+ return res * int . Parse ( line . Substring ( 0 , line . Length - 1 ) ) ;
39
+ }
40
+
41
+ ( long , Complex ) EncodeString ( string st , Dictionary < char , Complex > keypad2 , int depth , Cache cache , Complex top ) {
42
+ if ( depth == 0 ) {
43
+ return ( st . Length , top ) ;
44
+ } else {
45
+ var length = 0L ;
46
+ var pos = depth == 1 ? top : keypad2 [ 'A' ] ;
47
+ var originalTop = top ;
48
+ foreach ( var step in st ) {
49
+ long cost ;
50
+ ( cost , top ) = EncodeKey ( step , pos , keypad2 , depth , cache , top ) ;
51
+ length += cost ;
52
+ pos = keypad2 [ step ] ;
53
+ }
54
+ if ( depth == 1 ) {
55
+ top = st . Length == 1 ? originalTop : keypad2 [ st [ ^ 1 ] ] ;
56
+ }
57
+ return ( length , top ) ;
58
+ }
59
+ }
60
+ ( long , Complex ) EncodeKey ( char ch , Complex pos , Dictionary < char , Complex > keypad2 , int depth , Cache cache , Complex top ) {
61
+ var key = ( ch , pos , depth , top ) ;
62
+ if ( cache . ContainsKey ( key ) ) {
63
+ return cache [ key ] ;
64
+ }
65
+
66
+ if ( depth == 0 ) {
67
+ throw new Exception ( ) ;
51
68
}
52
69
53
- var cache = new Dictionary < ( Complex , string ) , string > ( ) ;
54
70
55
- var z = ys . Select ( y => Mikkamakka ( keypad2 [ 'A' ] , y , keypad2 , cache ) ) . MinBy ( z => z . Length ) ;
71
+ var target = keypad2 [ ch ] ;
56
72
57
- Console . WriteLine ( Decode ( Decode ( Decode ( z , keypad2 ) , keypad2 ) , keypad1 ) ) ;
58
- return z . Length * int . Parse ( line [ 0 ..^ 1 ] ) ;
59
- }
73
+ var dy = ( int ) ( target . Imaginary - pos . Imaginary ) ;
74
+ var dx = ( int ) ( target . Real - pos . Real ) ;
60
75
61
-
76
+ var resCost = long . MaxValue ;
77
+ var resTop = Complex . Infinity ;
62
78
63
- string Mikkamakka ( Complex pos , string st , Dictionary < char , Complex > keypad , Dictionary < ( Complex , string ) , string > cache ) {
64
- if ( st == "" ) {
65
- return "" ;
66
- }
67
- var key = ( pos , st ) ;
68
- if ( ! cache . ContainsKey ( key ) ) {
69
-
70
- var target = keypad [ st [ 0 ] ] ;
71
-
72
- var dy = ( int ) ( target . Imaginary - pos . Imaginary ) ;
73
- var dx = ( int ) ( target . Real - pos . Real ) ;
74
-
75
- var res1 = "" ;
76
- if ( pos + dy * Up != keypad [ ' ' ] ) {
77
- if ( dy < 0 ) {
78
- res1 += new string ( 'v' , Math . Abs ( dy ) ) ;
79
- } else if ( dy > 0 ) {
80
- res1 += new string ( '^' , Math . Abs ( dy ) ) ;
81
- }
82
- if ( dx < 0 ) {
83
- res1 += new string ( '<' , Math . Abs ( dx ) ) ;
84
- } else if ( dx > 0 ) {
85
- res1 += new string ( '>' , Math . Abs ( dx ) ) ;
86
- }
87
- res1 += "A" ;
88
- res1 += Mikkamakka ( target , st [ 1 ..] , keypad , cache ) ;
79
+ var toEncode = "" ;
80
+ if ( pos + dy * Up != keypad2 [ ' ' ] ) {
81
+ if ( dy < 0 ) {
82
+ toEncode += new string ( 'v' , Math . Abs ( dy ) ) ;
83
+ } else if ( dy > 0 ) {
84
+ toEncode += new string ( '^' , Math . Abs ( dy ) ) ;
89
85
}
90
- var res2 = "" ;
91
- if ( pos + dx * Right != keypad [ ' ' ] ) {
92
- if ( dx < 0 ) {
93
- res2 += new string ( '<' , Math . Abs ( dx ) ) ;
94
- } else if ( dx > 0 ) {
95
- res2 += new string ( '>' , Math . Abs ( dx ) ) ;
96
- }
97
-
98
- if ( dy < 0 ) {
99
- res2 += new string ( 'v' , Math . Abs ( dy ) ) ;
100
- } else if ( dy > 0 ) {
101
- res2 += new string ( '^' , Math . Abs ( dy ) ) ;
102
- }
103
-
104
- res2 += "A" ;
105
- res2 += Mikkamakka ( target , st [ 1 ..] , keypad , cache ) ;
86
+ if ( dx < 0 ) {
87
+ toEncode += new string ( '<' , Math . Abs ( dx ) ) ;
88
+ } else if ( dx > 0 ) {
89
+ toEncode += new string ( '>' , Math . Abs ( dx ) ) ;
106
90
}
91
+ toEncode += "A" ;
92
+ var ( cost , topT ) = EncodeString ( toEncode , keypad2 , depth - 1 , cache , top ) ;
107
93
108
- cache [ key ] = res1 == "" ? res2 : res2 == "" ? res1 : res1 . Length < res2 . Length ? res1 : res2 ;
94
+ if ( cost < resCost ) {
95
+ resCost = cost ;
96
+ resTop = topT ;
97
+ }
109
98
}
110
- return cache [ key ] ;
111
- }
112
99
100
+ if ( pos + dx * Right != keypad2 [ ' ' ] ) {
101
+ if ( dx < 0 ) {
102
+ toEncode += new string ( '<' , Math . Abs ( dx ) ) ;
103
+ } else if ( dx > 0 ) {
104
+ toEncode += new string ( '>' , Math . Abs ( dx ) ) ;
105
+ }
113
106
114
- string Decode ( string st , Dictionary < char , Complex > keymap ) {
115
- var res = "" ;
116
- var pos = keymap [ 'A' ] ;
117
- foreach ( var ch in st ) {
118
- if ( ch == '^' ) {
119
- pos += Up ;
120
- } else if ( ch == 'v' ) {
121
- pos += Down ;
122
- } else if ( ch == '<' ) {
123
- pos += Left ;
124
- } else if ( ch == '>' ) {
125
- pos += Right ;
126
- } else if ( ch == 'A' ) {
127
- res += keymap . Single ( kvp => kvp . Value == pos ) . Key ;
107
+ if ( dy < 0 ) {
108
+ toEncode += new string ( 'v' , Math . Abs ( dy ) ) ;
109
+ } else if ( dy > 0 ) {
110
+ toEncode += new string ( '^' , Math . Abs ( dy ) ) ;
111
+ }
112
+ toEncode += "A" ;
113
+
114
+ var ( cost , topT ) = EncodeString ( toEncode , keypad2 , depth - 1 , cache , top ) ;
115
+
116
+ if ( cost < resCost ) {
117
+ resCost = cost ;
118
+ resTop = topT ;
128
119
}
129
120
}
130
- return res ;
121
+
122
+ cache [ key ] = ( resCost , resTop ) ;
123
+ return cache [ key ] ;
131
124
}
132
125
133
-
126
+
127
+
134
128
IEnumerable < string > Encode ( string st , Dictionary < char , Complex > keymap , Complex pos ) {
135
129
if ( st == "" ) {
136
130
yield return "" ;
0 commit comments