改变随机发生器的骰子


10

介绍

您将获得具有以下实现的随机整数生成器

  • 第一次调用总是返回1。
  • 第二次调用返回1到2之间的随机整数。
  • 第三次调用返回1到3之间的随机整数。
  • 第n次调用返回1到n之间(包括1和n)的随机整数。

根据上述函数,编写一个完全随机的随机骰子生成器,以相等的概率返回一个介于1到6(含)之间的值。

规则

  • 您的程序/函数应以某种可用的形式(例如,到标准输出或作为函数返回值)得出1到6之间的一个随机整数(包括1和6)。
  • 上面的升序随机数生成器可以定义为程序中的“自由”函数(即不计入字符数),也可以定义为根据需要执行的单独脚本/程序(假定状态(n)是持久性的)通话之间。
  • 假设在您的程序的单个使用案例中,请求的掷骰子次数不会超过1000,并且可以将初始随机数生成器重置为11000掷骰子,以避免溢出n
  • 除了上面定义的升序随机生成器外,您的程序不得使用任何其他随机数源。您当然可以为每个骰子掷骰输出向随机数生成器请求多个随机数。
  • 这是代码高尔夫球,因此如果出现平局,获胜者将是最短答案或最多选票。如果您可以使用少于1000个生成的随机数生成1000个骰子掷骰,请给自己10点效率奖励

./asc-rand
1 # random integer between 1 and 1
./asc-rand
1 # random integer between 1 and 2
./asc-rand
3 # random integer between 1 and 3
./asc-rand
4 # random integer between 1 and 4

# dice-gen generates random dice based on output of asc-rand program.
./dice-gen
3
./dice-gen
6
./dice-gen
5
./dice-gen
1

该程序是否iterate(6):b=asc-rand(); print b非法或不起作用?我可能会误解第三条规则。
beary605

@ beary605:随机数生成器只能在整个1000个骰子掷骰后重置,而不能在每个骰子骰之间重置。我提到的唯一原因是处理随机数生成器返回的值可能出现的溢出并不是此挑战中的关注点之一。编辑:我澄清了规则的目的,希望能有所帮助。
mellamokb 2012年

当您说“随机数”时,您是指“随机整数”还是“随机(截断的)实数”?也许有一些我不知道的约定。
DavidC 2012年

@DavidCarraher:很好。我的意思是随机整数,但我不清楚。我将更新问题。 编辑:更新。
mellamokb

1
我们可以问随机发生器生成随机数多少次吗?我的印象是我们做不到。
马特2012年

Answers:


2

J-13个字符

这与Golfscript做出了相同的假设:骰子的数量在stdin中,我们列出了要掷出的骰子。

r=:1+?  NB. free random function
r>:i.".1!:1]1

爆炸解释:

r=:1+?           NB. r(x) = 1 + a random number between 0 and n-1
           ]1    NB. input file handle
       1!:1      NB. read in a string
     ".          NB. convert to integer
 >:i.            NB. make a list of numbers, from 1 to that integer
r                NB. apply the random function

如果不能令人满意,这里是一个更长的21字符程序,可以调用它f''生成随机数,其中包含状态和所有内容。

r=:1+?  NB. free random function
c=:0
f=:3 :'r c=:1+c'

K个类似物:免费随机函数r:{*1_draw x},stdin版本(10个字符)r'1+!. 0:` ,函数版本(14个字符)c:0;f:{r@c+:1}由调用f[]
algorithmhark

6

Python,31个字符

与scleaver类似,按如下方式定义生成器:

from random import randint
n=0
def r():
    global n;n+=1
    return randint(1,n)

然后一个返回骰子掷骰子的函数:

D=lambda:eval('r(),'*6)[-1]%6+1

D()在需要均匀随机骰子的任何时候致电。


嗯,巧妙地使用eval,我喜欢它。
scleaver

3

斯卡拉23

def s={r;r;r;r;r;r%6+1}

方法r可以这样实现(大约):

var cnt = 0 
val rnd = new util.Random 

def r = {
  cnt %= 1000
  cnt += 1
  rnd.nextInt (cnt)
}

粗略的测试:

scala> (1 to 6).map (i => ((1 to 600) map (_=>s)).filter (_ == i).size)
res26: scala.collection.immutable.IndexedSeq[Int] = Vector(110, 105, 91, 96, 106, 102)

每个第6次调用都应在6个值上产生相等的分布,因此我放弃了5。


2

GolfScript(15个字符)

假设在stdin上提供了所需的卷数,并将许多结果列出到stdout中。

# The free increasing random function
0:N;{N):N rand)}:r;

~{r{;r}5*6%)n}*

在线演示

