如何在DrRacket中打乱符号列表,使元素位置异于原列表?
实现列表打乱函数(确保与原排列不同)
需求是编写一个Scheme函数,接收包含重复符号的列表(如下方的Deck),返回一个打乱顺序的新列表,且结果必须与原列表排列不一致。
原始Deck定义
(define Deck (list 'symbol1 'symbol1 'symbol2 'symbol2 'symbol3 'symbol3 'symbol4 'symbol4))
实现方案
采用Fisher-Yates洗牌算法实现基础洗牌,再增加校验逻辑确保结果与原列表不同:
; 交换列表指定位置的元素 (define (swap lst i j) (let ((temp (list-ref lst i))) (list-set! (list-set! lst i (list-ref lst j)) j temp) lst)) ; Fisher-Yates洗牌函数(基于原列表副本操作,不修改原数据) (define (shuffle lst) (let loop ((lst (copy-list lst)) (len (length lst))) (if (<= len 1) lst (let ((rand-index (random len))) (loop (swap lst (- len 1) rand-index) (- len 1)))))) ; 生成与原列表不同的打乱结果 (define (shuffle-different original) (let ((shuffled (shuffle original))) (if (equal? shuffled original) (shuffle-different original) shuffled)))
说明
swap函数负责交换列表中两个索引位置的元素,配合copy-list避免修改原始列表。shuffle函数通过Fisher-Yates算法完成公平洗牌,每次随机选取元素与当前末尾元素交换,逐步完成整个列表的打乱。shuffle-different函数会检查洗牌结果是否与原列表完全一致,若一致则重新洗牌,直到生成符合要求的排列。
示例输出
调用 (shuffle-different Deck) 可能得到如下结果(每次运行结果随机,但一定与原Deck不同):
(list 'symbol2 'symbol1 'symbol3 'symbol1 'symbol4 'symbol2 'symbol3 'symbol4)
内容的提问来源于stack exchange,提问作者Nosferatu
相关产品推荐
相关产品推荐

