pixelator_core/common/
utils.rs1use std::cmp::Ordering;
2use std::collections::VecDeque;
3use std::fmt;
4
5use itertools::Itertools;
6use rand::prelude::*;
7
8use crate::common::types::NodeIdx;
9
10pub fn mode_via_sort(numbers: &mut [usize]) -> usize {
17 if numbers.is_empty() {
18 panic!("No numbers to choose from, `numbers` is empty");
19 }
20
21 numbers.sort_unstable();
22
23 let mut rng = rand::rng();
24 let ((_, best_n), _) = numbers.iter().dedup_with_count().fold(
25 ((0, 0), 0),
26 |((best_count, best_n), ties), (c, &n)| match c.cmp(&best_count) {
27 Ordering::Less => ((best_count, best_n), ties),
28 Ordering::Greater => ((c, n), 1),
29 Ordering::Equal => {
30 let ties = ties + 1;
31 if rng.random_bool(1. / ties as f64) {
32 ((c, n), ties)
33 } else {
34 ((best_count, best_n), ties)
35 }
36 }
37 },
38 );
39 best_n
40}
41
42pub struct NodeQueue {
43 queue: VecDeque<NodeIdx>,
44 present: Vec<bool>,
45}
46
47impl fmt::Debug for NodeQueue {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 if self.queue.len() > 20 {
50 write!(
51 f,
52 "NodeQueue(len: {}, front: {:?}, ... , back: {:?})",
53 self.queue.len(),
54 self.queue.iter().take(3).collect::<Vec<&NodeIdx>>(),
55 self.queue.iter().rev().take(3).collect::<Vec<&NodeIdx>>()
56 )
57 } else {
58 write!(
59 f,
60 "NodeQueue(len: {}, elements: {:?})",
61 self.queue.len(),
62 self.queue
63 )
64 }
65 }
66}
67impl NodeQueue {
73 pub fn from(vec: Vec<NodeIdx>) -> Self {
74 let present = vec![true; vec.len()];
75
76 NodeQueue {
77 queue: VecDeque::from(vec),
78 present,
79 }
80 }
81
82 pub fn pop_front(&mut self) -> Option<NodeIdx> {
83 let node = self.queue.pop_front();
84 if let Some(n) = node {
85 self.present[n] = false;
86 }
87 node
88 }
89
90 pub fn push_back(&mut self, node: NodeIdx) {
91 if !self.present[node] {
92 self.queue.push_back(node);
93 self.present[node] = true;
94 }
95 }
96
97 pub fn is_empty(&self) -> bool {
98 self.queue.is_empty()
99 }
100
101 pub fn len(&self) -> usize {
102 self.queue.len()
103 }
104
105 pub fn contains(&self, node: NodeIdx) -> bool {
106 self.present[node]
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113 use rustc_hash::FxHashSet as HashSet;
114
115 #[test]
116 fn test_mode_via_sort_basic() {
117 let mut data = vec![1, 2, 2, 3];
118 let mode = mode_via_sort(&mut data);
119 assert_eq!(mode, 2);
120 }
121
122 #[test]
123 fn test_mode_via_sort_tie() {
124 let mut data = vec![1, 2, 1, 2, 3];
126 let mode = mode_via_sort(&mut data);
127 assert!(mode == 1 || mode == 2);
128 }
129
130 #[test]
131 fn test_mode_via_sort_single_element() {
132 let mut data = vec![42];
133 let mode = mode_via_sort(&mut data);
134 assert_eq!(mode, 42);
135 }
136
137 #[test]
138 #[should_panic]
139 fn test_mode_via_sort_empty_panics() {
140 let mut data: Vec<usize> = vec![];
141 let _ = mode_via_sort(&mut data);
142 }
143
144 #[test]
145 fn test_nodequeue_basic_operations() {
146 let mut nq = NodeQueue::from(vec![0, 1, 2]);
147 assert_eq!(nq.len(), 3);
148 assert!(!nq.is_empty());
149 assert!(nq.contains(1));
150
151 assert_eq!(nq.pop_front(), Some(0));
152 assert!(!nq.contains(0));
153 assert_eq!(nq.len(), 2);
154
155 nq.push_back(2);
157 assert_eq!(nq.len(), 2);
158
159 nq.push_back(0);
161 assert_eq!(nq.len(), 3);
162 assert_eq!(nq.pop_front(), Some(1));
163 assert_eq!(nq.pop_front(), Some(2));
164 assert_eq!(nq.pop_front(), Some(0));
165 assert!(nq.is_empty());
166 }
167
168 #[test]
169 fn test_nodequeue_uniqueness() {
170 let mut nq = NodeQueue::from(vec![0, 1]);
171 nq.push_back(1); nq.push_back(0); assert_eq!(nq.len(), 2);
174 let mut seen = HashSet::default();
175 while let Some(n) = nq.pop_front() {
176 assert!(!seen.contains(&n));
177 seen.insert(n);
178 }
179 assert!(nq.is_empty());
180 }
181
182 #[test]
183 fn test_nodequeue_from_preserves_order() {
184 let mut nq = NodeQueue::from(vec![0, 1, 2, 3]);
185 assert_eq!(nq.pop_front(), Some(0));
186 assert_eq!(nq.pop_front(), Some(1));
187 assert_eq!(nq.pop_front(), Some(2));
188 assert_eq!(nq.pop_front(), Some(3));
189 assert_eq!(nq.pop_front(), None);
190 }
191
192 #[test]
193 fn test_nodequeue_reenqueue_after_pop() {
194 let mut nq = NodeQueue::from(vec![0, 1]);
195 assert_eq!(nq.pop_front(), Some(0));
196 assert!(!nq.contains(0));
197
198 nq.push_back(0);
199 assert!(nq.contains(0));
200 assert_eq!(nq.pop_front(), Some(1));
201 assert_eq!(nq.pop_front(), Some(0));
202 }
203
204 #[test]
205 #[should_panic]
206 fn test_nodequeue_contains_out_of_range_panics() {
207 let nq = NodeQueue::from(vec![0, 1, 2]);
208 let _ = nq.contains(3);
209 }
210
211 #[test]
212 fn test_nodequeue_empty_invariants() {
213 let mut nq = NodeQueue::from(vec![]);
214 assert!(nq.is_empty());
215 assert_eq!(nq.len(), 0);
216 assert_eq!(nq.pop_front(), None);
217 }
218
219 #[test]
220 #[should_panic]
221 fn test_nodequeue_push_back_out_of_range_panics() {
222 let mut nq = NodeQueue::from(vec![0, 1, 2]);
223 nq.push_back(3);
224 }
225
226 #[test]
227 fn test_nodequeue_all_nodes_present_at_initialization() {
228 let nq = NodeQueue::from(vec![0, 1, 2, 3]);
229 assert!(nq.contains(0));
230 assert!(nq.contains(1));
231 assert!(nq.contains(2));
232 assert!(nq.contains(3));
233 }
234}