Skip to content

Commit 8fae0cf

Browse files
committed
Add riffle_shuffle
1 parent 4553dc3 commit 8fae0cf

File tree

2 files changed

+53
-2
lines changed

2 files changed

+53
-2
lines changed

packages/std/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ mod mock;
5959
#[cfg(not(target_arch = "wasm32"))]
6060
pub mod testing {
6161
pub use crate::mock::{
62-
mock_dependencies, mock_dependencies_with_balances, mock_env, BankQuerier, MockApi,
63-
MockQuerier, MockQuerierCustomHandlerResult, MockStorage, StakingQuerier,
62+
mock_dependencies, mock_dependencies_with_balances, mock_env, riffle_shuffle, BankQuerier,
63+
MockApi, MockQuerier, MockQuerierCustomHandlerResult, MockStorage, StakingQuerier,
6464
MOCK_CONTRACT_ADDR,
6565
};
6666
}

packages/std/src/mock.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,25 @@ impl StakingQuerier {
343343
}
344344
}
345345

346+
/// Performs a perfect shuffle (in shuffle)
347+
///
348+
/// https://en.wikipedia.org/wiki/Riffle_shuffle_permutation#Perfect_shuffles
349+
/// https://en.wikipedia.org/wiki/In_shuffle
350+
pub fn riffle_shuffle<T: Clone>(input: &[T]) -> Vec<T> {
351+
assert!(
352+
input.len() % 2 == 0,
353+
"Method only defined for even number of elements"
354+
);
355+
let mid = input.len() / 2;
356+
let (left, right) = input.split_at(mid);
357+
let mut out = Vec::<T>::with_capacity(input.len());
358+
for i in 0..mid {
359+
out.push(right[i].clone());
360+
out.push(left[i].clone());
361+
}
362+
out
363+
}
364+
346365
#[cfg(test)]
347366
mod test {
348367
use super::*;
@@ -610,4 +629,36 @@ mod test {
610629
let dels = get_delegator(&staking, user_c.clone(), val2.clone());
611630
assert_eq!(dels, Some(del2c.clone()));
612631
}
632+
633+
#[test]
634+
fn riffle_shuffle_works() {
635+
// Example from https://en.wikipedia.org/wiki/In_shuffle
636+
let start = [0xA, 0x2, 0x3, 0x4, 0x5, 0x6];
637+
let round1 = riffle_shuffle(&start);
638+
assert_eq!(round1, [0x4, 0xA, 0x5, 0x2, 0x6, 0x3]);
639+
let round2 = riffle_shuffle(&round1);
640+
assert_eq!(round2, [0x2, 0x4, 0x6, 0xA, 0x3, 0x5]);
641+
let round3 = riffle_shuffle(&round2);
642+
assert_eq!(round3, start);
643+
644+
// For 14 elements, the original order is restored after 4 executions
645+
// See https://en.wikipedia.org/wiki/In_shuffle#Mathematics and https://oeis.org/A002326
646+
let original = [12, 33, 76, 576, 0, 44, 1, 14, 78, 99, 871212, -7, 2, -1];
647+
let mut result = Vec::from(original);
648+
for _ in 0..4 {
649+
result = riffle_shuffle(&result);
650+
}
651+
assert_eq!(result, original);
652+
653+
// For 24 elements, the original order is restored after 20 executions
654+
let original = [
655+
7, 4, 2, 4656, 23, 45, 23, 1, 12, 76, 576, 0, 12, 1, 14, 78, 99, 12, 1212, 444, 31,
656+
111, 424, 34,
657+
];
658+
let mut result = Vec::from(original);
659+
for _ in 0..20 {
660+
result = riffle_shuffle(&result);
661+
}
662+
assert_eq!(result, original);
663+
}
613664
}

0 commit comments

Comments
 (0)