虽然我可以使用少于1000个字符来生成1000个数字,从而获得10点奖励,但我要花掉10个以上的字符。当N是2或3的幂的倍数时,提取合适的熵的简单方法很短,因为mod 3可用的结果数仅为333 + 111 + 37 + 12 + 4 + 1 =498。因此,有必要采取抽样拒绝的方法。使用这种方法,您可以通过1000次调用来获得预期的2242次滚动r,但簿记base会产生额外的开销,并且函数名非常长。


5
“并且它base是一个很长的函数名”您显然没有使用Mathematica。我们得到这样的奇观NegativeBinomialDistributionExponentialGeneratingFunctionMathieuCharacteristicExponentInverseFourierSequenceTransform,和SemialgebraicComponentInstances。:-)
巫师先生(Mr.Wizard)2012年

1

Python 65 63

i=7
while i>5:[R()for x in range(9)];i=int(`R()`[-1])
print i+1

函数R()是升序随机数。

用法:

$ ./rollDice.py
3
$ ./rollDice.py
5

为什么不摆脱for循环,只Rwhile循环之前调用一次?
基思·兰德尔

@KeithRandall我掷骰子时返回的数字是升序生成器返回的数字的最后一位。我需要对上升生成器进行10次调用,以确保所有可能数字的概率相等。
马特2012年

为什么要打10个电话?原则上,如果生成器是随机的,则每个呼叫是否应为(十个)数字中的任何一个提供相等的概率?当然,实际上,您只能期望每个数字的计数相等。
DavidC 2012年

@DavidCarraher生成器返回从1到n的随机数,其中n是您调用它的次数。我正在查看此返回数字的最后一位。如果n不是10的整数倍,则概率将不一致。例如:如果n = 13,则概率将分解如下:卷1,5,6的1/9和卷2,3,4的2/9
Matt

@Matt:我以为R()是返回浮点数,而您正在获取最低有效位。现在已经弄清楚R()返回整数,这很有意义。
基思·兰德尔

1

Python,56岁

r定义为:

from random import randint
n=0
def r(z):
    global n;n+=1
    return randint(1,n)

骰子生成器d:

import math;d=lambda:math.ceil(6.*r(r(r(r(r(r(0))))))/n)

用法,例如,用于100卷:

for i in range(100):print d()

import math如果替换math.ceil(...)int(...)+1
Matt

我会的,但是它将产生7作为可能的输出。
scleaver

哦耶。我错过了。
马特

mellamokb阐明了我对升序随机化器的疑问。不允许您要求n。
马特

1

Mathematica 51

r通过将全局变量设置n为1 ,可以重置随机数生成器。

n = 1; r[c_] := RandomInteger[{1, c}]

不在运行中以最短的代码...

h := (n++; If[n < 4 \[Or] (y = r@n) > 6 Quotient[n, 6], h, y~Mod~6 + 1])

用法

t = Table[h, {60000}];
n
SortBy[Tally[t], First]

60000卷骰子需要60031次通话hTally以1-6表示细分。

60031

{{1,9923},{2,9966},{3,10016},{4,10028},{5,10009},{6,10058}}


1

Perl,22或45

升序随机数生成器的实现:

my $n=0;
sub r { $n++; return 1+int(rand$n); }

产生:

#copy of the Scala solution; short code; uses 6N rolls
sub s{r;r;r;r;r;1+r%6}
#more efficient implementation, uses approximately 6+N+lnN rolls
sub roll { do{$a=r-1}while($a>$n-$n%6);return 1+(1+$a)%6 }

测试:

n号卡方
1 10001867 0.348569
2 10004853 2.355161
3 9994395 3.141602
4 10000177 0.003133
5 9999227 0.059753
6 9999481 0.026936
电话60000000 5.935154
60000000骰子掷出60000042通话至570.432735秒



0

GolfScript,8个字节

f;3f*f(-

在线尝试!

它一次弹出生成器,然后删除结果。然后滚动f2,并将其乘以3(3或6),然后减去f3-1(0、1、2),得出(3-2、3-1、3-0)或(6-2, 6-1,6-0)W5。

Golfscript和随机函数在发布此问题之前就已存在,因此法律意见书也是存在的。

这是一次只能运行的提交。如果您需要在一次通话中多次运行它,

GolfScript,12个字节

f;3f*f-)0:i;

在线尝试!

这会将您的i呼叫重置为0,因此会相应重置。此TIO显示50个随机结果。


0

C(gcc),31个字节

f(i){for(i=5;i--;)c;i=~-c%6+1;}

每6个通话,产生1到6(含)之间的每个数字的概率相等。

c#define对生成完美随机数的函数的调用。

在线尝试!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.