sorting_race/services/sorters/
selection.rs1use crate::models::traits::{Sorter, StepResult, Telemetry, Markers};
4use std::any::Any;
5
6#[derive(Debug)]
8pub struct SelectionSort {
9 data: Vec<i32>,
10 current_position: usize,
11 search_index: usize,
12 min_index: usize,
13 comparisons: u64,
14 moves: u64,
15 complete: bool,
16}
17
18impl SelectionSort {
19 pub fn new() -> Self {
21 Self {
22 data: Vec::new(),
23 current_position: 0,
24 search_index: 1,
25 min_index: 0,
26 comparisons: 0,
27 moves: 0,
28 complete: false,
29 }
30 }
31}
32
33impl Default for SelectionSort {
34 fn default() -> Self {
35 Self::new()
36 }
37}
38
39impl Sorter for SelectionSort {
40 fn step(&mut self, budget: usize) -> StepResult {
41 if self.complete || self.data.len() <= 1 {
42 return StepResult {
43 comparisons_used: 0,
44 moves_made: 0,
45 continued: false,
46 };
47 }
48
49 let mut comparisons_used = 0;
50 let mut moves_made = 0;
51
52 while comparisons_used < budget && !self.complete {
53 if self.current_position >= self.data.len() - 1 {
54 self.complete = true;
55 break;
56 }
57
58 if self.search_index < self.data.len() {
59 comparisons_used += 1;
61 self.comparisons += 1;
62
63 if self.data[self.search_index] < self.data[self.min_index] {
64 self.min_index = self.search_index;
65 }
66
67 self.search_index += 1;
68 } else {
69 if self.min_index != self.current_position {
71 self.data.swap(self.current_position, self.min_index);
72 moves_made += 1;
73 self.moves += 1;
74 }
75
76 self.current_position += 1;
78 if self.current_position < self.data.len() {
79 self.search_index = self.current_position + 1;
80 self.min_index = self.current_position;
81 }
82 }
83 }
84
85 StepResult {
86 comparisons_used,
87 moves_made,
88 continued: !self.complete,
89 }
90 }
91
92 fn is_complete(&self) -> bool {
93 self.complete
94 }
95
96 fn get_telemetry(&self) -> Telemetry {
97 let mut markers = Markers::default();
98
99 if !self.complete {
100 if self.search_index < self.data.len() {
101 markers.cursors = vec![self.current_position, self.search_index, self.min_index];
102 } else if self.current_position < self.data.len() {
103 markers.cursors = vec![self.current_position, self.min_index];
104 }
105 }
106
107 markers.cursors.sort_unstable();
109 markers.cursors.dedup();
110
111 Telemetry {
112 total_comparisons: self.comparisons,
113 total_moves: self.moves,
114 memory_current: self.get_memory_usage(),
115 memory_peak: self.get_memory_usage(),
116 highlights: markers.cursors.clone(),
117 markers,
118 status_text: if self.complete {
119 "Completed".to_string()
120 } else if self.search_index < self.data.len() {
121 format!("Position {}, searching at {}, min at {}",
122 self.current_position, self.search_index, self.min_index)
123 } else {
124 format!("Position {}, found min at {}", self.current_position, self.min_index)
125 },
126 progress_hint: if self.data.len() <= 1 {
127 1.0
128 } else {
129 let progress = (self.current_position as f32) / ((self.data.len() - 1) as f32);
130 progress.min(1.0).max(0.0) },
132 }
133 }
134
135 fn reset(&mut self, data: Vec<i32>) {
136 self.data = data;
137 self.current_position = 0;
138 self.search_index = 1;
139 self.min_index = 0;
140 self.comparisons = 0;
141 self.moves = 0;
142 self.complete = self.data.len() <= 1;
143 }
144
145 fn name(&self) -> &str {
146 "Selection Sort"
147 }
148
149 fn get_array(&self) -> &[i32] {
150 &self.data
151 }
152
153 fn get_memory_usage(&self) -> usize {
154 self.data.len() * std::mem::size_of::<i32>()
156 }
157
158 fn as_any(&self) -> &dyn Any {
159 self
160 }
161
162 fn as_any_mut(&mut self) -> &mut dyn Any {
163 self
164 }
165}