fn polymer_counts(polymer: &String, rules: &HashMap<u16, u8>, steps: usize, verbose: bool)
    -> (usize, usize)
{
    let span = usize::from(1 + b'Z' - b'A');
    /* With a vector instead of a hash map, we need to iterate through all possible pairs
     * each iteration, not just the ones which are nonzero. Let's check later which is faster.
    let mut pairs: Vec<usize> = std::iter::repeat(0).take(span).collect();
    fn ipair(p: u16) -> usize {
        let (a, b) = pairsplit(p);
        a * span + b
    }
    */
    let mut pairs: HashMap<u16, usize> = HashMap::with_capacity(span * span);
    let mut chars: Vec<usize> = std::iter::repeat(0).take(span).collect();
    #[inline]
    fn ichar(b: u8) -> usize { usize::from(b - b'A') }
    for pair in polymer.as_bytes().windows(2) {
        chars[ichar(pair[0])] += 1;
        chars[ichar(pair[1])] += 1;
        *pairs.entry(polypair(pair[0], pair[1])).or_insert(0) += 1;
    }
    // The last character is not covered by windows(2).
    if let Some(b) = polymer.as_bytes().last() {
        chars[ichar(*b)] += 1;
    }
    if verbose {
        println!("To begin, counts are:\n  [chars] {}\n  [pairs] {}",
                 dispchars(&chars), disppairs(&pairs));
    }
    for step in 0..steps {
        // Apply all updates in one step.
        let mut pair_updates: HashMap<u16, isize> = HashMap::with_capacity(span * span);
        for (pair, count) in &pairs {
            let (pair, count) = (*pair, *count);
            if let Some(new) = rules.get(&pair) {
                let new = *new;
                let (left, right) = pairsplit(pair);
                // Replace the pair with two new pairs.
                *pair_updates.entry(pair).or_insert(0) -= count as isize;
                *pair_updates.entry(polypair(left, new)).or_insert(0) += count as isize;
                *pair_updates.entry(polypair(new, right)).or_insert(0) += count as isize;
                chars[ichar(new)] += count;
            }
        }
        for (pair, inserted) in pair_updates {
            let count = pairs.entry(pair).or_insert(0);
            if inserted > 0 {
                *count += inserted as usize;
            } else {
                *count -= (-inserted) as usize;
            }
        }
        if verbose {
            println!("After step {}:\n  [chars] {}\n  [pairs] {}",
                     step + 1, dispchars(&chars), disppairs(&pairs));
        }
    }
    chars.into_iter().fold((usize::MAX, 0), |(min, max), count| {
        (if count > 0 { min.min(count) } else { min }, max.max(count))
    })
}
// Count the numbers of each character after n solution steps.
//
// Return the (least, most) frequent counts.
Count the numbers of each character after n solution steps.
Return the (least, most) frequent counts.
Count the numbers of each character after n solution steps . Return the ( least most ) frequent counts .
fn polymer_counts(polymer: &String, rules: &HashMap<u16, u8>, steps: usize, verbose: bool)
    -> (usize, usize)
{
    let span = usize::from(1 + b'Z' - b'A');
    /* With a vector instead of a hash map, we need to iterate through all possible pairs
     * each iteration, not just the ones which are nonzero. Let's check later which is faster.
    let mut pairs: Vec<usize> = std::iter::repeat(0).take(span).collect();
    fn ipair(p: u16) -> usize {
        let (a, b) = pairsplit(p);
        a * span + b
    }
    */
    let mut pairs: HashMap<u16, usize> = HashMap::with_capacity(span * span);
    let mut chars: Vec<usize> = std::iter::repeat(0).take(span).collect();
    #[inline]
    fn ichar(b: u8) -> usize { usize::from(b - b'A') }
    for pair in polymer.as_bytes().windows(2) {
        chars[ichar(pair[0])] += 1;
        chars[ichar(pair[1])] += 1;
        *pairs.entry(polypair(pair[0], pair[1])).or_insert(0) += 1;
    }
    // The last character is not covered by windows(2).
    if let Some(b) = polymer.as_bytes().last() {
        chars[ichar(*b)] += 1;
    }
    if verbose {
        println!("To begin, counts are:\n  [chars] {}\n  [pairs] {}",
                 dispchars(&chars), disppairs(&pairs));
    }
    for step in 0..steps {
        // Apply all updates in one step.
        let mut pair_updates: HashMap<u16, isize> = HashMap::with_capacity(span * span);
        for (pair, count) in &pairs {
            let (pair, count) = (*pair, *count);
            if let Some(new) = rules.get(&pair) {
                let new = *new;
                let (left, right) = pairsplit(pair);
                // Replace the pair with two new pairs.
                *pair_updates.entry(pair).or_insert(0) -= count as isize;
                *pair_updates.entry(polypair(left, new)).or_insert(0) += count as isize;
                *pair_updates.entry(polypair(new, right)).or_insert(0) += count as isize;
                chars[ichar(new)] += count;
            }
        }
        for (pair, inserted) in pair_updates {
            let count = pairs.entry(pair).or_insert(0);
            if inserted > 0 {
                *count += inserted as usize;
            } else {
                *count -= (-inserted) as usize;
            }
        }
        if verbose {
            println!("After step {}:\n  [chars] {}\n  [pairs] {}",
                     step + 1, dispchars(&chars), disppairs(&pairs));
        }
    }
    chars.into_iter().fold((usize::MAX, 0), |(min, max), count| {
        (if count > 0 { min.min(count) } else { min }, max.max(count))
    })
}
fn polymer_counts ( polymer : & String , rules : & HashMap < u16 , u8 > , steps : usize , verbose : bool ) -> ( usize , usize ) { let span = usize :: from ( 1 + b'Z' - b'A' ) ; /* With a vector instead of a hash map, we need to iterate through all possible pairs
     * each iteration, not just the ones which are nonzero. Let's check later which is faster.
    let mut pairs: Vec<usize> = std::iter::repeat(0).take(span).collect();
    fn ipair(p: u16) -> usize {
        let (a, b) = pairsplit(p);
        a * span + b
    }
    */ let mut pairs : HashMap < u16 , usize > = HashMap :: with_capacity ( span * span ) ; let mut chars : Vec < usize > = std :: iter :: repeat ( 0 ) . take ( span ) . collect ( ) ; # [ inline ] fn ichar ( b : u8 ) -> usize { usize :: from ( b - b'A' ) } for pair in polymer . as_bytes ( ) . windows ( 2 ) { chars [ ichar ( pair [ 0 ] ) ] += 1 ; chars [ ichar ( pair [ 1 ] ) ] += 1 ; * pairs . entry ( polypair ( pair [ 0 ] , pair [ 1 ] ) ) . or_insert ( 0 ) += 1 ; } // The last character is not covered by windows(2). if let Some ( b ) = polymer . as_bytes ( ) . last ( ) { chars [ ichar ( * b ) ] += 1 ; } if verbose { println ! ( " \n \n " dispchars ( chars ) disppairs ( pairs ) ) ; } for step in 0 .. steps { // Apply all updates in one step. let mut pair_updates : HashMap < u16 , isize > = HashMap :: with_capacity ( span * span ) ; for ( pair , count ) in & pairs { let ( pair , count ) = ( * pair , * count ) ; if let Some ( new ) = rules . get ( & pair ) { let new = * new ; let ( left , right ) = pairsplit ( pair ) ; // Replace the pair with two new pairs. * pair_updates . entry ( pair ) . or_insert ( 0 ) -= count as isize ; * pair_updates . entry ( polypair ( left , new ) ) . or_insert ( 0 ) += count as isize ; * pair_updates . entry ( polypair ( new , right ) ) . or_insert ( 0 ) += count as isize ; chars [ ichar ( new ) ] += count ; } } for ( pair , inserted ) in pair_updates { let count = pairs . entry ( pair ) . or_insert ( 0 ) ; if inserted > 0 { * count += inserted as usize ; } else { * count -= ( - inserted ) as usize ; } } if verbose { println ! ( " \n \n " step 1 dispchars ( chars ) disppairs ( pairs ) ) ; } } chars . into_iter ( ) . fold ( ( usize :: MAX , 0 ) , | ( min , max ) , count | { ( if count > 0 { min . min ( count ) } else { min } , max . max ( count ) ) } ) }
Count the numbers of each character after n solution steps.
Count the numbers of each character after n solution steps .
polymer
&String
rules
&HashMap<u16, u8>
steps
usize
verbose
bool