定义一个采用非空列表的函数,并以相等的概率返回随机选择的列表元素。 (不要使用内置的list-ref过程。)
我坚持这个。我觉得你需要计算函数递归运行的次数,并将它与你得到的随机数进行比较,但我不知道如何在BSL +中这样做。任何帮助都会非常棒。
答案 0 :(得分:2)
这是一个解决方案。为了使球滚动,选择列表的第一个元素作为要返回的候选者。然后,对于列表中剩余元素的每个元素,我们随机选择是否要替换候选者。
例如:对于包含两个元素的列表'(a b),首先选择元素' a。 翻转一枚硬币:概率为50%&#b;而是返回。
检查代码以查看算法如何适用于更大的列表:
(define (pick-random xs)
(pick-random/helper (rest xs) (first xs) 1))
(define (pick-random/helper xs chosen k)
(cond
[(empty? xs) chosen]
[else ; with probability 1/(k+1) choose the first element of xs
(if (= (random (+ k 1)) 0)
(pick-random/helper (rest xs) (first xs) (+ k 1))
(pick-random/helper (rest xs) chosen (+ k 1)))]))
如果你想谷歌理论,这种类型的算法属于"采样算法"。
答案 1 :(得分:0)
我接受了关于不使用list-ref作为递归思考问题的方向的评论。
假设“等概率”没有考虑到基于软件的幼稚RNG的缺陷。
请注意,我们在函数定义中使用[]-notation来表示步骤(除非另有说明)的(默认)值为(random(长度为lst)) 。这意味着它最初会有一个随机数量的“步入”列表。
#lang racket
(define (random-element lst [steps (random (length lst))])
(if (= steps 0)
(first lst)
(random-element (rest lst)
(sub1 steps))))
由于步骤是在内部指定的(因为(sub1 steps),从步骤中减去1),它将始终具有显式值,除非应用函数时如下:
(random-element '(42 1337 128 256))
; 256