球拍随机列表 - 参考功能

时间:2015-03-01 04:42:30

标签: scheme racket

  

定义一个采用非空列表的函数,并以相等的概率返回随机选择的列表元素。 (不要使用内置的list-ref过程。)

我坚持这个。我觉得你需要计算函数递归运行的次数,并将它与你得到的随机数进行比较,但我不知道如何在BSL +中这样做。任何帮助都会非常棒。

2 个答案:

答案 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