Skip to main content

thanos_sort/
lib.rs

1#![doc = include_str!("../README.md")]
2#![deny(missing_docs)]
3#![warn(rustdoc::missing_crate_level_docs)]
4
5//! # Thanos Sort 🗿
6//!
7//! **⚠️ WARNING: THIS CRATE IS A JOKE. DO NOT USE FOR ACTUAL SORTING.⚠️**
8//!
9//! Thanos Sort "sorts" by repeatedly snapping away half the elements until one survivor remains.
10//! Perfectly balanced, as all things should be.
11//!
12//! # Examples
13//!
14//! Basic usage with mutable reference:
15//! ```
16//! let mut data = vec![1, 2, 3, 4, 5];
17//! let history = thanos_sort::thanos_sort(&mut data);
18//!
19//! // Only one survivor remains
20//! assert_eq!(data.len(), 1);
21//! // History tracks each snap
22//! assert_eq!(history.len(), 4); // 5 -> 3 -> 2 -> 1
23//! ```
24//!
25//! If you need to keep the original data:
26//! ```
27//! let original = vec![1, 2, 3, 4, 5];
28//! let (survivor, history) = thanos_sort::thanos_sort_owned(&original);
29//!
30//! // Original is unchanged
31//! assert_eq!(original.len(), 5);
32//! // Survivor is the result
33//! assert_eq!(survivor.len(), 1);
34//! ```
35//!
36//! **Use `data.sort_unstable()` instead.**
37extern crate self as thanos_sort;
38
39use rand::seq::SliceRandom;
40
41/// Thanos sorts by randomly halving the array until one survivor remains.
42///
43/// This function mutates the input slice in-place, destroying half of the elements
44/// (rounded down) at each iteration until only one remains. It returns a history
45/// of all intermediate states.
46///
47/// **THIS IS A JOKE. DO NOT USE FOR REAL SORTING.**
48///
49/// # Arguments
50///
51/// * `data` - A mutable reference to a `Vec<T>` to be "sorted"
52///
53/// # Returns
54///
55/// * `Vec<Vec<T>>` - History of the vector's state after each snap (including initial state)
56///
57/// # Examples
58///
59/// Basic sorting:
60/// ```
61/// use thanos_sort::thanos_sort;
62///
63/// let mut numbers = vec![4, 2, 7, 1, 9, 3];
64/// let history = thanos_sort(&mut numbers);
65///
66/// // Only one number survives
67/// assert_eq!(numbers.len(), 1);
68/// // We can see the whole history
69/// assert_eq!(history.len(), 4); // 6 -> 3 -> 2 -> 1
70/// ```
71///
72/// Empty vector:
73/// ```
74/// use thanos_sort::thanos_sort;
75///
76/// let mut empty: Vec<i32> = vec![];
77/// let history = thanos_sort(&mut empty);
78///
79/// assert!(empty.is_empty());
80/// assert_eq!(history.len(), 1);
81/// assert!(history[0].is_empty());
82/// ```
83///
84/// Single element (no snaps needed):
85/// ```
86/// use thanos_sort::thanos_sort;
87///
88/// let mut data = vec![42];
89/// let history = thanos_sort(&mut data);
90///
91/// assert_eq!(data, vec![42]);
92/// assert_eq!(history.len(), 1);
93/// ```
94///
95/// Works with any cloneable type:
96/// ```
97/// use thanos_sort::thanos_sort;
98///
99/// let mut strings = vec!["thanos".to_string(), "sort".to_string(), "is".to_string(), "balanced".to_string()];
100/// let history = thanos_sort(&mut strings);
101///
102/// assert_eq!(strings.len(), 1);
103/// assert_eq!(history.len(), 3); // 4 -> 2 -> 1
104/// ```
105pub fn thanos_sort<T>(data: &mut Vec<T>) -> Vec<Vec<T>>
106where
107    T: Clone,
108{
109    let mut history = vec![data.clone()];
110
111    while data.len() > 1 {
112        let keep_count = data.len().div_ceil(2);
113        let mut rng = rand::rng();
114        data.shuffle(&mut rng);
115        data.truncate(keep_count);
116        history.push(data.clone());
117    }
118
119    history
120}
121
122/// Owned version of Thanos sort that preserves the original data.
123///
124/// This function takes a slice and returns both the survivor vector and the history,
125/// leaving the original data untouched. Useful when you need to keep the original
126/// collection for other purposes.
127///
128/// **THIS IS A JOKE. DO NOT USE FOR REAL SORTING.**
129///
130/// # Arguments
131///
132/// * `data` - A slice of `T` to be "sorted"
133///
134/// # Returns
135///
136/// * `(Vec<T>, Vec<Vec<T>>)` - A tuple containing:
137///   * The survivor vector (single element or empty)
138///   * History of all intermediate states
139///
140/// # Examples
141///
142/// Basic usage:
143/// ```
144/// use thanos_sort::thanos_sort_owned;
145///
146/// let original = vec![10, 20, 30, 40, 50];
147/// let (survivor, history) = thanos_sort_owned(&original);
148///
149/// // Original is preserved
150/// assert_eq!(original, vec![10, 20, 30, 40, 50]);
151/// // Survivor is the result
152/// assert_eq!(survivor.len(), 1);
153/// // History tracks all snaps
154/// assert_eq!(history.len(), 4); // 5 -> 3 -> 2 -> 1
155/// ```
156///
157/// Empty slice:
158/// ```
159/// use thanos_sort::thanos_sort_owned;
160///
161/// let empty: &[i32] = &[];
162/// let (survivor, history) = thanos_sort_owned(empty);
163///
164/// assert!(survivor.is_empty());
165/// assert_eq!(history.len(), 1);
166/// assert!(history[0].is_empty());
167/// ```
168///
169/// Single element:
170/// ```
171/// use thanos_sort::thanos_sort_owned;
172///
173/// let (survivor, history) = thanos_sort_owned(&[99]);
174///
175/// assert_eq!(survivor, vec![99]);
176/// assert_eq!(history.len(), 1);
177/// ```
178///
179/// Works with custom types:
180/// ```
181/// use thanos_sort::thanos_sort_owned;
182///
183/// #[derive(Debug, Clone, PartialEq)]
184/// struct Titan {
185///     name: String,
186///     power: u32,
187/// }
188///
189/// let titans = vec![
190///     Titan { name: "Thanos".into(), power: 100 },
191///     Titan { name: "Star Lord".into(), power: 50 },
192///     Titan { name: "Gamora".into(), power: 75 },
193/// ];
194///
195/// let (survivor, history) = thanos_sort_owned(&titans);
196///
197/// assert_eq!(survivor.len(), 1);
198/// assert_eq!(history.len(), 3); // 3 -> 2 -> 1
199/// assert_eq!(titans.len(), 3); // Original unchanged
200/// ```
201pub fn thanos_sort_owned<T: Clone>(data: &[T]) -> (Vec<T>, Vec<Vec<T>>) {
202    let mut data = data.to_vec();
203    let history = thanos_sort(&mut data);
204    (data, history)
205}
206
207#[cfg(test)]
208mod tests {
209    use super::*;
210
211    #[test]
212    fn test_even_length() {
213        let mut data = vec![1, 2, 3, 4];
214        let history = thanos_sort(&mut data);
215        assert_eq!(data.len(), 1);
216        assert_eq!(history[0].len(), 4);
217        assert_eq!(history[1].len(), 2);
218    }
219
220    #[test]
221    fn test_odd_length() {
222        let mut data = vec![1, 2, 3];
223        let history = thanos_sort(&mut data);
224        assert_eq!(data.len(), 1);
225        assert_eq!(history[0].len(), 3);
226        assert_eq!(history[1].len(), 2);
227        assert_eq!(history[2].len(), 1);
228    }
229
230    #[test]
231    fn test_single_element() {
232        let mut data = vec![42];
233        let history = thanos_sort(&mut data);
234        assert_eq!(data, vec![42]);
235        assert_eq!(history.len(), 1);
236    }
237
238    #[test]
239    fn test_empty() {
240        let mut data: Vec<i32> = vec![];
241        let history = thanos_sort(&mut data);
242        assert!(data.is_empty());
243        assert_eq!(history.len(), 1);
244        assert!(history[0].is_empty());
245    }
246
247    #[test]
248    fn test_snap_counts() {
249        let test_cases = vec![
250            (1, vec![1]),
251            (2, vec![2, 1]),
252            (3, vec![3, 2, 1]),
253            (4, vec![4, 2, 1]),
254            (5, vec![5, 3, 2, 1]),
255            (6, vec![6, 3, 2, 1]),
256            (7, vec![7, 4, 2, 1]),
257            (8, vec![8, 4, 2, 1]),
258        ];
259
260        for (start_len, expected_lengths) in test_cases {
261            let mut data: Vec<i32> = vec![0; start_len];
262            let history = thanos_sort(&mut data);
263            let actual_lengths: Vec<usize> = history.iter().map(|v| v.len()).collect();
264            assert_eq!(
265                actual_lengths, expected_lengths,
266                "Failed for length {}: expected {:?}, got {:?}",
267                start_len, expected_lengths, actual_lengths
268            );
269        }
270    }
271
272    #[test]
273    fn test_owned_version_preserves_original() {
274        let original = vec![1, 2, 3, 4, 5];
275        let (survivor, history) = thanos_sort_owned(&original);
276
277        assert_eq!(original.len(), 5);
278        assert_eq!(survivor.len(), 1);
279        assert_eq!(history.len(), 4);
280    }
281
282    #[test]
283    fn test_with_strings() {
284        let mut data = vec!["a".to_string(), "b".to_string(), "c".to_string()];
285        let _history = thanos_sort(&mut data);
286        assert_eq!(data.len(), 1);
287    }
288}