Rebol3 Code Examplex
Knuth shuffle
Randomly permute a sequence using the Fisher-Yates method.
Rebol [
title: "Rosetta code: Knuth shuffle"
file: %Knuth_shuffle.r3
url: https://rosettacode.org/wiki/Knuth_shuffle
]
fisher-yates: func [
"Fisher-Yates shuffle algorithm - randomly shuffles elements in a block"
;Uses the modern variant that works backwards through the array
data [block!] "Input block to shuffle"
/local i j tmp ;; Local variables: i=current index, j=random index, tmp=swap variable
][
;; Make a copy of the input block and get its length
;; This prevents modification of the original block
i: length? data: copy data
;; Loop from the last element down to the second element
;; We stop at 1 because there's no need to swap the first element with itself
while [i > 1] [
;; Generate random index j from 1 to i (inclusive)
j: random i
;; Previous version tried to avoid self-swap as an optimization
;; but actually it is faster to avoid it!
;; Three-step swap using path notation for direct block access
;; Step 1: Store element at random position j in temporary variable
tmp: data/:j
;; Step 2: Move current element (at position i) to random position j
data/:j: data/:i
;; Step 3: Move stored element to current position i
;; Using :tmp to get the value (word evaluation)
data/:i: :tmp
;; Move to previous element (working backwards through the block)
i: i - 1
]
;; Return the shuffled block
data
]
random/seed 0 ;; to get consistent results
probe fisher-yates []
probe fisher-yates [10]
probe fisher-yates [10 20]
probe fisher-yates [10 20 30]