/**
 * Transforms a map of pairs to counts by applying the right action.
 *
 * For (A,B) -> C, (that is AB becomes ACB)
 * the counts of A and B remain, but the count of C increases with the number of occurences of AB.
 * The number of (A,C) and (C,B) is the amount of (A,B) in the input. Because other transformations
 * may also insert (C,B) (like (X,B)->B) we need to increment and not just set the count. To keep
 * track of the old and new counts, 2 separate maps are needed.
 *
 * To quickly find the transformation to be applied, the list must be sorted by from
 **/
Transforms a map of pairs to counts by applying the right action.
For (A,B) -> C, (that is AB becomes ACB)
the counts of A and B remain, but the count of C increases with the number of occurences of AB.
The number of (A,C) and (C,B) is the amount of (A,B) in the input. Because other transformations
may also insert (C,B) (like (X,B)->B) we need to increment and not just set the count. To keep
track of the old and new counts, 2 separate maps are needed.

To quickly find the transformation to be applied, the list must be sorted by from
Transforms a map of pairs to counts by applying the right action . For ( A B ) - > C ( that is AB becomes ACB ) the counts of A and B remain but the count of C increases with the number of occurences of AB . The number of ( A C ) and ( C B ) is the amount of ( A B ) in the input . Because other transformations may also insert ( C B ) ( like ( X B ) - > B ) we need to increment and not just set the count . To keep track of the old and new counts 2 separate maps are needed . To quickly find the transformation to be applied the list must be sorted by from
fn transform(
    pairs: &mut HashMap<[char; 2], u64>, // num occurences per pair of characters
    counts: &mut HashMap<char, u64>,     // counts of individual letters
    actions: &Vec<Line>,                 // sorted transformations
) {
    let mut pairs_new: HashMap<[char; 2], u64> = HashMap::new();
    for (key, val) in &*pairs {
        let found = actions.binary_search_by_key(&key, |v| &v.from);
        match found {
            Ok(pos) => {
                let new_char: char = actions[pos].to.to_owned();
                inc_with(&mut pairs_new, [key[0], new_char], *val);
                inc_with(&mut pairs_new, [new_char, key[1]], *val);
                inc_with(counts, new_char, *val);
            }
            Err(_) => {
                // does not change
                inc_with(&mut pairs_new, *key, *val);
            }
        }
    }
    *pairs = pairs_new;
}
fn transform ( pairs : & mut HashMap < [ char ; 2 ] , u64 > , // num occurences per pair of characters counts : & mut HashMap < char , u64 > , // counts of individual letters actions : & Vec < Line > , // sorted transformations ) { let mut pairs_new : HashMap < [ char ; 2 ] , u64 > = HashMap :: new ( ) ; for ( key , val ) in & * pairs { let found = actions . binary_search_by_key ( & key , | v | & v . from ) ; match found { Ok ( pos ) => { let new_char : char = actions [ pos ] . to . to_owned ( ) ; inc_with ( & mut pairs_new , [ key [ 0 ] , new_char ] , * val ) ; inc_with ( & mut pairs_new , [ new_char , key [ 1 ] ] , * val ) ; inc_with ( counts , new_char , * val ) ; } Err ( _ ) => { // does not change inc_with ( & mut pairs_new , * key , * val ) ; } } } * pairs = pairs_new ; }
Transforms a map of pairs to counts by applying the right action.
Transforms a map of pairs to counts by applying the right action .
pairs
&mut HashMap<[char; 2], u64>
counts
&mut HashMap<char, u64>
actions
&Vec<Line>