震动探针的死亡:很多骰子


20

在网络漫画《达斯与机器人》Darths&Droids)中,皮特(Pete)在该漫画所基于的虚构角色扮演活动中扮演R2-D2,曾声称(警告:链接的漫画中潜在的破坏者),他与帕纳斯塔科里亚(Phanastacoria)的失落宝珠一起操纵了他震动探针,他现在可以抛出1048576d4损坏。(通用汽车公司既没有证实也没有否认这一点。)由于应该有明显的理由,几乎没有人会真正有耐心掷出那么多骰子,所以编写一个计算机程序为他掷骰子,并以合理的价格输出掷出的总价值。格式。条目将根据程序大小(最短的程序,字节数,获胜次数),整体语言和每种语言进行排名,并且会中断运行时间。答案可能是完整的程序,也可能是函数定义。

每种语言的分数

腐霉菌

Maltysen-8个字节*

Jakube-10个字节

杀伤人员地雷

Alex A-10个字节

贾姆

优化器-11个字节

Ĵ

--12个字节**

剪辑10

Ypnypn-12个字节**

ķ

JohnE-13个字节

Ti-84 BASIC

SuperJedi224-17字节*

[R

MickyT-23个字节

八度/ MATLAB

Oebele-24个字节

PARI / GP

查尔斯-25个字节**

Wolfram / Mathematica

LegionMammal978-27字节

佩尔

Nutki-29个字节

AsciiThenAnsii-34字节

红宝石

Haegin-32字节**

ConfusedMr_C-51个字节**

准将

标记-37个字节**

的PHP

Ismael Miguel-38个字节

VBA

肖恩·柴郡-40字节**

电源外壳

Nacht-41个字节**

Java脚本

拉尔夫·马歇尔-41字节

edc65-54字节(要求并非所有浏览器都提供ES6功能。)

a

cryptych-51个字节

爪哇

RobAu-52字节**

Geobits-65字节

C

Functino-57字节

蟒蛇

CarpetPython-58个字节

PostgreSQL / SQL

安德鲁-59个字节**

迅速

Skrundz-69个字节

GoatInTheMachine-81个字节

哈斯克尔

Zeta-73个字节**

动作脚本

Brian-75个字节**

> <>

ConfusedMr_C-76字节

Kristoffer Sall-Storgaard-78个字节

C#

布兰登-91字节**

安德鲁-105字节

Ewan-148字节

SuperJedi224-102字节

C ++

Michelfrancis Bustillos-154字节

多重发光

Ismael Miguel(Javascript / ActionScript2)-67个字节


总排名前十

马尔蒂森
亚历克斯·A
雅库比
优化器
/ıʇǝɥʇuʎs/ Ypnypn(顺序不确定)
约翰
超级绝地224
米奇
Oebele

警告标记为*的条目非常慢。

程序标记为**我尚未能够正确测试


等一下,我是否必须给出骰子总和还是列表中的所有骰子?
Maltysen

5
从目前的角度来看,您的问题可能因其不清楚或过于广泛而受到批评。如果您以特定的客观术语描述程序的评分方式以及程序应采用的方法,那将非常有帮助。另外,1048576d4某些用户可能不清楚的标记。准确描述应计算的内容以及必须遵循的任何准则将很有帮助。
BrainSteel

2
这个问题可能做得太快了,无法成为一个好的时间试用。
isaacg 2015年

12
您可以尝试制作堆栈摘要排行榜,而不必手动保持最新的提交清单。
Alex A.

1
我绝对喜欢这个标题。
ASCIIThenANSI

Answers:


10

Pyth- 9 8个字节

使用明显的简单的randint求和方法。花了我几分钟的时间才意识到10485762^20,现在我真的很傻。感谢@Jakube通过指出来节省了我一个字节2^20 = 4^10

smhO4^4T

运行时非常糟糕,它尚未在我的计算机上完成,因此在线运行它毫无意义,因此这里是2^10一个:在此处在线尝试

s        Summation
 m       Map
  h      Incr (accounts for 0-indexed randint)
   O4    Randint 4
  ^4T    Four raised to ten

4
8个字节是可能的。2^20 = 4^10
2015年

@Jakube感谢您的提示:)
Maltysen 2015年

