将 n 分成 x 个随机部分。

我需要实现的基本上是将 x 个骰子的点数相加得到 n,但是是反过来的。

让我们创建一个例子:

必须丢 5 次骰子(最小总和为 5,最大总和为 30),也就是说:

x = 5

假设在这种情况下,掷出的总数为 23,也就是说:

n = 23

我需要的是获取任意可能的单个骰子的点数组合(例如 6、4、5、3、5)

目前我能想到的方法是:

  1. 创建 5 个随机数。
  2. 将它们相加并得到总和。
  3. 现在将每个随机数除以总和并乘以想要的数字 23。
  4. 结果是 5 个等于想要的数字 23 的随机数。

问题是这个公式返回随机值(小数、小于 1 或大于 6 的值),具体取决于随机数。我找不到一种方法来编辑公式,以仅返回整数 >= 1 或 <= 6。

点赞
用户1895684
用户1895684

如果您不需要大幅度扩展它,最简单的方法是重新随机化,直到您得到正确的总和。在任何现代 CPU 上只需要几毫秒。不太美观。

#!/usr/local/bin/lua

math.randomseed(os.time())

function divs(n,x)
  local a = {}

  repeat
    local s = 0
    for i=1,x do
      a[i] = math.random(6)
      s = s + a[i]
    end
  until s==n

  return a
end

a = divs(23,5)
for k,v in pairs(a) do print(k,v) end
2014-10-13 02:05:53
用户312586
用户312586

这是一个有趣的问题。以下是我的解决方案:

编辑:我错过了您需要它们是骰子掷出的事实。以下是一个新方案。作为奖励,您可以使用可选参数指定骰子的面数。

local function getDiceRolls(n, num_rolls, num_sides)
  num_sides = num_sides or 6
  assert(n >= num_rolls, "n 必须大于等于 num_rolls")
  assert(n <= num_rolls * num_sides, "n 太大了,超过了骰子的数量和面数")

  local rolls = {}
  for i=1, num_rolls do rolls[i] = 1 end

  for i=num_rolls+1, n do
    local index = math.random(1,num_rolls)
    while rolls[index] == num_sides do
      index = (index % num_rolls) + 1
    end
    rolls[index] = rolls[index] + 1
  end

  return rolls
end

-- 测试:

print(unpack(getDiceRolls(21, 4))) -- 6 4 6 5
print(unpack(getDiceRolls(21, 4))) -- 5 5 6 5
print(unpack(getDiceRolls(13, 3))) -- 4 3 6
print(unpack(getDiceRolls(13, 3))) -- 5 5 3
print(unpack(getDiceRolls(30, 3, 20))) -- 9 10 11
print(unpack(getDiceRolls(7, 7)))  -- 1 1 1 1 1 1 1
print(unpack(getDiceRolls(7, 8)))  -- 出错
print(unpack(getDiceRolls(13, 2)))  -- 出错
2014-10-13 17:03:21
用户869951
用户869951

如果投掷的次数不发生太大变化,但总和发生变化,则值得为给定总和的组合创建查找表。您会生成每个组合,并为每个组合计算总和,然后将组合添加到与该总和相关联的列表中。查找表将如下所示:

T = {12 = {{1,2,3,4,2},{2,5,3,1,1},{2,2,2,3,3}, ...}, 13=....}

然后,当您想要为n = 23随机选择一个组合时,您在表中查找关键字23,列表中有所有具有该总和的组合,现在只需随机选择其中之一。对于任何其他数字也是一样。

2014-10-16 03:28:03