@@ -26,37 +26,39 @@ fn to_idx(i: u8) -> usize {
2626 }
2727}
2828
29+ const HAS_START : u16 = 1 << 15 ;
2930#[ derive( Debug , Copy , Clone ) ]
30- enum NfaTrans {
31- None ,
32- Start ,
33- Next ( usize ) ,
34- Both ( usize ) ,
35- }
31+ struct NfaTrans ( u16 ) ;
3632
3733impl NfaTrans {
34+ #[ inline( always) ]
35+ const fn empty ( ) -> Self {
36+ NfaTrans ( 0 )
37+ }
38+
39+ #[ inline( always) ]
40+ fn has_start ( & self ) -> bool {
41+ self . 0 & HAS_START != 0
42+ }
43+
44+ #[ inline( always) ]
45+ fn get_next ( & self ) -> u16 {
46+ self . 0 & ( !HAS_START )
47+ }
48+
49+ #[ inline( always) ]
3850 fn add_start ( & mut self ) {
39- match * self {
40- NfaTrans :: None => * self = NfaTrans :: Start ,
41- NfaTrans :: Next ( n) => * self = NfaTrans :: Both ( n) ,
42- _ => { }
43- }
51+ self . 0 |= HAS_START ;
4452 }
4553
46- fn add_or_foolow ( & mut self , new_nfa_node : impl FnOnce ( ) -> usize ) -> usize {
47- match * self {
48- NfaTrans :: None => {
49- let new = new_nfa_node ( ) ;
50- * self = NfaTrans :: Next ( new) ;
51- new
52- }
53- NfaTrans :: Start => {
54- let new = new_nfa_node ( ) ;
55- * self = NfaTrans :: Both ( new) ;
56- new
57- }
58- NfaTrans :: Next ( n) => n,
59- NfaTrans :: Both ( n) => n,
54+ #[ inline( always) ]
55+ fn add_or_foolow ( & mut self , new_nfa_node : impl FnOnce ( ) -> u16 ) -> u16 {
56+ if self . get_next ( ) == 0 {
57+ let new = new_nfa_node ( ) ;
58+ self . 0 |= new;
59+ new
60+ } else {
61+ self . get_next ( )
6062 }
6163 }
6264}
@@ -74,7 +76,7 @@ pub fn part1(s: &str) -> u64 {
7476// #[target_feature(enable = "avx2,bmi1,bmi2,cmpxchg16b,lzcnt,movbe,popcnt")]
7577fn inner_part1 ( s : & [ u8 ] ) -> u64 {
7678 let mut nfa = heapless:: Vec :: < [ NfaTrans ; 5 ] , NFA_SIZE > :: new ( ) ;
77- nfa. push ( [ NfaTrans :: None ; 5 ] ) . unwrap ( ) ;
79+ nfa. push ( [ NfaTrans :: empty ( ) ; 5 ] ) . unwrap ( ) ;
7880
7981 let mut i = 0 ;
8082 let mut nfa_node = 0 ;
@@ -93,21 +95,21 @@ fn inner_part1(s: &[u8]) -> u64 {
9395 } else {
9496 let mut nfa_trans = nfa[ nfa_node] [ color] ;
9597 let next_nfa_node = nfa_trans. add_or_foolow ( || {
96- let new_nfa_node = nfa. len ( ) ;
97- nfa. push ( [ NfaTrans :: None ; 5 ] ) . unwrap ( ) ;
98+ let new_nfa_node = nfa. len ( ) as u16 ;
99+ nfa. push ( [ NfaTrans :: empty ( ) ; 5 ] ) . unwrap ( ) ;
98100 new_nfa_node
99101 } ) ;
100102 nfa[ nfa_node] [ color] = nfa_trans;
101103
102- nfa_node = next_nfa_node;
104+ nfa_node = next_nfa_node as usize ;
103105 i += 1 ;
104106 }
105107 }
106108
107109 let mut sum = 0 ;
108110
109- let mut states1 = & mut ( true , heapless:: Vec :: < usize , NFA_SIZE > :: new ( ) ) ;
110- let mut states2 = & mut ( false , heapless:: Vec :: < usize , NFA_SIZE > :: new ( ) ) ;
111+ let mut states1 = & mut ( true , heapless:: Vec :: < u16 , NFA_SIZE > :: new ( ) ) ;
112+ let mut states2 = & mut ( false , heapless:: Vec :: < u16 , NFA_SIZE > :: new ( ) ) ;
111113
112114 while i < s. len ( ) {
113115 if s[ i] == b'\n' {
@@ -126,34 +128,18 @@ fn inner_part1(s: &[u8]) -> u64 {
126128
127129 if states1. 0 {
128130 let next = nfa[ 0 ] [ color] ;
129- match next {
130- NfaTrans :: None => { }
131- NfaTrans :: Start => {
132- states2. 0 = true ;
133- }
134- NfaTrans :: Next ( n) => {
135- states2. 1 . push ( n) . unwrap ( ) ;
136- }
137- NfaTrans :: Both ( n) => {
138- states2. 0 = true ;
139- states2. 1 . push ( n) . unwrap ( ) ;
140- }
131+
132+ states2. 0 |= next. has_start ( ) ;
133+ if next. get_next ( ) != 0 {
134+ states2. 1 . push ( next. get_next ( ) ) . unwrap ( ) ;
141135 }
142136 }
143137 for s in states1. 1 . iter ( ) {
144- let next = nfa[ * s] [ color] ;
145- match next {
146- NfaTrans :: None => { }
147- NfaTrans :: Start => {
148- states2. 0 = true ;
149- }
150- NfaTrans :: Next ( n) => {
151- states2. 1 . push ( n) . unwrap ( ) ;
152- }
153- NfaTrans :: Both ( n) => {
154- states2. 0 = true ;
155- states2. 1 . push ( n) . unwrap ( ) ;
156- }
138+ let next = nfa[ * s as usize ] [ color] ;
139+
140+ states2. 0 |= next. has_start ( ) ;
141+ if next. get_next ( ) != 0 {
142+ states2. 1 . push ( next. get_next ( ) ) . unwrap ( ) ;
157143 }
158144 }
159145 std:: mem:: swap ( & mut states2, & mut states1) ;
@@ -180,7 +166,7 @@ pub fn part2(s: &str) -> u64 {
180166// #[target_feature(enable = "avx2,bmi1,bmi2,cmpxchg16b,lzcnt,movbe,popcnt")]
181167fn inner_part2 ( s : & [ u8 ] ) -> u64 {
182168 let mut nfa = heapless:: Vec :: < [ NfaTrans ; 5 ] , NFA_SIZE > :: new ( ) ;
183- nfa. push ( [ NfaTrans :: None ; 5 ] ) . unwrap ( ) ;
169+ nfa. push ( [ NfaTrans :: empty ( ) ; 5 ] ) . unwrap ( ) ;
184170
185171 let mut i = 0 ;
186172 let mut nfa_node = 0 ;
@@ -199,25 +185,26 @@ fn inner_part2(s: &[u8]) -> u64 {
199185 } else {
200186 let mut nfa_trans = nfa[ nfa_node] [ color] ;
201187 let next_nfa_node = nfa_trans. add_or_foolow ( || {
202- let new_nfa_node = nfa. len ( ) ;
203- nfa. push ( [ NfaTrans :: None ; 5 ] ) . unwrap ( ) ;
188+ let new_nfa_node = nfa. len ( ) as u16 ;
189+ nfa. push ( [ NfaTrans :: empty ( ) ; 5 ] ) . unwrap ( ) ;
204190 new_nfa_node
205191 } ) ;
206192 nfa[ nfa_node] [ color] = nfa_trans;
207193
208- nfa_node = next_nfa_node;
194+ nfa_node = next_nfa_node as usize ;
209195 i += 1 ;
210196 }
211197 }
212198
213199 let mut sum = 0 ;
214200
215- let mut states1 = & mut ( 1 , heapless:: Vec :: < ( usize , u64 ) , NFA_SIZE > :: new ( ) ) ;
216- let mut states2 = & mut ( 0 , heapless:: Vec :: < ( usize , u64 ) , NFA_SIZE > :: new ( ) ) ;
201+ let mut states1 = & mut ( 1u64 , heapless:: Vec :: < ( u16 , u64 ) , NFA_SIZE > :: new ( ) ) ;
202+ let mut states2 = & mut ( 0u64 , heapless:: Vec :: < ( u16 , u64 ) , NFA_SIZE > :: new ( ) ) ;
217203
218204 while i < s. len ( ) {
219205 if s[ i] == b'\n' {
220206 sum += states1. 0 ;
207+
221208 states1. 1 . clear ( ) ;
222209 states1. 0 = 1 ;
223210 i += 1 ;
@@ -230,38 +217,26 @@ fn inner_part2(s: &[u8]) -> u64 {
230217
231218 if states1. 0 > 0 {
232219 let next = nfa[ 0 ] [ color] ;
233- match next {
234- NfaTrans :: None => { }
235- NfaTrans :: Start => {
236- states2. 0 += states1. 0 ;
237- }
238- NfaTrans :: Next ( n) => {
239- states2. 1 . push ( ( n, states1. 0 ) ) . unwrap ( ) ;
240- }
241- NfaTrans :: Both ( n) => {
242- states2. 0 += states1. 0 ;
243- states2. 1 . push ( ( n, states1. 0 ) ) . unwrap ( ) ;
244- }
220+
221+ if next. has_start ( ) {
222+ states2. 0 += states1. 0 ;
223+ }
224+ if next. get_next ( ) != 0 {
225+ states2. 1 . push ( ( next. get_next ( ) , states1. 0 ) ) . unwrap ( ) ;
245226 }
246227 }
247228 for ( s, amount) in states1. 1 . iter ( ) {
248- let next = nfa[ * s] [ color] ;
249- match next {
250- NfaTrans :: None => { }
251- NfaTrans :: Start => {
252- states2. 0 += * amount;
253- }
254- NfaTrans :: Next ( n) => {
255- states2. 1 . push ( ( n, * amount) ) . unwrap ( ) ;
256- }
257- NfaTrans :: Both ( n) => {
258- states2. 0 += * amount;
259- states2. 1 . push ( ( n, * amount) ) . unwrap ( ) ;
260- }
229+ let next = nfa[ * s as usize ] [ color] ;
230+
231+ if next. has_start ( ) {
232+ states2. 0 += amount;
233+ }
234+ if next. get_next ( ) != 0 {
235+ states2. 1 . push ( ( next. get_next ( ) , * amount) ) . unwrap ( ) ;
261236 }
262237 }
263-
264238 std:: mem:: swap ( & mut states2, & mut states1) ;
239+
265240 if states1. 0 == 0 && states1. 1 . is_empty ( ) {
266241 while i < s. len ( ) && s[ i] != b'\n' {
267242 i += 1 ;
0 commit comments