1use core::hash::Hash;
10use std::collections::HashMap;
11use std::fmt::Debug;
12use std::ops::Range;
13
14#[derive(Debug, PartialEq, Eq)]
18pub struct PermutationResult {
19 pub perm: Vec<usize>,
20 pub unmatched_source_indices: Vec<usize>,
21 pub unmatched_target_indices: Vec<usize>,
22}
23
24#[derive(Debug)]
28pub struct ExpandedPermResult {
29 pub perm: Vec<Option<usize>>,
30 pub unmatched_source_indices: Vec<usize>,
31 pub unmatched_target_indices: Vec<usize>,
32}
33
34impl ExpandedPermResult {
35 fn collapse(self) -> PermutationResult {
38 let Self {
39 perm,
40 unmatched_source_indices,
41 unmatched_target_indices,
42 } = self;
43
44 PermutationResult {
45 perm: perm.into_iter().flatten().collect(),
46 unmatched_source_indices,
47 unmatched_target_indices,
48 }
49 }
50}
51pub fn generate_expanded_permutation<T>(source: &[T], target: &[T]) -> ExpandedPermResult
55where
56 T: Hash + Eq,
57{
58 let mut index_source: HashMap<&T, Vec<usize>> = Default::default();
59 let mut unmatched_target_indices: Vec<usize> = Default::default();
60 let mut unmatched_source_indices: Vec<usize>;
61
62 source
63 .iter()
64 .enumerate()
65 .for_each(|(i, v)| index_source.entry(v).or_default().push(i));
66
67 index_source.values_mut().for_each(|vec| vec.reverse());
68
69 let result_perm = target
70 .iter()
71 .enumerate()
72 .map(|(i, v)| (i, index_source.get_mut(v).and_then(|tp| tp.pop())))
73 .map(|(i, v)| {
74 v.is_none().then(|| unmatched_target_indices.push(i));
75 v
76 })
77 .collect::<Vec<_>>();
78
79 unmatched_source_indices = index_source
80 .values()
81 .flat_map(|v| v.iter())
82 .cloned()
83 .collect();
84
85 unmatched_source_indices.sort();
86
87 ExpandedPermResult {
88 perm: result_perm,
89 unmatched_source_indices,
90 unmatched_target_indices,
91 }
92}
93
94pub fn generate_permutation<T>(source: &[T], target: &[T]) -> PermutationResult
101where
102 T: Hash + Eq,
103{
104 generate_expanded_permutation(source, target).collapse()
105}
106
107fn find_sortable_range(perm: &[usize], max_index: usize) -> Range<usize> {
117 let prefix_len = perm
118 .iter()
119 .enumerate()
120 .take_while(|(expected, value)| *expected == **value)
121 .count();
122
123 let postfix_len = if prefix_len < perm.len() {
127 perm.iter()
128 .rev()
129 .enumerate()
130 .take_while(|(index_from_end, value)| (max_index - *index_from_end) == **value)
131 .count()
132 } else {
133 0
134 };
135
136 Range {
137 start: prefix_len,
138 end: perm.len() - postfix_len,
139 }
140}
141
142pub struct BubbleSortIter<'a, T> {
143 perm: Vec<usize>,
144 source: &'a [T],
145 swap_history: Vec<(usize, usize)>,
146 history_size: usize,
147 history_cursor: usize,
148 unused_value_count: usize,
149}
150
151impl<'a, T> BubbleSortIter<'a, T>
152where
153 T: Hash + Eq,
154{
155 fn new(
156 perm: Vec<usize>,
157 source: &'a [T],
158 swap_history: Vec<(usize, usize)>,
159 unused_value_count: usize,
160 ) -> Self {
161 BubbleSortIter {
162 perm,
163 source,
164 history_size: swap_history.len(),
165 history_cursor: swap_history.len(),
166 swap_history,
167 unused_value_count,
168 }
169 }
170
171 pub fn edit_distance(&self) -> usize {
175 self.history_size + self.unused_value_count
176 }
177
178 pub fn swap_distance(&self) -> usize {
181 self.history_size
182 }
183
184 pub fn next<'b>(&'b mut self) -> Option<Perm<'a, 'b, T>> {
185 (self.history_cursor < self.history_size).then(|| {
186 let swap = self.swap_history[self.history_cursor];
187 self.perm.swap(swap.0, swap.1);
188 self.history_cursor += 1;
189
190 self.current()
191 })
192 }
193
194 pub fn skip(&mut self, distance: usize) {
195 for _ in 0..distance {
196 let _ = self.next();
197 }
198 }
199
200 pub fn next_back<'b>(&'b mut self) -> Option<Perm<'a, 'b, T>> {
201 (self.history_cursor > 0).then(|| {
202 self.history_cursor -= 1;
203 let swap = self.swap_history[self.history_cursor];
204 self.perm.swap(swap.0, swap.1);
205
206 self.current()
207 })
208 }
209
210 pub fn skip_back(&mut self, distance: usize) {
211 for _ in 0..distance {
212 let _ = self.next_back();
213 }
214 }
215
216 pub fn current<'b>(&'b self) -> Perm<'a, 'b, T> {
217 Perm::new(self)
218 }
219
220 pub fn midpoint<'b>(&'b mut self) -> Perm<'a, 'b, T> {
221 let m = self.history_size / 2;
222 if m > self.history_cursor {
223 self.skip(m - self.history_cursor);
224 } else {
225 self.skip_back(self.history_cursor - m);
226 }
227 self.current()
228 }
229
230 pub fn interpolate<'b>(&'b mut self, interpolate_percentage: u8) -> Perm<'a, 'b, T> {
231 let m = (self.history_size * (interpolate_percentage as usize)) / 100;
232 if m > self.history_cursor {
233 self.skip(m - self.history_cursor);
234 } else {
235 self.skip_back(self.history_cursor - m);
236 }
237 self.current()
238 }
239
240 pub fn history_size(&self) -> usize {
241 self.history_size
242 }
243}
244
245pub struct Perm<'a, 'b, T> {
246 perm: &'b Vec<usize>,
247 source: &'a [T],
248 i: usize,
249}
250
251impl<'a, 'b, T> Perm<'a, 'b, T> {
252 fn new(parent: &'b BubbleSortIter<'a, T>) -> Self {
253 Perm {
254 perm: &parent.perm,
255 source: parent.source,
256 i: 0,
257 }
258 }
259}
260
261impl<'a, 'b, T> Iterator for Perm<'a, 'b, T>
262where
263 T: Hash + Eq,
264{
265 type Item = &'a T;
266
267 fn next(&mut self) -> Option<Self::Item> {
268 (self.i < self.perm.len()).then(|| {
269 let result = &self.source[self.perm[self.i]];
270 self.i += 1;
271 result
272 })
273 }
274}
275
276fn bubble_sort_history<T>(perm: &mut [usize], source: &[T]) -> Vec<(usize, usize)> {
279 let mut history = vec![];
280 let sortable_range = find_sortable_range(perm, source.len() - 1);
281 let index_offset = sortable_range.start;
282 let sortable_slice = &mut perm[sortable_range];
283 let size = sortable_slice.len();
284
285 if size == 0 {
286 return history;
287 }
288
289 for i in 0..(size - 1) {
290 let mut swapped = false;
291 for j in 0..(size - i - 1) {
292 if sortable_slice[j] > sortable_slice[j + 1] {
293 sortable_slice.swap(j, j + 1);
297
298 history.push((index_offset + j, index_offset + j + 1));
299 swapped = true;
300 }
301 }
302
303 if !swapped {
306 break;
307 }
308 }
309
310 history
311}
312
313pub fn bubble_sort_distance<T>(source: &[T], target: &[T]) -> usize
314where
315 T: PartialEq + Hash + Eq + Debug + Clone + Copy + 'static,
316{
317 iterable_bubble_sort(source, target).history_size
318}
319
320pub fn iterable_bubble_sort_from_perm<T>(
321 source: &[T],
322 permutation_result: PermutationResult,
323) -> BubbleSortIter<'_, T>
324where
325 T: Hash + Eq,
326{
327 let PermutationResult {
328 mut perm,
329 unmatched_source_indices,
330 unmatched_target_indices,
331 } = permutation_result;
332
333 let history = bubble_sort_history(&mut perm, source);
334
335 let unused_values = unmatched_source_indices.len() + unmatched_target_indices.len();
336
337 BubbleSortIter::new(perm, source, history, unused_values)
338}
339
340pub fn iterable_bubble_sort<'a, T>(source: &'a [T], target: &'a [T]) -> BubbleSortIter<'a, T>
341where
342 T: Hash + Eq,
343{
344 iterable_bubble_sort_from_perm(source, generate_permutation(source, target))
345}
346
347#[cfg(test)]
348mod tests {
349 use std::str::from_utf8;
350
351 use super::*;
352
353 #[test]
354 fn test_get_permutations() {
355 assert_eq!(
356 generate_permutation(b"abaca", b"aaacb"),
357 PermutationResult {
358 perm: vec![0, 2, 4, 3, 1],
359 unmatched_source_indices: vec![],
360 unmatched_target_indices: vec![],
361 }
362 );
363 }
364
365 #[test]
366 fn test_get_permutations_with_mismatch() {
367 assert_eq!(
368 generate_permutation(b"abacaF", b"aaaacb"),
369 PermutationResult {
370 perm: vec![0, 2, 4, 3, 1],
371 unmatched_source_indices: vec![5],
372 unmatched_target_indices: vec![3],
373 }
374 );
375 }
376
377 #[test]
378 fn test_get_permutations_with_lots_of_mismatches() {
379 assert_eq!(
381 generate_permutation(b"AabcefGHijmNNp", b"abcDefijKLmOpQRST"),
382 PermutationResult {
383 perm: vec![1, 2, 3, 4, 5, 8, 9, 10, 13],
384 unmatched_source_indices: vec![0, 6, 7, 11, 12],
385 unmatched_target_indices: vec![3, 8, 9, 11, 13, 14, 15, 16],
386 }
387 );
388
389 assert_eq!(
392 generate_permutation(b"fceaiGHNpbAjmN", b"abcDefijKLmOpQRST"),
393 PermutationResult {
394 perm: vec![3, 9, 1, 2, 0, 4, 11, 12, 8],
395 unmatched_source_indices: vec![5, 6, 7, 10, 13],
396 unmatched_target_indices: vec![3, 8, 9, 11, 13, 14, 15, 16],
397 }
398 );
399 }
400 macro_rules! assert_sortable_range_eq {
401 ([$($full:expr),*], [$($expected_sortable_range:expr),*]; where max_index = $max_index:expr) => {
402 let full_perm : &[usize] = &[$($full),*];
403 let range = find_sortable_range(full_perm, $max_index);
404 let actual_sortable_range = &full_perm[range];
405 let expected_sortable_range: &[usize] = &[$($expected_sortable_range),*];
406 assert_eq!(actual_sortable_range, expected_sortable_range);
407 };
408 }
409
410 #[test]
411 fn test_find_sortable_range() {
412 assert_sortable_range_eq!([0, 1, 2, 3, 4, 5, 6], []; where max_index = 6);
413 assert_sortable_range_eq!([0, 1, 2, 4, 3, 5, 6], [4, 3]; where max_index = 6);
414 assert_sortable_range_eq!([0, 1, 2, 4, 3, 5, 6], [4, 3, 5, 6]; where max_index = 7);
415 assert_sortable_range_eq!([1, 2, 4, 3, 5, 6], [1, 2, 4, 3]; where max_index = 6);
416 }
417
418 #[test]
419 fn test_bubble_sort_distance() {
420 assert_eq!(bubble_sort_distance(b"abaca", b"aaacb"), 4);
421 }
422
423 macro_rules! assert_perm_eq {
424 ($expected:expr, $perm:expr) => {
425 assert_eq!(
426 Ok($expected),
427 from_utf8(&$perm.cloned().collect::<Vec<u8>>())
428 );
429 };
430 }
431
432 #[test]
433 fn test_bubble_sort_iterator() {
434 let mut it = iterable_bubble_sort(b"abaca", b"aaacb");
435
436 assert_perm_eq!("abaca", it.current());
439 assert_perm_eq!("aabca", it.next_back().expect("Should be 1 of 4"));
440 assert_perm_eq!("aacba", it.next_back().expect("Should be 2 of 4"));
441 assert_perm_eq!("aacab", it.next_back().expect("Should be 3 of 4"));
442 assert_perm_eq!("aaacb", it.next_back().expect("Should be 4 of 4"));
443
444 assert_perm_eq!("aaacb", it.current());
447 assert_perm_eq!("aacab", it.next().expect("Should be 1 of 4"));
448 assert_perm_eq!("aacba", it.next().expect("Should be 2 of 4"));
449 assert_perm_eq!("aabca", it.next().expect("Should be 3 of 4"));
450 assert_perm_eq!("abaca", it.next().expect("Should be 4 of 4"));
451 }
452
453 #[test]
454 fn test_bubble_sort_distance_mismatch() {
455 assert_eq!(bubble_sort_distance(b"afbaca", b"aadacb"), 4);
456 }
457
458 #[test]
459 fn test_bubble_sort_iterator_mismatch() {
460 let mut it = iterable_bubble_sort(b"afbaca", b"aadacb");
461
462 assert_eq!(it.edit_distance(), it.swap_distance() + 2);
463
464 assert_perm_eq!("abaca", it.current());
467 assert_perm_eq!("aabca", it.next_back().expect("Should be 1 of 4"));
468 assert_perm_eq!("aacba", it.next_back().expect("Should be 2 of 4"));
469 assert_perm_eq!("aacab", it.next_back().expect("Should be 3 of 4"));
470 assert_perm_eq!("aaacb", it.next_back().expect("Should be 4 of 4"));
471
472 assert_perm_eq!("aaacb", it.current());
475 assert_perm_eq!("aacab", it.next().expect("Should be 1 of 4"));
476 assert_perm_eq!("aacba", it.next().expect("Should be 2 of 4"));
477 assert_perm_eq!("aabca", it.next().expect("Should be 3 of 4"));
478 assert_perm_eq!("abaca", it.next().expect("Should be 4 of 4"));
479 }
480
481 #[test]
482 pub fn test_midpoint() {
483 let mut it = iterable_bubble_sort(b"baaaa", b"aaaab");
484
485 assert_perm_eq!("aabaa", it.midpoint());
486 }
487
488 macro_rules! assert_expanded_target_eq {
493 ($expected:expr, expand_target($src:expr, $target:expr)) => {
494 assert_eq!(
495 Ok($expected),
496 from_utf8(
497 &generate_expanded_permutation($src, $target)
498 .perm
499 .into_iter()
500 .map(|i_opt| i_opt.map(|i| $src[i]).unwrap_or(b'_'))
501 .collect::<Vec<u8>>()
502 )
503 );
504 };
505 }
506
507 #[test]
508 pub fn test_expanted_perm() {
509 assert_expanded_target_eq!("a_", expand_target(b"a", b"ab"));
510 assert_expanded_target_eq!("aaacb", expand_target(b"abaca", b"aaacb"));
511 assert_expanded_target_eq!("_aa_ac_b", expand_target(b"aVbaFGcaER", b"PaaAacTb"));
512 }
513}