1
+ use std:: cell:: RefCell ;
1
2
use std:: time:: Instant ;
2
3
use std:: io:: { self , Read } ;
3
4
@@ -23,7 +24,7 @@ fn get_input() -> (Vec<(String, bool)>, Vec<(String, Operation, String, String)>
23
24
let gates = gates. lines ( ) . map ( |line| {
24
25
let ( input, output) = line. split_once ( " -> " ) . unwrap ( ) ;
25
26
26
- let input = input. split ( " " ) . collect :: < Vec < & str > > ( ) ;
27
+ let input = input. split ( ' ' ) . collect :: < Vec < & str > > ( ) ;
27
28
assert_eq ! ( input. len( ) , 3 ) ;
28
29
29
30
let a = input[ 0 ] . to_string ( ) ;
@@ -44,7 +45,7 @@ fn get_input() -> (Vec<(String, bool)>, Vec<(String, Operation, String, String)>
44
45
#[ derive( Debug ) ]
45
46
struct Node < ' a > {
46
47
name : & ' a String ,
47
- id : usize ,
48
+ value : RefCell < Option < bool > > ,
48
49
depends_on : Option < usize >
49
50
}
50
51
@@ -57,9 +58,9 @@ struct Gate {
57
58
}
58
59
59
60
impl Gate {
60
- pub fn get_output ( & self , nodes : & [ Node ] , gates : & [ Gate ] , values : & mut [ Option < bool > ] ) -> bool {
61
- let a = nodes[ self . a ] . get_output ( nodes, gates, values ) ;
62
- let b = nodes[ self . b ] . get_output ( nodes, gates, values ) ;
61
+ pub fn get_output ( & self , nodes : & [ Node ] , gates : & [ Gate ] ) -> bool {
62
+ let a = nodes[ self . a ] . get_output ( nodes, gates) ;
63
+ let b = nodes[ self . b ] . get_output ( nodes, gates) ;
63
64
64
65
return match self . op {
65
66
Operation :: And => a & b,
@@ -69,28 +70,26 @@ impl Gate {
69
70
}
70
71
}
71
72
72
- impl < ' a > Node < ' a > {
73
- pub fn get_output ( & self , nodes : & [ Node ] , gates : & [ Gate ] , values : & mut [ Option < bool > ] ) -> bool {
74
- if let Some ( value) = values [ self . id ] {
73
+ impl Node < ' _ > {
74
+ pub fn get_output ( & self , nodes : & [ Node ] , gates : & [ Gate ] ) -> bool {
75
+ if let Some ( value) = * self . value . borrow ( ) {
75
76
return value;
76
77
}
77
78
78
79
if let Some ( depends_on) = self . depends_on {
79
80
let gate = & gates[ depends_on] ;
80
- values [ self . id ] = Some ( gate. get_output ( nodes, gates, values ) ) ;
81
- return values [ self . id ] . unwrap ( ) ;
81
+ * self . value . borrow_mut ( ) = Some ( gate. get_output ( nodes, gates) ) ;
82
+ return self . value . borrow ( ) . unwrap ( ) ;
82
83
}
83
84
84
- println ! ( "{:?}" , self ) ;
85
- println ! ( "{:?}" , values[ self . id] ) ;
86
85
panic ! ( "Unknowable node" ) ;
87
86
}
88
87
}
89
88
90
89
fn char2ind ( c : u8 ) -> usize {
91
- if c >= b'0' && c <= b'9' {
90
+ if c. is_ascii_digit ( ) {
92
91
return ( c - b'0' ) as usize ;
93
- } else if c >= b'a' && c <= b'z' {
92
+ } else if c. is_ascii_lowercase ( ) {
94
93
return ( c - b'a' + 10 ) as usize ;
95
94
}
96
95
@@ -102,17 +101,17 @@ fn hash(s: &str) -> usize {
102
101
return char2ind ( bytes[ 0 ] ) * 36 * 36 + char2ind ( bytes[ 1 ] ) * 36 + char2ind ( bytes[ 2 ] ) ;
103
102
}
104
103
105
- fn str2id ( s : & str , table : & mut [ Option < usize > ; 36 * 36 * 36 ] , table_ind : & mut usize ) -> ( usize , bool ) {
104
+ fn maybe_insert_new_string ( s : & str , table : & mut [ Option < usize > ; 36 * 36 * 36 ] , table_ind : & mut usize ) -> bool {
106
105
let h = hash ( s) ;
107
- if let Some ( id ) = table[ h] {
108
- return ( id , false ) ;
106
+ if table[ h] . is_some ( ) {
107
+ return false ;
109
108
}
110
109
table[ h] = Some ( * table_ind) ;
111
110
* table_ind += 1 ;
112
- return ( * table_ind - 1 , true ) ;
111
+ return true ;
113
112
}
114
113
115
- fn str2id_get ( s : & str , table : & [ Option < usize > ; 36 * 36 * 36 ] ) -> usize {
114
+ fn str2id ( s : & str , table : & [ Option < usize > ; 36 * 36 * 36 ] ) -> usize {
116
115
let h = hash ( s) ;
117
116
return table[ h] . unwrap ( ) ;
118
117
}
@@ -121,37 +120,33 @@ fn part1(inputs: &[(String, bool)], gates: &[(String, Operation, String, String)
121
120
let mut name_table = [ None ; 36 * 36 * 36 ] ;
122
121
let mut table_ind = 0 ;
123
122
124
- let ( mut nodes, mut values) : ( Vec < Node > , Vec < Option < bool > > ) = inputs. iter ( ) . map ( |( name, value) |
125
- (
126
- Node {
127
- name,
128
- id : str2id ( name, & mut name_table, & mut table_ind) . 0 ,
129
- depends_on : None
130
- } ,
131
- Some ( * value)
132
- )
133
- ) . unzip ( ) ;
123
+ let mut nodes = inputs. iter ( ) . map ( |( name, value) | {
124
+ assert ! ( maybe_insert_new_string( name, & mut name_table, & mut table_ind) ) ;
125
+ return Node {
126
+ name,
127
+ value : RefCell :: new ( Some ( * value) ) ,
128
+ depends_on : None
129
+ } ;
130
+ } ) . collect :: < Vec < Node > > ( ) ;
134
131
135
132
for ( a, _, b, out) in gates {
136
- for x in [ a, b, out] . iter ( ) {
137
- let ( id, new) = str2id ( x, & mut name_table, & mut table_ind) ;
138
- if new {
133
+ for x in & [ a, b, out] {
134
+ if maybe_insert_new_string ( x, & mut name_table, & mut table_ind) {
139
135
nodes. push ( Node {
140
136
name : x,
141
- id ,
137
+ value : RefCell :: new ( None ) ,
142
138
depends_on : None
143
139
} ) ;
144
- values. push ( None ) ;
145
140
}
146
141
}
147
142
}
148
143
149
144
let gates = gates. iter ( ) . map ( |( a, op, b, out) |
150
145
Gate {
151
- a : str2id_get ( a, & name_table) ,
152
- b : str2id_get ( b, & name_table) ,
146
+ a : str2id ( a, & name_table) ,
147
+ b : str2id ( b, & name_table) ,
153
148
op : * op,
154
- out : str2id_get ( out, & name_table)
149
+ out : str2id ( out, & name_table)
155
150
}
156
151
) . collect :: < Vec < Gate > > ( ) ;
157
152
@@ -161,12 +156,12 @@ fn part1(inputs: &[(String, bool)], gates: &[(String, Operation, String, String)
161
156
162
157
163
158
let mut result = nodes. iter ( )
164
- . filter ( |node| node. name . starts_with ( "z" ) )
159
+ . filter ( |node| node. name . starts_with ( 'z' ) )
165
160
. map ( |node| {
166
- ( node. name , node. get_output ( & nodes, & gates, & mut values ) )
161
+ ( node. name , node. get_output ( & nodes, & gates) )
167
162
} ) . collect :: < Vec < ( & String , bool ) > > ( ) ;
168
163
169
- result. sort_by ( |a, b| b. 0 . cmp ( a. 0 ) ) ;
164
+ result. sort_unstable_by ( |a, b| b. 0 . cmp ( a. 0 ) ) ;
170
165
171
166
return result. iter ( ) . fold ( 0 , |acc, ( _, value) | {
172
167
acc << 1 | ( * value as u64 )
@@ -185,7 +180,7 @@ fn part2(_inputs: &[(String, bool)], _gates: &[(String, Operation, String, Strin
185
180
. flat_map ( |( a, b) | vec ! [ * a, * b] )
186
181
. collect :: < Vec < & str > > ( ) ;
187
182
188
- result. sort ( ) ;
183
+ result. sort_unstable ( ) ;
189
184
190
185
return result. join ( "," ) ;
191
186
}
0 commit comments