1212//!
1313//! Computing the result is simply multiplying the number of each element by its length. There are
1414//! 92 elements total so we can use a fixed size array to store the decay chain information.
15+ //!
16+ //! It would be possible (but less fun) to precompute all possible 92 answers into a
17+ //! look up table.
1518use crate :: util:: hash:: * ;
1619
1720const ELEMENTS : & str = "\
@@ -113,34 +116,34 @@ type Result = (usize, usize);
113116pub fn parse ( input : & str ) -> Result {
114117 let elements: Vec < Vec < _ > > =
115118 ELEMENTS . lines ( ) . map ( |line| line. split_ascii_whitespace ( ) . collect ( ) ) . collect ( ) ;
116- let mut indices = FastMap :: with_capacity ( 92 ) ;
119+ let mut indices = FastMap :: with_capacity ( 92 * 2 ) ;
117120
121+ // Map both sequence and element name to indices.
118122 for ( i, tokens) in elements. iter ( ) . enumerate ( ) {
123+ indices. insert ( tokens[ 0 ] , i) ;
119124 indices. insert ( tokens[ 2 ] , i) ;
120125 }
121126
122- let mut sequence = [ "" ; 92 ] ;
123- let mut decays = [ [ None ; 6 ] ; 92 ] ;
127+ // Build list of decay chains.
128+ let sizes: Vec < _ > = elements. iter ( ) . map ( |e| e[ 0 ] . len ( ) ) . collect ( ) ;
129+ let decays: Vec < Vec < _ > > =
130+ elements. iter ( ) . map ( |e| e[ 4 ..] . iter ( ) . map ( |t| indices[ t] ) . collect ( ) ) . collect ( ) ;
124131
125- for ( i, tokens) in elements. iter ( ) . enumerate ( ) {
126- sequence[ i] = tokens[ 0 ] ;
127- for ( j, & token) in tokens. iter ( ) . skip ( 4 ) . enumerate ( ) {
128- decays[ i] [ j] = Some ( indices[ token] ) ;
129- }
130- }
132+ // Each input is a single element.
133+ let mut current = [ 0 ; 92 ] ;
134+ current[ indices[ input. trim ( ) ] ] = 1 ;
131135
132- let mut current = initial_state ( input, & sequence) ;
133136 for _ in 0 ..40 {
134137 current = step ( & current, & decays) ;
135138 }
139+ let part1 = length ( & current, & sizes) ;
136140
137- let result1 = length ( & current, & sequence) ;
138141 for _ in 0 ..10 {
139142 current = step ( & current, & decays) ;
140143 }
144+ let part2 = length ( & current, & sizes) ;
141145
142- let result2 = length ( & current, & sequence) ;
143- ( result1, result2)
146+ ( part1, part2)
144147}
145148
146149pub fn part1 ( input : & Result ) -> usize {
@@ -151,31 +154,20 @@ pub fn part2(input: &Result) -> usize {
151154 input. 1
152155}
153156
154- fn initial_state ( input : & str , sequence : & [ & str ] ) -> [ usize ; 92 ] {
155- let input = input. trim ( ) ;
156- let start = sequence. iter ( ) . position ( |& s| s == input) . unwrap ( ) ;
157-
158- let mut current = [ 0 ; 92 ] ;
159- current[ start] += 1 ;
160- current
161- }
162-
163- fn step ( current : & [ usize ; 92 ] , decays : & [ [ Option < usize > ; 6 ] ; 92 ] ) -> [ usize ; 92 ] {
157+ fn step ( current : & [ usize ] , decays : & [ Vec < usize > ] ) -> [ usize ; 92 ] {
164158 let mut next = [ 0 ; 92 ] ;
165159
166- for i in 0 ..92 {
167- let c = current[ i] ;
168- if c > 0 {
169- let mut iter = decays[ i] . iter ( ) ;
170- while let Some ( Some ( index) ) = iter. next ( ) {
171- next[ * index] += c;
160+ for ( i, & count) in current. iter ( ) . enumerate ( ) {
161+ if count > 0 {
162+ for & element in & decays[ i] {
163+ next[ element] += count;
172164 }
173165 }
174166 }
175167
176168 next
177169}
178170
179- fn length ( current : & [ usize ; 92 ] , sequence : & [ & str ; 92 ] ) -> usize {
180- current. iter ( ) . zip ( sequence . iter ( ) ) . map ( |( c, s) | c * s. len ( ) ) . sum ( )
171+ fn length ( current : & [ usize ] , sizes : & [ usize ] ) -> usize {
172+ current. iter ( ) . zip ( sizes . iter ( ) ) . map ( |( c, s) | c * s) . sum ( )
181173}
0 commit comments