最近又開始用 CL 重写麻將遊戲了⋯⋯
想搞个洗牌算法。
目前用的是从 Code Golf 抄的 i{⊃a[⍺⍵]←a[⍵⍺]}¨?i←⌽⍳⍴a←⎕
a←⎕ ⍝ evaluated input, assign to "a"
⍴a ⍝ length
⍳⍴a ⍝ 1 2 .. length
⌽⍳⍴a ⍝ length .. 2 1
i← ⍝ assign to "i"
?i ⍝ random choices: (1..length)(1..length-1)..(1 2)(1)
i{ }¨?i ⍝ for each index ⍺ and corresponding random choice ⍵
a[⍺⍵]←a[⍵⍺] ⍝ swap a[⍺] and a[⍵]
← ⍝ in Dyalog, assignment returns its right-hand side
⊃ ⍝ first element, i.e. a[⍵]
⍝ the result from {} is an array of all those a[⍵]
用 CL21 写起來是这樣的
(defun generate-random-array (length)
(let (a)
(setf a #())
(loop for i from 1 to length
do (push i a))
(nreverse (map #'random a))))
(defun shuffle (array)
(let* ((arr array)
(leng (length array))
(rand (generate-random-array leng)))
(loop for i from 0 to (1- leng)
do (rotatef (aref arr i) (aref arr (elt rand i))))
arr))
(shuffle #(1 2 3 4 5 6 7 8 9))
;;=> #(1 7 3 6 9 4 2 5 8)
Elisp 版
(defun random-array (length)
(let (a)
(cl-loop for i from 1 to length
do (push i a))
(setq a (vconcat a))
(map 'vector #'random a)))
(defun shuffle (array)
(let* ((leng (length array))
(rand (random-array leng)))
(cl-loop for i from 0 to (1- leng)
do (cl-rotatef (aref array i) (aref array (elt rand i))))
array))
(shuffle [1 2 3 4 5 6 7])
;; => [7 2 1 5 3 6 4]