From d9bb742c4917b707b2477b281c9ff1f0f948d475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8B=B9=E6=9E=9C=E5=96=B5=E5=96=B5?= <149125378+PingGuoMiaoMiao@users.noreply.github.com> Date: Mon, 14 Jul 2025 07:31:18 +0000 Subject: [PATCH 1/2] Please enter the commit message for your changes. Lines starting with '#' will be ignored, and an empty message aborts the commit. On branch shuffle-implement Your branch is up to date with 'origin/shuffle-implement'. Changes to be committed: modified: deque/deque.mbt modified: deque/deque.mbti modified: deque/deque_test.mbt --- deque/deque.mbt | 41 +++++++++++++++++++++++++++++++++++++++++ deque/deque.mbti | 2 ++ deque/deque_test.mbt | 27 +++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/deque/deque.mbt b/deque/deque.mbt index 7973f9270..240eb87e7 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1588,3 +1588,44 @@ pub impl[A : Compare] Compare for T[A] with compare(self, other) { } 0 } + +///| +/// Shuffle the deque in place using Knuth shuffle (Fisher-Yates algorithm) +/// +/// To use this function, you need to provide a rand function, which takes an integer as its upper bound +/// and returns an integer. +/// *rand n* is expected to return a uniformly distributed integer between 0 and n - 1 +/// +/// # Note +/// This function handles the circular buffer nature of the deque internally. +pub fn[A] T::shuffle_in_place(self : T[A], rand~ : (Int) -> Int) -> Unit { + let n = self.len + let buf_length = self.buf.length() + for i = n - 1; i > 0; i = i - 1 { + let j = rand(i + 1) + // Calculate circular buffer positions + let i_pos = (self.head + i) % buf_length + let j_pos = (self.head + j) % buf_length + // Swap elements + let tmp = self.buf[i_pos] + self.buf[i_pos] = self.buf[j_pos] + self.buf[j_pos] = tmp + } +} + +///| +/// Shuffle the deque using Knuth shuffle (Fisher-Yates algorithm) +/// +/// Returns a new shuffled deque without modifying the original deque. +/// +/// To use this function, you need to provide a rand function, which takes an integer as its upper bound +/// and returns an integer. +/// *rand n* is expected to return a uniformly distributed integer between 0 and n - 1 +pub fn[A] shuffle(self : T[A], rand~ : (Int) -> Int) -> T[A] { + // Create a copy of the original deque + let new_deque = self.copy() + // Shuffle the copy in place + new_deque.shuffle_in_place(rand~) + // Return the shuffled copy + new_deque +} diff --git a/deque/deque.mbti b/deque/deque.mbti index 34a158c84..e3bff93ed 100644 --- a/deque/deque.mbti +++ b/deque/deque.mbti @@ -58,6 +58,8 @@ fn[A] T::rev_iter(Self[A]) -> Iter[A] fn[A] T::rev_iter2(Self[A]) -> Iter2[Int, A] fn[A : Eq] T::search(Self[A], A) -> Int? fn[A] T::shrink_to_fit(Self[A]) -> Unit +fn[A] T::shuffle(Self[A], rand~ : (Int) -> Int) -> Self[A] +fn[A] T::shuffle_in_place(Self[A], rand~ : (Int) -> Int) -> Unit fn[A] T::to_array(Self[A]) -> Array[A] fn[A] T::truncate(Self[A], Int) -> Unit fn[A] T::unsafe_pop_back(Self[A]) -> Unit diff --git a/deque/deque_test.mbt b/deque/deque_test.mbt index d40f4fdb0..192015fe9 100644 --- a/deque/deque_test.mbt +++ b/deque/deque_test.mbt @@ -1164,3 +1164,30 @@ test "deque_compare" { inspect(dq3.compare(dq1), content="-1") inspect(dq1.compare(dq1), content="0") } + +///| +test "shuffle_in_place" { + let original = @deque.of([1, 2, 3, 4, 5, 6, 7]) + let dq = original.copy() + + // Simple deterministic "random" function for testing + fn rand(upper : Int) -> Int { + (upper * 3 + 7) % upper // Deterministic pseudo-random for testing + } + + // Shuffle in place + T::shuffle_in_place(dq, rand~) + + // Verify properties of shuffle: + assert_eq(dq.length(), original.length()) + assert_eq(dq.to_array().sort(), original.to_array().sort()) + assert_true(dq != original) + + // Test non-in-place version + let shuffled = T::shuffle(original, rand~) + assert_eq(shuffled.length(), original.length()) + assert_eq(shuffled.to_array().sort(), original.to_array().sort()) + assert_true(shuffled != original) +} + +///| From 86ac41742c943346189c5892409e2898ac325e53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8B=B9=E6=9E=9C=E5=96=B5=E5=96=B5?= <149125378+PingGuoMiaoMiao@users.noreply.github.com> Date: Mon, 14 Jul 2025 08:32:54 +0000 Subject: [PATCH 2/2] modified: deque/deque_test.mbt --- deque/deque_test.mbt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/deque/deque_test.mbt b/deque/deque_test.mbt index 192015fe9..b2accc9ff 100644 --- a/deque/deque_test.mbt +++ b/deque/deque_test.mbt @@ -1170,9 +1170,9 @@ test "shuffle_in_place" { let original = @deque.of([1, 2, 3, 4, 5, 6, 7]) let dq = original.copy() - // Simple deterministic "random" function for testing + // Better deterministic "random" function for testing fn rand(upper : Int) -> Int { - (upper * 3 + 7) % upper // Deterministic pseudo-random for testing + (upper * 123 + 456) % (upper + 1) // More varied results } // Shuffle in place @@ -1189,5 +1189,3 @@ test "shuffle_in_place" { assert_eq(shuffled.to_array().sort(), original.to_array().sort()) assert_true(shuffled != original) } - -///|