aboutsummaryrefslogtreecommitdiff
path: root/src/util.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.rs')
-rw-r--r--src/util.rs79
1 files changed, 79 insertions, 0 deletions
diff --git a/src/util.rs b/src/util.rs
index 0a3de227..aa382560 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -1,3 +1,5 @@
+use std::iter::Iterator;
+
/// Threading utilities
pub mod thread {
/// Like `thread::spawn`, but with a `name` argument
@@ -10,3 +12,80 @@ pub mod thread {
::std::thread::Builder::new().name(name.into()).spawn(f).expect("thread spawn works")
}
}
+
+/// Types that can have their elements rotated
+pub trait Rotate {
+ fn rotate(&mut self, positions: isize);
+}
+
+impl<T> Rotate for [T] {
+ fn rotate(&mut self, positions: isize) {
+ // length is needed over and over
+ let len = self.len();
+
+ // Enforce positions in [0, len) and treat negative rotations as a
+ // posititive rotation of len - positions.
+ let positions = if positions > 0 {
+ positions as usize % len
+ } else {
+ len - (-positions as usize) % len
+ };
+
+ // If positions is 0 or the entire slice, it's a noop.
+ if positions == 0 || positions == len {
+ return;
+ }
+
+ self[..positions].reverse();
+ self[positions..].reverse();
+ self.reverse();
+ }
+}
+
+
+#[cfg(test)]
+mod tests {
+ use super::Rotate;
+
+ #[test]
+ fn rotate_forwards_works() {
+ let s = &mut [1, 2, 3, 4, 5];
+ s.rotate(1);
+ assert_eq!(&[2, 3, 4, 5, 1], s);
+ }
+
+ #[test]
+ fn rotate_backwards_works() {
+ let s = &mut [1, 2, 3, 4, 5];
+ s.rotate(-1);
+ assert_eq!(&[5, 1, 2, 3, 4], s);
+ }
+
+ #[test]
+ fn rotate_multiple_forwards() {
+ let s = &mut [1, 2, 3, 4, 5, 6, 7];
+ s.rotate(2);
+ assert_eq!(&[3, 4, 5, 6, 7, 1, 2], s);
+ }
+
+ #[test]
+ fn rotate_multiple_backwards() {
+ let s = &mut [1, 2, 3, 4, 5];
+ s.rotate(-3);
+ assert_eq!(&[3, 4, 5, 1, 2], s);
+ }
+
+ #[test]
+ fn rotate_forwards_overflow() {
+ let s = &mut [1, 2, 3, 4, 5];
+ s.rotate(6);
+ assert_eq!(&[2, 3, 4, 5, 1], s);
+ }
+
+ #[test]
+ fn rotate_backwards_overflow() {
+ let s = &mut [1, 2, 3, 4, 5];
+ s.rotate(-6);
+ assert_eq!(&[5, 1, 2, 3, 4], s);
+ }
+}