2
2
use crate :: util:: hash:: * ;
3
3
use crate :: util:: iter:: * ;
4
4
use crate :: util:: parse:: * ;
5
+ use std:: collections:: VecDeque ;
5
6
6
7
type Input < ' a > = ( & ' a str , Vec < [ & ' a str ; 5 ] > ) ;
7
8
@@ -14,39 +15,41 @@ pub fn parse(input: &str) -> Input<'_> {
14
15
pub fn part1 ( input : & Input < ' _ > ) -> u64 {
15
16
let ( prefix, gates) = input;
16
17
17
- let mut names = FastMap :: new ( ) ;
18
- let mut cache = FastMap :: new ( ) ;
19
- let mut ops = FastMap :: new ( ) ;
18
+ let mut cache = vec ! [ u8 :: MAX ; 1 << 15 ] ;
19
+ let to_index = |s : & str | {
20
+ let b = s. as_bytes ( ) ;
21
+ ( ( b[ 0 ] as usize & 31 ) << 10 ) + ( ( b[ 1 ] as usize & 31 ) << 5 ) + ( b[ 2 ] as usize & 31 )
22
+ } ;
20
23
21
24
for line in prefix. lines ( ) {
22
25
let prefix = & line[ ..3 ] ;
23
26
let suffix = & line[ 5 ..] ;
24
-
25
- let size = names. len ( ) ;
26
- let index = * names. entry ( prefix) . or_insert ( size) ;
27
-
28
- cache. insert ( index, suffix. unsigned ( ) ) ;
27
+ cache[ to_index ( prefix) ] = suffix. unsigned ( ) ;
29
28
}
30
29
31
- for & [ left, kind, right, _, to] in gates {
32
- let size = names. len ( ) ;
33
- let left = * names. entry ( left) . or_insert ( size) ;
30
+ let mut todo: VecDeque < _ > = gates. iter ( ) . copied ( ) . collect ( ) ;
34
31
35
- let size = names. len ( ) ;
36
- let right = * names. entry ( right) . or_insert ( size) ;
32
+ while let Some ( gate @ [ left, kind, right, _, to] ) = todo. pop_front ( ) {
33
+ let left = cache[ to_index ( left) ] ;
34
+ let right = cache[ to_index ( right) ] ;
37
35
38
- let size = names. len ( ) ;
39
- let to = * names. entry ( to) . or_insert ( size) ;
40
-
41
- ops. insert ( to, ( left, kind, right) ) ;
36
+ if left == u8:: MAX || right == u8:: MAX {
37
+ todo. push_back ( gate) ;
38
+ } else {
39
+ cache[ to_index ( to) ] = match kind {
40
+ "AND" => left & right,
41
+ "OR" => left | right,
42
+ "XOR" => left ^ right,
43
+ _ => unreachable ! ( ) ,
44
+ }
45
+ }
42
46
}
43
47
44
48
let mut result = 0 ;
45
49
46
- for i in ( 0 ..64 ) . rev ( ) {
47
- let key = format ! ( "z{i:02}" ) ;
48
- if let Some ( & key) = names. get ( key. as_str ( ) ) {
49
- result = ( result << 1 ) | helper ( & mut cache, & mut ops, key) ;
50
+ for i in ( to_index ( "z00" ) ..to_index ( "z64" ) ) . rev ( ) {
51
+ if cache[ i] != u8:: MAX {
52
+ result = ( result << 1 ) | ( cache[ i] as u64 ) ;
50
53
}
51
54
}
52
55
@@ -102,27 +105,3 @@ pub fn part2(input: &Input<'_>) -> String {
102
105
result. sort_unstable ( ) ;
103
106
result. join ( "," )
104
107
}
105
-
106
- fn helper (
107
- cache : & mut FastMap < usize , u64 > ,
108
- ops : & mut FastMap < usize , ( usize , & str , usize ) > ,
109
- key : usize ,
110
- ) -> u64 {
111
- if let Some ( & value) = cache. get ( & key) {
112
- return value;
113
- }
114
-
115
- let ( left, op, right) = ops[ & key] ;
116
- let left = helper ( cache, ops, left) ;
117
- let right = helper ( cache, ops, right) ;
118
-
119
- let value = match op {
120
- "AND" => left & right,
121
- "OR" => left | right,
122
- "XOR" => left ^ right,
123
- _ => unreachable ! ( ) ,
124
- } ;
125
-
126
- cache. insert ( key, value) ;
127
- value
128
- }
0 commit comments