codebreaker_solver/
hint.rs1use std::cmp::min;
2
3use crate::{
4 code::{Code, NUMBER_OF_PEGS_IN_CODE},
5 peg::{Peg, POSSIBLE_COLORS},
6};
7
8#[derive(Debug, PartialEq, Eq, Clone, Copy)]
11pub struct Hint {
12 pub correct: u8,
14 pub displaced: u8,
18}
19
20impl Hint {
21 pub fn new(guess: Code, code: Code) -> Self {
22 let (correct, displaced) =
23 POSSIBLE_COLORS
24 .iter()
25 .fold((0, 0), |(total_correct, total_displaced), &color| {
26 let (color_correct, color_displaced) = color_hint(color, guess, code);
27 (
28 total_correct + color_correct,
29 total_displaced + color_displaced,
30 )
31 });
32
33 Hint { correct, displaced }
34 }
35
36 pub fn is_solution(&self) -> bool {
37 self.correct == NUMBER_OF_PEGS_IN_CODE as u8
38 }
39}
40
41fn color_hint(color: Peg, guess: Code, code: Code) -> (u8, u8) {
43 let mut color_guess = 0;
44 let mut color_code = 0;
45 let mut correct = 0;
46 for (&guess, code) in guess.0.iter().zip(code.0) {
47 if guess == color {
48 color_guess += 1;
49 }
50 if code == color {
51 color_code += 1;
52 }
53 if guess == color && code == color {
54 correct += 1;
55 }
56 }
57 let displaced = min(color_code, color_guess) - correct;
58 (correct, displaced)
59}
60
61#[cfg(test)]
62mod tests {
63 use super::Hint;
64
65 #[test]
66 fn hint() {
67 let hint = Hint::new("6335".parse().unwrap(), "3311".parse().unwrap());
68 assert_eq!(
69 hint,
70 Hint {
71 correct: 1,
72 displaced: 1
73 }
74 )
75 }
76}