对我来说,这立即完成。
Carcigenicate,2015年

@Carcigenicate您是否在谈论我给的链接?那是修改过的,只求和1024d4
Maltysen

@Maltysen糟糕,抱歉。是的,就是这样。
Carcigenicate,2015年

9

Perl- 48 44 37 39 34字节

$-+=rand(4)+1for(1..2**20);print$-

打印总和,不带尾随换行符。
通过代入2**20(感谢Maltysen)并删除打印前后的引号节省了4个字节。
通过重新排列代码节省了另外7个字节(感谢Thaylon!)
丢失了2个字节,因为我的旧代码生成了0-4(应该是1-4)。
再次感谢Caek和nutki,节省了5个字节。

松散,正确编写的代码:

my $s = 0
$s += int( rand(4) + 1 ) for (1 .. 2**20);
print "$s";

连接计时器有点困难,但是我最终使它工作了。
SuperJedi224 2015年

2
由于我们不在乎警告... $ s + = int rand(5)for(1..2 ** 20); print $ s
Thaylon 2015年

3
int(rand(5))返回范围为0〜4,而D4应为1〜4
nutki

@nutki好,谢谢。我现在已经编辑了。
ASCIIThenANSI

$s+=int rand(4)+1for(1..2**20);print$s删除int括号也对我有用,以节省笔画。
Caek

7

APL,11个10字节

+/?4⍴⍨2*20

这只是需要的2的阵列的总和20 = 1048576个随机整数1和4之间。

+/           ⍝ Reduce by summing a
  ?          ⍝ random integer
   4⍴⍨       ⍝ array with values between 1 and 4
      2*20   ⍝ of length 2^20

您可以通过在前后打印时间戳来在TryAPL上进行基准测试。大约需要0.02秒。

感谢marinus和FUZxxl,节省了一个字节!


一和五???D4一个可以给1,2,3或4。你不能得到5
罗兰Pechtel

@LorenPechtel:对不起,我不好。感谢您指出了这一点。现在已修复。我脑子累了。
Alex A.

保存一个字节:+/?4⍴⍨2*20
marinus

小改进:+/?4⍴⍨2*20改为使用。
FUZxxl 2015年

1
偶然地,这个答案绝不是一成不变的:它将在生产APL代码中以完全相同的方式编写。
FUZxxl 2015年

7

Ti-84 Basic,17个字节

总占用空间-程序头的大小= 17个字节

运行时间:未知,根据较小卷数的性能估计为5-6 小时(因此,基本上不是很好)

