fn guess_plugboard<F: FitnessFn>(msg: &str, enigma: Enigma) -> Enigma {
    let rotor = enigma.rotor_list();
    let key = enigma.key_settings();
    let ring = enigma.ring_settings();

    let mut curr_plugboard = Vec::new();
    let mut plug_pool: Vec<char> = ('A'..='Z').collect();
    let mut best_score = F::score(&msg);

    for _ in 0..MAX_PLUGS {
        let plugs: Vec<String> = plug_pool
            .iter()
            .combinations(2)
            .map(|p| p.into_iter().collect())
            .collect();

        let (score, plug) = plugs.par_iter()
            .map(|plug| {
                let plugboard = curr_plugboard
                    .iter()
                    .chain(iter::once(plug))
                    .join(" ");

                let mut enigma = Enigma::new(&rotor, &key, &ring, 'B', &plugboard);
                (OrderedFloat(F::score(&enigma.encrypt(&msg))), plug)
            }).max().unwrap();

        if *score > best_score {
            best_score = *score;
            curr_plugboard.push(plug.to_string());
            plug_pool.retain(|&c| !plug.chars().any(|p| p == c));
        } else {
            break;
        }
    }

    Enigma::new(&rotor, &key, &ring, 'B', &curr_plugboard.iter().join(" "))
}
/// Given a piece of ciphertext, fitness function, and an `Enigma` instance
/// with the correct rotors, key, and ring settings, attempts to add plugs
/// to the plugboard until adding one does not increase the overall fitness
/// of the decryption (or the number of plugs equals `MAX_PLUGS`). Returns the
/// resulting `Enigma`.
///
/// At most, this is MAX_PLUGS * 26^2 == 6,760 tests.
Given a piece of ciphertext, fitness function, and an `Enigma` instance
with the correct rotors, key, and ring settings, attempts to add plugs
to the plugboard until adding one does not increase the overall fitness
of the decryption (or the number of plugs equals `MAX_PLUGS`). Returns the
resulting `Enigma`.


Given a piece of ciphertext fitness function and an ` Enigma ` instance with the correct rotors key and ring settings attempts to add plugs to the plugboard until adding one does not increase the overall fitness of the decryption ( or the number of plugs equals ` MAX_PLUGS ` ) . Returns the resulting ` Enigma ` .
fn guess_plugboard<F: FitnessFn>(msg: &str, enigma: Enigma) -> Enigma {
    let rotor = enigma.rotor_list();
    let key = enigma.key_settings();
    let ring = enigma.ring_settings();
    let mut curr_plugboard = Vec::new();
    let mut plug_pool: Vec<char> = ('A'..='Z').collect();
    let mut best_score = F::score(&msg);
    for _ in 0..MAX_PLUGS {
        let plugs: Vec<String> = plug_pool
            .iter()
            .combinations(2)
            .map(|p| p.into_iter().collect())
            .collect();
        let (score, plug) = plugs.par_iter()
            .map(|plug| {
                let plugboard = curr_plugboard
                    .iter()
                    .chain(iter::once(plug))
                    .join(" ");
                let mut enigma = Enigma::new(&rotor, &key, &ring, 'B', &plugboard);
                (OrderedFloat(F::score(&enigma.encrypt(&msg))), plug)
            }).max().unwrap();
        if *score > best_score {
            best_score = *score;
            curr_plugboard.push(plug.to_string());
            plug_pool.retain(|&c| !plug.chars().any(|p| p == c));
        } else {
            break;
        }
    }
    Enigma::new(&rotor, &key, &ring, 'B', &curr_plugboard.iter().join(" "))
}
fn guess_plugboard < F : FitnessFn > ( msg : & str , enigma : Enigma ) -> Enigma { let rotor = enigma . rotor_list ( ) ; let key = enigma . key_settings ( ) ; let ring = enigma . ring_settings ( ) ; let mut curr_plugboard = Vec :: new ( ) ; let mut plug_pool : Vec < char > = ( 'A' ..= 'Z' ) . collect ( ) ; let mut best_score = F :: score ( & msg ) ; for _ in 0 .. MAX_PLUGS { let plugs : Vec < String > = plug_pool . iter ( ) . combinations ( 2 ) . map ( | p | p . into_iter ( ) . collect ( ) ) . collect ( ) ; let ( score , plug ) = plugs . par_iter ( ) . map ( | plug | { let plugboard = curr_plugboard . iter ( ) . chain ( iter :: once ( plug ) ) . join ( " " ) ; let mut enigma = Enigma :: new ( & rotor , & key , & ring , 'B' , & plugboard ) ; ( OrderedFloat ( F :: score ( & enigma . encrypt ( & msg ) ) ) , plug ) } ) . max ( ) . unwrap ( ) ; if * score > best_score { best_score = * score ; curr_plugboard . push ( plug . to_string ( ) ) ; plug_pool . retain ( | & c | ! plug . chars ( ) . any ( | p | p == c ) ) ; } else { break ; } } Enigma :: new ( & rotor , & key , & ring , 'B' , & curr_plugboard . iter ( ) . join ( " " ) ) }
Given a piece of ciphertext, fitness function, and an `Enigma` instance
with the correct rotors, key, and ring settings, attempts to add plugs
to the plugboard until adding one does not increase the overall fitness
of the decryption (or the number of plugs equals `MAX_PLUGS`).
Given a piece of ciphertext fitness function and an ` Enigma ` instance with the correct rotors key and ring settings attempts to add plugs to the plugboard until adding one does not increase the overall fitness of the decryption ( or the number of plugs equals ` MAX_PLUGS ` ) .
msg
&str
enigma
Enigma
msg
&str
enigma
Enigma