【问题标题】:How to split list in evenly random chunks?如何将列表分成均匀随机的块?
【发布时间】:2017-10-11 11:04:45
【问题描述】:
sizes :: StdGen -> Int -> Int -> [Int]
sizes g c 0 = []
sizes g c b = a : (sizes g' (c - a) (b - 1)) where
    (a, g') = randomR (1, c - b) g   

main = do
    g <- newStdGen
    print $ sizes g 100 10

我已经把这个问题归结为生成随机数列表的问题,这些随机数总和为某个数字。

这段代码基本上可以工作,但数字似乎分布不均(例如[7,46,3,4,26,8,1,2,1,1])。

它们往往一开始就很大,然后最终变得更小。从代码中可以看出原因。

我想要的是像[8, 6, 10, 4, 15..] 这样的数字彼此之间并没有那么不同。

【问题讨论】:

  • 我还不完全清楚你在问什么。让我提出一些你可能会问的事情,看看你的想法。您可能要求从给定数量和给定大小的partitions 集合中随机均匀地绘制。或者您可能会要求从一组方法中随机均匀地绘制,以将给定数量的(未标记的)球放入给定数量的(标记的)盒子中。 (...或其他三种变体,其他选择标记/未标记的盒子和球。)
  • 请参阅stackoverflow.com/a/31814348/2166798 以获得可能的答案。实现是 Python,但算法很简单。
  • (想一想,可能从分区中均匀选择与从将未标记的球放入未标记的盒子的方式中均匀选择相同,直到对参数进行一些重新调整。)
  • @pjs 是的,这就是我想要的。你能解释一下为什么差异加起来是n吗?
  • @user1685095 因为范围[0,n]的总长度是n,区别就像棍子(或绳子,或尺子)的长度,放在末端时会跨越整个范围- 到结束。

标签: haskell random


【解决方案1】:

我不太清楚你想做什么,但如果你想在最小值和最大值之间均匀分布,你可以使用randomRs

Prelude> :m +System.Random
Prelude System.Random> g <- newStdGen
Prelude System.Random> take 10 $ randomRs (10, 100) g
[48,93,21,50,84,57,25,80,68,18]

如果你想让这些随机数和一个特定的数字相加,你基本上可以从左边开始挑选,直到你足够接近。 inits 函数可以帮助您:

Prelude System.Random> :m +Data.List
Prelude System.Random Data.List> take 10 $ inits $ randomRs (10, 100) g
[[],[48],[48,93],[48,93,21],[48,93,21,50],[48,93,21,50,84],[48,93,21,50,84,57],
[48,93,21,50,84,57,25],[48,93,21,50,84,57,25,80],[48,93,21,50,84,57,25,80,68]]

代替take 10,您可以开始浏览此列表列表,直到找到足够接近的列表。例如,您可以计算所有这些列表的总和:

Prelude System.Random Data.List> fmap sum $ take 10 $ inits $ randomRs (10, 100) g
[0,48,141,162,212,296,353,378,458,526]

因此,如果您的目标是 500,您可以看到第九个和是 458,而第十个和太高了。换句话说,前九个数字会让您达到 458。您将如何达到 500?

一种选择是简单地说最后一个数字必须是 500 - 458 = 42,但我不确定分布是否不再是完全均匀的,因为最后一个数字是确定性的。

另一种选择是继续生成随机数,直到你有一个完美匹配的序列。

由于我不知道确切的要求,我无法建议哪种方式最好。

在上面的例子中,我用fmap sum 来说明我的观点。这样做的问题是,这样做会丢弃产生总和的数字。据我了解,您实际上想要这些数字,因此您可能需要一个更复杂的左折叠来计算总和,同时仍然记住产生它的数字。为此,您可以使用foldlfoldl'

【讨论】:

  • 我想要的是这个问题的第二个答案stackoverflow.com/questions/2640053/… 适合使用整数而不是浮点数。
  • 我不知道怎样才能让这个更清楚producing list of random numbers that sums up into some number。例如,假设我有一个数字 10,我需要三个整数来总结这个数字 [3, 3, 4]
  • 很抱歉,这是一个非常糟糕的解决方案。即使容量长度为100,也需要花费大量时间来计算。我的链接中的解决方案要好得多。你能帮助它适应haskell和整数吗?我考虑将浮点数拆分为整数和小数部分,然后它们以某种方式分配这些小数部分,以便结果总和等于给定数字。
猜你喜欢
  • 1970-01-01
  • 2021-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-07
  • 2011-03-02
  • 2020-11-05
  • 1970-01-01
相关资源
最近更新 更多