Scheme 球拍随机列表参考函数

Scheme 球拍随机列表参考函数,scheme,racket,Scheme,Racket,定义一个函数,该函数接受一个非空列表,并返回随机选择的、概率相等的列表元素。(不要使用内置的列表参考程序。) 我被困在这上面了。我觉得您需要计算函数递归运行的次数,并将其与您得到的随机数进行比较,但我不知道如何在BSL+中做到这一点。任何帮助都会非常好。我将关于不使用列表引用的评论作为递归思考问题的方向 假设“等概率”不考虑基于软件的原始RNG的缺陷 请注意,我们在函数定义中使用,表示除非指定,否则步骤的(默认)值为((length lst))。这意味着它最初会随机进入列表 #lang rack

定义一个函数,该函数接受一个非空列表,并返回随机选择的、概率相等的列表元素。(不要使用内置的列表参考程序。)


我被困在这上面了。我觉得您需要计算函数递归运行的次数,并将其与您得到的随机数进行比较,但我不知道如何在BSL+中做到这一点。任何帮助都会非常好。

我将关于不使用列表引用的评论作为递归思考问题的方向

假设“等概率”不考虑基于软件的原始RNG的缺陷

请注意,我们在函数定义中使用,表示除非指定,否则步骤的(默认)值为((length lst))。这意味着它最初会随机进入列表

#lang racket

(define (random-element lst [steps (random (length lst))])
  (if (= steps 0)
      (first lst)
      (random-element (rest lst)
                      (sub1 steps))))
由于步骤是内部指定的(如(sub1步骤),从步骤中减去一个),因此它将始终具有显式值,除非函数是这样应用的:

(random-element '(42 1337 128 256))
; 256

这里有一个解决方案。为了让球滚动,选择列表的第一个元素作为要返回的候选元素。然后,对于列表中剩余元素的每个元素,我们随机选择是否替换候选元素

例如:对于包含两个元素(AB)的列表,首先选择元素“a”。 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)))]))

如果你想用谷歌搜索这个理论,这种类型的算法属于“采样算法”。

这很好,但是[]符号在BSL+中不运行。(random element lst)只能有一个变量lst,所以我假设你需要一个helper函数设置为random probability,但是为了让程序工作,你需要从helper函数中选择sub1并返回(random element(rest lst)),但是Racket编程只允许你返回一件事,而不是两件事。实际上,你可以在的帮助下归还一些东西。这是有效的,但我不知道为什么。为什么选择(random(k+1))而不是(+1(random(length xs)))?(length xs)花费的时间与列表的长度成比例。如果您在一个列表中运行并保持调用长度(在较短和较短的列表中),您的算法将花费时间O(n+(n-1)+(n-2)+…+1)=O(n^2)。在k+1上使用random将是O(1)。好的,这是有意义的。我认为有一种方法可以一次性获取长度并将其设置为默认值,而不是在递归中每次都运行它。如果这是唯一的问题,您可以使用GoNZoo的解决方案。试着用三个元素的列表来模拟这个算法,看看为什么1/(k+1)是有效的。你试过什么代码?