ogs/
stats.rs

1use std::fmt::Display;
2
3pub trait SolverEvent {
4    #[inline] fn take_option(&mut self) {}
5    #[inline] fn break_option(&mut self) {}
6    #[inline] fn rebuilding_rc(&mut self, _nimbers_len: usize) {}
7}
8
9impl SolverEvent for () {}
10
11#[derive(Default, Clone, Copy)]
12pub struct SolverIterations {
13    pub taking: usize,
14    pub breaking: usize,
15    pub rebuilding_rc: usize,
16    pub rebuilding_r_positions: usize
17}
18
19impl SolverEvent for SolverIterations {
20    #[inline] fn take_option(&mut self) { self.taking += 1; }
21    #[inline] fn break_option(&mut self) { self.breaking += 1; }
22    #[inline] fn rebuilding_rc(&mut self, rebuilding_r_positions: usize) {
23         self.rebuilding_rc += 1;
24         self.rebuilding_r_positions += rebuilding_r_positions
25    }
26}
27
28impl Display for SolverIterations {
29    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30        if self.taking != 0 { write!(f, "taking: {}  ", self.taking)?; }
31        if self.breaking != 0 { write!(f, "breaking: {}  ", self.breaking)?; }
32        write!(f, "total: {}", self.taking+self.breaking)?;
33        if self.rebuilding_rc != 0 { write!(f, "  RC effort/rebuilds: {}/{}", self.rebuilding_r_positions, self.rebuilding_rc)?; }
34        Ok(())
35    }
36}
37
38pub struct NimberStats {
39    pub occurences: [u32; 1<<16],
40    pub max: u16
41}
42
43impl Default for NimberStats {
44    fn default() -> Self { Self { occurences: [0; 1<<16], max: 0 } }
45}
46
47impl NimberStats {
48    pub fn count(&mut self, nimber: u16) {
49        self.occurences[nimber as usize] += 1;
50        if nimber > self.max { self.max = nimber; }
51    }
52
53    /// Returns sorted vector of nimbers, from the most to the less commmon, skip chosen nimber
54    pub fn nimbers_from_most_common(&self, to_skip: u16) -> Vec<u16> {
55        let mut result = Vec::with_capacity(self.max as usize);
56        if to_skip == 0 {
57            for nimber in 1..=self.max {
58                if self.occurences[nimber as usize] != 0 {
59                    result.push(nimber);
60                }
61            }
62        } else {
63            for nimber in 0..=self.max {
64                if nimber != to_skip && self.occurences[nimber as usize] != 0 {
65                    result.push(nimber);
66                }
67            }
68        }
69        // we use stable sort to lower nimber be the first in the case of tie
70        result.sort_by(|a, b| self.occurences[*b as usize].cmp(&self.occurences[*a as usize]));
71        result
72    }
73}
74
75impl Display for NimberStats {
76    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77        if f.sign_plus() {  // pairs:
78            for nimber in (0..=self.max).step_by(2) {
79                let occ = (self.occurences[nimber as usize], self.occurences[nimber as usize + 1]);
80                if occ.0 != 0 || occ.1 != 0 {
81                    if nimber != 0 { write!(f, "\t")?; }
82                    write!(f, "{:>2}:{}+{}", nimber>>1, occ.0, occ.1)?;
83                }
84            }
85        } else {
86            for nimber in 0..=self.max {
87                let occ = self.occurences[nimber as usize];
88                if occ != 0 {
89                    if nimber != 0 { write!(f, "\t")?; }
90                    write!(f, "{:>2}:{}", nimber, occ)?;
91                }
92            }
93        }
94        Ok(())
95    }
96}