Σ(randInt(1,4),A,1,2 ^ 20

1
+1以使其在TI-84上运行。我想时间在这里不是问题,到目前为止,那是30-40年的计算器。
ASCIIThenANSI

我认为有一个函数可以对正态分布进行采样,而不是对均匀分布进行采样?应该快得多。
Ben Voigt 2015年

@BenVoigt:因为这是为了模拟骰子的滚动,所以不适合使用正态分布;它必须是统一的。
Alex A.

2
@AlexA .:中心极限定理规定,许多均匀骰子的总和与正态分布是无法区分的。因此,这取决于我们对“模拟滚动”的学究程度。
Ben Voigt 2015年

1
@MIWright,我认为这只是为了交流。至少我用的是AAA电池。
Arturo TorresSánchez2015年

7

R,32 24 23 21字节

编辑:摆脱了as.integer和使用的整数除法%/%。稍微加快速度。

感谢Alex A提供的示例提示...以及Giuseppe删除了 r=

sum(sample(4,2^20,T))

经过测试

i = s = 0
repeat {
i = i + 1
print(sum(sample(4,2^20,r=T)))
s = s + system.time(sum(sample(4,2^20,r=T)))[3]
if (i == 10) break
}
print (s/10)

产出

[1] 2621936
[1] 2620047
[1] 2621004
[1] 2621783
[1] 2621149
[1] 2619777
[1] 2620428
[1] 2621840
[1] 2621458
[1] 2620680
elapsed 
   0.029 

对于纯速度,以下以毫秒为单位完成。但是我不确定我的逻辑是否正确。结果似乎与随机方法一致。可耻的是更长的长度。

sum(rmultinom(1,2^20,rep(1,4))*1:4)

这是我在机器上执行的计时

system.time(for(i in 1:1000000)sum(rmultinom(1,2^20,rep(1,4))*1:4))
                   user                  system                 elapsed 
7.330000000000040927262 0.000000000000000000000 7.370000000000345607987 

您可以使用sample()代替保存几个字节runif(),即sum(sample(4,2^20,r=T))
Alex A.

刚刚在我的计算机上做了一些基准测试,sample()实际上也更快!
Alex A.

@AlexA。当我靠近电脑时,感谢将进行测试和更改
MickyT 2015年

不要坏掉这个或其他东西,但是您不需要r=T,只是T可以更换。
朱塞佩

1
@Giuseppe,谢谢..这确实是一个古老的
-MickyT

6

Python 2,58个字节

我们从操作系统中获得1048576个随机字符,每个取2位,并将它们相加。使用该os库似乎比使用该random库节省了一些字符。

import os
print sum(1+ord(c)%4 for c in os.urandom(1<<20))

在我的PC上大约需要0.2秒。


6

CJam,12 11个字节

YK#_{4mr+}*

这是很直截了当的:

YK                  e# Y is 2, K is 20
  #                 e# 2 to the power 20
   _                e# Copy this 2 to the power 20. The first one acts as a base value
    {    }*         e# Run this code block 2 to the power 20 times
     4mr            e# Get a random int from 0 to 3. 0 to 3 works because we already have
                    e# 2 to the power 20 as base value for summation.
        +           e# Add it to the current sum (initially 2 to the power 20)

但是,这样做的好处在于它的速度也非常快!在我的机器上(并使用Java编译器)平均需要70毫秒。

网络版需要在我的机器上1.7秒。

更新:DocMax节省了1个字节


在线版本距离此处的计算机大约6秒钟,但这可能只是学校坚持使用的网络和/或Macbook。到家后我会再试一次。
SuperJedi224 2015年

@ SuperJedi224在线版本全部使用JavaScript,不会进行任何网络调用。您可以下载Java版本并按照网站上的说明运行它。
Optimizer

3
除非我遗漏了某些东西(这对我和CJam来说实在是太可惜了),否则不要使用0进行种子设定并为2 ^ 20运行加1,而是使用2 ^ 20进行种子设定以节省1个字节:YK#_{4mr+}*
DocMax 2015年

@DocMax你是对的。谢谢!
Optimizer

+1; 我打算发布这个确切的答案(4A#而不是而不是YK#),但是您击败了我。:)
Ilmari Karonen 2015年

6

JavaScript(ES6),54个字节

平均时间<100毫秒。运行代码片段进行测试(在Firefox中)

// This is the answer
f=t=>(i=>{for(t=i;i--;)t+=Math.random()*4|0})(1<<20)|t

// This is the test
test();

function test(){
  var time = ~new Date;
  var tot = f();
  time -= ~new Date;
  
  Out.innerHTML = "Tot: " + tot + " in msec: " + time + "\n" + Out.innerHTML;
}
<button onclick="test()">Repeat test</button><br>
<pre id=Out></pre>

说明

在没有内置统计包的情况下,在Javascript中,获取一百万个随机数之和的最短方法是调用random()一百万次。这么简单

f=()=>{
   var t = 0, r, i
   for (i=1<<20; i--; ) 
   {
      r = Math.random()*4 // random number between 0 and 3.9999999
      r = r + 1 // range 1 ... 4.999999
      r = r | 0 // truncate to int, so range 1 ... 4
      t = t+r
   }
   return t
}

现在,相加一百万次与添加一百万次完全相同,或者甚至更好,将一百万次加和,然后将其余部分相加:

f=()=>{
   var t, r, i
   for (t = i = 1<<20; i--; ) 
   {
      r = Math.random()*4 // random number between 0 and 3.9999999
      r = r | 0 // truncate to int, so range 0 ... 3
      t = t+r
   }
   return t
}

然后高尔夫,删除临时变量r并删除局部变量的声明。t是一个参数,因为需要使用它来缩短的声明fi是全球性的(坏事)

f=t=>{
   for(t=i=1<<20;i--;) 
      t+=Math.random()*4|0
   return t
}

然后找到使用无名内部函数避免“返回”的方法。副作用是,我们获得了另一个参数,因此没有使用全局变量

f=t=>(
  (i=>{ // start inner function body
     for(t=i;i--;)t=t+Math.random()*4|0 // assign t without returning it
   })(1<<20) // value assigned to parameter i
  | t // the inner function returns 'undefined', binary ored with t gives t again
) // and these open/close bracket can be removed too

在Chrome中不起作用。即将在FF中进行测试。
SuperJedi224 2015年

当然。Chrome是ES5
edc65

1
它具有某些ES6支持(大多数功能只能通过从chrome:\\ flags启用实验性JavaScript来获得),但尚不支持箭头功能
SuperJedi224

5

Perl,29岁

生成所需长度的表。

print~~map{0..rand 4}1..2**20

我在此上遇到语法错误。
SuperJedi224 2015年

这需要足够新的Perl版本(smartmatch运算符是在5.10.1中引入的,我认为默认情况下直到后来它才可用)。
标记

~~这不是智能匹配,只是强制标量上下文的双位反转。一个字符更长的方式是print$x=map...。也许在较新的版本上会由于smartmatch的歧义而发出警告,但它似乎在我的系统上和没有警告的情况下也可以正常工作:ideone.com/LAIWzq
nutki

是的,它可以在IDEone上使用。我给你
SuperJedi224

5

J(12个字节,大约9.8毫秒)

+/>:?4$~2^20

我怀疑这主要是内存带宽限制:我什至无法将其最大化到单个内核...

您可以使用以下代码对此进行测试:

   timeit =: 13 : '(1000 * >./ ($/x) 6!:2"0 1 y)'
   4 20 timeit '+/>:?4$~2^20'
9.90059

它将以20条路径的4组运行,并以最快的组返回平均时间的毫秒数。可以在这里找到翻译。


4

Pyth,10个字节

u+GhO4^4TZ

它比@Maltysen的Pyth解决方案具有更多的字节。但是它可以在我的笔记本电脑上运行8.5秒,而@Maltysen的解决方案在20分钟的运行时间内没有任何解决方案。

但是对于在线编译器而言仍然有些慢。

说明

u     ^4TZ   start with G = 0, for H in 0, ... 4^10-1:
                G = 
 +GhO4              G + (rand_int(4) + 1)
             result is printed implicitly 

今天下午将进行测试。
SuperJedi224'2015-4-30

4

爪哇,65

既然我们按语言列出了分数,为什么不将Java混入其中呢?在这里打高尔夫球的东西并不多,只是一个简单的循环,但我能够从最初的尝试中挤出几对:

int f(){int i=1<<20,s=i;while(i-->0)s+=Math.random()*4;return s;}

今天下午将进行测试。
SuperJedi224'2015-4-30

没问题。在这台(缓慢的)PC上花费大约80毫秒,但我不知道您正在使用什么时间。
Geobits's

我不认为您的程序是正确的模型。在我的测试中,它可以并且确实在某些位置将0加。据我了解,大多数d4是1,2,3,4(不可能有0)。

4
@ user39526 s(总和)从1<<20(卷数)开​​始。这相当于向每个卷添加一个。当随机投0中,翻卷1等
Geobits


4

Matlab,24岁

首次提交!

sum(randi([1,4],1,2^20))

我曾希望使用randi([1,4],1024),该矩阵给出1048576个元素的矩阵,但随后我需要一个双和,它需要更多的字符。

关于问题中提到的运行速度,timeit告诉我运行时间约为0.031秒。因此,几乎是即时的。


我通过八度在线获得0.04到0.05秒。
SuperJedi224

4

Haskell,73个字节

import System.Random
f=fmap sum.(sequence.replicate(2^20))$randomRIO(1,4)

用法:

$ ghci sourcefile.hs
ghci> f
2622130

4

C#:105个字节

using System.Linq;class C{int D(){var a=new System.Random();return new int[1<<20].Sum(i=>a.Next(1,5));}}

很好,即使两次错,我也喜欢。是1 << 20,不是2 << 20。而Random.Next的第二个参数The *exclusive* upper bound of the range是5
edc65

@ edc65感谢您捕获这些错误。我已经更新了答案。
安德鲁

1
通过消除a和移动的new System.Random()内部,您可以节省9个字符Sum。当然,它Random每次都会创建一个新的,但是只要它能提供结果,谁会在乎呢?
LegionMammal978

@ LegionMammal978如果您一次又一次创建一个新的Random,则结果主要是非随机的
edc65

@ edc65这就是为什么我没有走那条路的原因。我没有机会测试如果遵循该建议会发生什么。
安德鲁

4

PHP, 38 37字节

这使用了一个非常简单的想法:将它们全部加起来!

另外,我注意到它104857610000000000000000000二进制形式,等效于1<<20

这是代码:

while($i++<1<<20)$v+=rand(1,4);echo$v

在您的浏览器中进行测试(所做的更改非常小):

$i=$v=0;while($i++<1<<20)$v+=rand(1,4);printf($v);

注释中解释了代码中的所有更改。


您可以删除;之后echo$v
Martijn

@Martijn我把它留在那里,因为大多数时候PHP都在抱怨它。但是我现在已经将其删除。它可以在sandbox.onlinephpfunctions.com上运行,这就足够了。
Ismael Miguel


3

C,57字节

main(a,b){for(b=a=1<<20;a--;b+=rand()%4);printf("%d",b);}

此代码有效...一次。如果您需要再次掷出那些骰子,则需要放入srand(time(0))其中,增加14个字节。


为什么需要添加srand(time(0))?(对不起,我没有使用C。)
ASCIIThenANSI

@ASCIIThenANSI C的许多实现rand都会在每次运行时将其种子化为相同的值。srand播种RNG,并time(0)获取自1970
。– Functino

如果初始化,a=b=1<<20则可以跳过1+,这将节省4个字节。
nutki

此外,int之前main是不需要的。
nutki

提示任何人这样做t=0,然后t=t (...) +1进行1048576次:再想一想!(最终请看我的回答)
edc65

3

PostgreSQL,59个字节

select sum(ceil(random()*4)) from generate_series(1,1<<20);

我承认random()在理论上可以精确地产生零的微小问题,在这种情况下,模头辊将为零。


您真的不需要;终止查询,因为它是唯一的查询
MickyT,2015年

3

Ruby,32个字节

(1..2**20).inject{|x|x-~rand(4)}

以更具可读性的形式:

(1..2**20).inject(0) do |x|
  x + rand(4) + 1
end

它创建从1到1048576的范围,然后在该块上迭代多次。每次执行该块时,前一次迭代的值将作为x(最初为0,默认为inject)。每次迭代都会计算出一个介于0到3(含3)之间的随机数,将其加一,从而模拟d4的滚动并将其加到总数中。

在我的机器上,运行(0.25 real, 0.22 user, 0.02 sys)非常快。

如果您已安装Ruby,则可以使用 ruby -e 'p (1..2**20).inject{|x|x+rand(4)+1}'p以这种方式运行时,有必要查看输出;如果您不关心它,则可以忽略它;或者仅在IRB中运行它,然后将结果打印到屏幕上为了你)。我已经在Ruby 2.1.6上进行了测试。

由于histocrat的位操作黑客替换x + rand(4) + 1x-~rand(4)


1
您能解释一下它是如何工作的吗?
ASCIIThenANSI

我可以找到的第一个在线解释器实际上是想声明rand()方法不存在。我会尝试找到另一个。
SuperJedi224

好吧,我找到了一个可行的。
SuperJedi224

有点动摇hack:x-~rand(4)等同于x+rand(4)+1
histocrat

另外,您也可以替换2**204e10
histocrat

3

PARI / GP,25个字节

确实,这里不需要打高尔夫球-这是在GP中进行计算的直接方法。它在我的机器上运行90毫秒。吊装+1节省了大约20毫秒的时间。

sum(i=1,2^20,random(4)+1)

只是为了好玩:如果要针对PARI的性能进行优化,

inline long sum32d4(void) {
  long n = rand64();
  // Note: __builtin_popcountll could replace hamming_word if using gcc
  return hamming_word(n) + hamming_word(n & 0xAAAAAAAAAAAAAAAALL);
}

long sum1048576d4(void) {
  long total = 0;
  int i;
  for(i=0; i<32768; i++) total += sum32d4();
  return total;
}

总操作数非常少-如果是xorgens每个64位字需要个周期(有人可以验证吗?),那么具有POPCNT的处理器应该只花费大约0.5个周期/位,或者最后几百微秒。数。

在使用相似或更高质量的随机数的方法中,这应该具有接近最佳的最坏情况性能。通过组合案例-一次可能一百万卷-并使用(基本上)算术编码进行选择,应该可以大大提高平均速度。


3

Javascript,55 53 50 47 41字节

for(a=i=1<<20;i--;)a+=(Math.random()*4)|0

我没有意识到非随机数是已知的刺激物,因此我认为应该发布一个真正的解决方案。并不表示不尊重。

注释:如上述其他人所述,您可以通过从答案中的掷骰数开始,跳过每掷+1,而不必写a = 0,i = 1 << 20则节省了两个字节,并且另外2个,因为您没有为每卷添加+1。parseInt函数的功能与Math.floor相同,但要短2个字符。


请注意,此答案与SuperJedi224和@Andrew最初评论的答案完全不同-Ralph
Marshall

您可以同时删除方括号和最后一个分号(并且只能删除最后一个分号),以减少其他字符。此外,目前的版本只有50个字符,而不是52
SuperJedi224

SuperJedi-感谢您的建议。我以为我尝试过不带括号的尝试只是遇到了问题,但也许我遇到了另一个问题。无论如何,我认为这将达到预期的效果。
拉尔夫·马歇尔

a+=parseInt(Math.random()*4)可能缩短为a+=1+Math.random()*4&7。的1+,如果你不在乎它推出0或不只有。
伊斯梅尔·米格尔

您可以将其for(a=i=1<<20;i--;)a+=(Math.random()*4)|0
压缩

2

剪辑10,12字节

r+`m[)r4}#WT

         #4T    .- 4^10 = 1048576             -.
   m[   }       .- that many...               -.
     )r4        .-          ...random numbers -.
r+`             .- sum                        -.

在我的计算机上运行大约需要0.6秒。




2

Commodore Basic,37个字节

1F┌I=1TO2↑20:C=C+INT(R/(1)*4+1):N─:?C

PETSCII替代:= SHIFT+E/= SHIFT+N=SHIFT+O

基于较少骰子运行的估计运行时间:4.25小时。

试图通过C整数来获得两个字节,从而隐含地对随机数进行四舍五入,这很诱人。但是,Commodore Basic中整数的范围是-32678到32767-当中位数答案是2621440时,还不够。



2

Ruby,51个 47个字符

x=[];(2**20).times{x<<rand(4)+1};p x.inject(:+)

在执行此操作之前,我查看了所有答案,然后 sum(2**20 times {randInt(4)})策略确实很困难,所以我使用了它。

> <>,​​76个字符

012a*&>2*&1v
|.!33&^?&:-<
3.v < >-:v >
   vxv1v^<;3
  1234    n+
  >>>> >?!^^

我不知道,如果这一个作品,因为浏览器崩溃了,当我试图测试,但这里的在线翻译。


我会给您+1的> <>答案。
SuperJedi224 2015年

2

迅捷,64字节

没什么聪明的,在Swift中打高尔夫球很难。

func r()->Int{var x=0;for _ in 0..<(2<<19) {x+=Int(arc4random()%4)+1;};return x;}

版本2(为时已晚)

var x=0;for _ in 0..<(2<<19){x+=Int(arc4random()%4)+1;};print(x)

2

Java(Java 8)-52

int f(){return new Random().ints(1<<20,1,5).sum();}
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.