这些骰子是非传递性的吗?


31

非传递性骰子是违反概率论直觉的漂亮小玩具。对于此挑战,我们需要一些定义:

考虑两个骰子一个这是在同一时间抛出。我们说,一个 节拍 ,如果概率一个显示出比数量较多严格小于的概率大于出比大数量的一个

现在考虑一组三个带有标签ABC的骰子。这样的一组骰子被称为非传递,如果

  • 任一节拍节拍ÇÇ节拍
  • Ç节拍节拍节拍Ç

作为我最喜欢的示例之一,请考虑Grime骰子,它具有以下方面:

A: 3 3 3 3 3 6
B: 2 2 2 5 5 5
C: 1 4 4 4 4 4

有趣的是,每个骰子的平均值是3.5,就像常规骰子一样。

可以证明:

  • A以7/12的概率击败B。
  • B以7/12的概率击败C。
  • C以25/36的概率击败A。

现在这些特定的骰子甚至变得更奇怪了。如果我们将每个骰子掷两次,然后将结果相加,那么拍子的顺序就会颠倒:

  • B击败A的可能性为85/144。
  • C以85/144的概率击败B。
  • A击败C的可能性为671/1296。

让我们用此属性Grime-nontransitive调用一组骰子。

另一方面,如果骰子在使用两次抛出时仍保持其原始循环,则将它们称为非传递性强。(如果两次抛出都没有循环,我们可以简单地将它们称为非传递式。)

挑战

给出三个六面的骰子,确定哪些上述性能这组具有,和下面的字符串输出的一个:nonenontransitiveGrime-nontransitivestrongly nontransitive

您可以编写程序或函数,通过STDIN,命令行参数,提示或函数参数接受输入,然后将结果写入STDOUT或以字符串形式返回。

您可以假设所有边都是非负整数。您不能假定边或骰子的顺序特殊。您可以采用任何方便的列表或字符串格式输入。

这是代码高尔夫球,因此最短的答案(以字节为单位)获胜。

测试用例

none
1 2 3 4 5 6, 6 5 4 3 2 1, 1 3 5 2 4 6
1 1 1 6 6 6, 4 4 4 5 5 5, 5 5 5 5 5 5
1 1 2 5 6 6, 2 2 3 4 4 6, 2 3 3 4 4 5
0 1 2 3 4 5, 1 1 2 3 3 5, 1 2 2 2 3 5
3 13 5 7 13 7, 5 7 11 5 7 13, 5 9 13 5 7 9

nontransitive
1 2 2 4 6 6, 1 2 3 5 5 5, 2 3 4 4 4 4
1 4 4 4 4 4, 2 2 2 4 5 6, 2 3 3 3 5 5
1 2 1 6 5 6, 3 1 3 6 2 6, 2 4 2 4 4 5
3 4 6 6 7 7, 4 4 4 7 7 7, 5 5 5 5 6 7
2 5 11 11 14 14, 5 5 5 14 14 14, 8 8 8 8 8 17

Grime-nontransitive
3 3 3 3 3 6, 2 2 2 5 5 5, 1 4 4 4 4 4
1 1 4 5 5 5, 2 2 2 3 6 6, 3 3 3 4 4 4
2 1 4 6 4 4, 2 4 5 2 3 5, 3 3 6 3 3 3
11 11 13 15 15 16, 12 12 12 13 16 16, 13 13 13 14 14 14
4 4 7 16 19 19, 4 7 13 13 13 19, 4 10 10 10 16 19

strongly nontransitive
2 2 2 5 5 5, 2 3 3 3 5 5, 1 1 4 5 5 5
2 2 2 3 6 6, 2 2 2 5 5 5, 2 2 4 4 4 5
1 5 1 3 6 5, 6 6 4 2 2 1, 5 3 4 3 4 2
0 0 2 4 4 5, 0 1 1 3 5 5, 1 1 2 3 4 4
1 1 9 17 17 21, 1 5 5 13 21 21, 5 5 13 13 13 17

如果您想更彻底地测试您的代码,彼得·泰勒(Peter Taylor)很友好,可以编写一个参考实现,该实现将所有〜5000套骰子分类为1到6面,平均值为3.5。粘贴链接


我完全忘记了非传递性骰子。谢谢您:)
npst 2015年

第一个非传递性示例正确吗?1 2 2 4 6 6, 1 2 3 5 5 5, 2 3 4 4 4 4我得到A <B 17/36,B> C 19/36,C <A 16/36。
Tobia 2015年

@Tobia您忘记了抽奖是可能的。您还需要计算每个骰子输给其他骰子的频率,并检查是否小于获胜概率:是A以17/36击败B,但A以16/36输给B,因此A击败B同样,C赢取对A和16/36像你说的,但是C失去对一个只有14/36,所以C击败A.
马丁安德

Answers:


5

Dyalog APL, 107个 100字节

{({+/×+/¨,¨×⍵∘.-¨1⌽⍵}{3≠|a←⍺⍺⍵:1⋄a=b←⍺⍺∘.+⍨¨⍵:2⋄3+a=-b}⍵)⊃(⊂'none'),'strongly '⍬'Grime-',¨⊂'nontransitive'}

{T←{+/×+/¨∊¨×⍵∘.-¨1⌽⍵}⋄3≠|S←T⍵:'none'⋄N←'nontransitive'⋄S=D←T∘.+⍨¨⍵:'strongly ',N⋄S=-D:'Grime-',N⋄N}

(感谢@Tobia这个更简单,更短,更好的解决方案)

基本:

  • 分配

  • 语句分隔符

  • {} 拉姆达形式

  • ⍺⍵ 左右论点

  • A:B守卫(如果A返回B ”)

T是一个函数,如果A击败B,B击败C,C击败A,则返回3;-3如果是相反的情况;和其他之间的东西。详细:

  • 1⌽⍵是的单向旋转。如果为ABC,则轮换为BCA。

  • ∘.-计算两个向量之间的减法表(1 2...10 ∘.× 1 2...10将是我们从学校知道的乘法表)。我们将此应用于的每个(¨)项和中的对应项之间1⌽⍵

  • × 减表中所有数字的符号

  • ∊¨ 展平每张桌子

  • +/¨总结一下 现在,我们有三个代表余额的数字:A对B,B对C,C对A的获胜数减去败诉数。

  • × 这些的信号

  • +/

然后依次处理案例:

  • 3≠|S←T⍵:'none' 如果 T⍵的绝对值不是3,则返回'none'

  • N←'nontransitive' 我们非常需要这个词

  • S=D←T∘.+⍨¨⍵:'strongly ',N计算T骰子对(∘.+⍨¨⍵←→ ⍵((∘.+)¨)⍵),如果ABC之间的相同关系仍然成立,则返回“ strongly ...”

  • S=-D:'Grime-',N the如果关系相反,则为“格蕾姆”

  • N 如果所有其他方法都失败了,则只是“非传递性”


1
你打败我了!我三天前就在解决这个问题,但是后来我停止写我的答案了。无论如何,它与您的都太相似了,所以我将其发布在这里。每100个字符短一点:{T←{+/×+/¨∊¨×⍵∘.-¨1⌽⍵}⋄3≠|S←T⍵:'none'⋄N←'nontransitive'⋄S=D←T∘.+⍨¨⍵:'strongly ',N⋄S=-D:'Grime-',N⋄N}
Tobia

@MartinBüttner:标题中的正确术语是“字符”,因为字节数将根据用于编码APL符号的字符集而变化。传统上,它们只是在ASCII之后的8位字节的高半部分中编码。如今,我们使用UTF-8,但是旧的字符集仍然有用……主要是在打高尔夫球时将字节数减少为字符数!
Tobia 2015年

@Tobia在代码高尔夫中更早地赢得王牌,这样您就赢了!我不太熟悉高尔夫礼节,但我认为您应该将其作为一个单独的答案发布,因为它与众不同,并且您是独立完成的。
ngn

@Tobia我也更喜欢算字符,但是如果隐含经典编码,则bytes =字符,所以也许我们称呼它们并不重要……
ngn 2015年

@Tobia好吧,在按字节计分的挑战中提供字符数绝对没有用。但是,没有人说过我们以UTF-8字节计分。实际上,标签Wiki明确表示可以将不同的现有编码用于ASCII范围之外的字符。而且APL确实有自己的代码页,因此整个字符集都适合一个字节。PPCG的政策是使用此代码页来计算APL-惩罚APL比ASCII更旧是不公平的。
Martin Ender 2015年

13

Python 2,269

这是一个评估函数的漂亮小表达式。它接受三个整数列表。通过所有测试用例。

lambda A,B,C,w=lambda A,B:cmp(sum(cmp(a,b)for a in A for b in B),0),x=lambda A,B:cmp(sum(cmp(a+c,b+d)for a in A for b in B for c in A for d in B),0): (w(A,B)==w(B,C)==w(C,A)!=0)*((x(A,B)==x(B,C)==x(C,A))*["","strongly ","Grime-"][x(A,B)*w(A,B)]+"nontransitive")or"none"

2

的J - 311个 257字节

更新(2015年1月13日):

g=:4 :'(+/,x>/y)>+/,y>/x'
h=:4 :'(,+/~x)g,+/~y'
f=: 3 :0
'a b c'=:y
if. (b g a)*(c g b)*a g c do.
a=.2{y
c=.0{y
end.
'none'([`]@.((a g b)*(b g c)*c g a))((''([`]@.((b h a)*(c h b)*a h c))'Grime-')([`]@.((a h b)*(b h c)*c h a))'strongly '),'nontransitive'
)

说明:使用Gerunds,将if.s 简化为@.s。

旧版本:

首先尝试用J编码和打高尔夫球。

g=:4 :'(+/,x>/y)>+/,y>/x'
h=:4 :'(,+/~x)g,+/~y'
f=: 3 :0
'a b c'=:y
if. (b g a)*(c g b)*a g c do.
a=.2{y
c=.0{y
end.
if. (a g b)*(b g c)*c g a do.
if. (a h b)*(b h c)*c h a do.
'strongly nontransitive'
elseif. (b h a)*(c h b)*a h c do.
'Grime-nontransitive'
elseif. do.
'nontransitive'
end.
else.
'none'
end.
)

使用与以下类似的语法运行它(为清楚起见,请留出空格):

f 3 6 $          1 1 9 17 17 21, 1 5 5 13 21 21, 5 5 13 13 13 17

说明:

g被定义为一个接受两个数组的骰子,它们告诉第一个骰子是否击败了第二个骰子
h被定义为一个接受两个数组的骰子,表明两个骰子是否抛出了两次并求和,第一个骰子是否击败了第二个骰子
f是一个单子,需要一个表,并返回一个字符串与正确答案

编辑:修正了污垢非传递条件下的一个错误(替换,*


我希望有任何改进的建议。:)
Jay Bosamiya

@MartinBüttner,我最初尝试过这种方法,但不知道如何在不增加代码长度的情况下在多行(或句子,如J所知)中串联起来。许多句子变成一个句子,最终也缩短了代码的长度……
Jay Bosamiya 2015年

1

Pyth 129 133

Lmsd^b2Msmsm>bkGHDPNK-ghNeNgeNhNR?^tZ<KZKZAGHmsdCm,PkP,yhkyekm,@Qb@QhbUQ?"none"|!G%G3s[*!+GH"Grime-"*qGH"strongly ""nontransitive

在这里尝试,或者至少可以尝试,但是在线eval似乎不喜欢列表列表:(如果要在此处尝试,请将3个骰子列表手动存储到程序未使用的变量中,然后替换Q该变量的所有实例。初始化示例:

J[[3 3 3 3 3 6)[2 2 2 5 5 5)[1 4 4 4 4 4))

这通过了马丁的所有测试用例,我还没有完全通过彼得的所有用例:P

说明(这将是一个笨拙的)

Lmsd^b2

非常简单,使函数y可以迭代地返回每个笛卡尔值对的和。等效于:def y(b):return map(lambda d:sum(d),product(b,repeats=2))。这用于创建多面模具,以模拟两次将常规模具掷出。

Msmsm>bkGH

定义g2个参数的函数,该函数返回骰子击败另一个骰子的次数。等同于def g(G,H):return sum(map(lambda k:sum(map(lambda b:b>k,G)),H)

DPNK-ghNeNgeNhNR?^tZ<KZKZ

定义一个功能P,该功能将两个骰子的列表作为参数。如果第一个骰子“输”,则返回-1;如果平局,则返回0;如果第一个骰子“输”,则返回1。相当于:

def P(N):
 K=g(N[0],N[-1]) - g(N[-1],N[0])
 return -1**(K<0) if K else 0

AGH受让人的作用就像一个蟒2元组分配。实质上G,H=(result)

msdCm,PkP,yhkyekm,@Qb@QhbUQ

将通过地图向后解释。 m,@Qb@QhbUQ在b = 0..2上进行迭代,并生成2个具有索引b和索引b + 1的骰子。这给了我们骰子(A,B),(B,C),(C,A)(pyth根据列表的长度自动修改索引)。

接下来,m,PkP,yhkyek迭代上一个映射的结果,每个骰子对在每次运行中都存储在k中。返回tuple(P(k),P(tuple(y(k[0]),y(k[-1]))))每个值。归结为`((A拍B ?, 2 * A拍2 * B),(B拍C ?, 2 * B拍..))。

最后,msdC将前一个地图压缩后的值相加。zip会在第一个元组中导致所有单个骰子“拍子”值,而在第二个元组中导致所有双骰子值。

?"none"|!G%G3s[*!+GH"Grime-"*qGH"strongly ""nontransitive

粗略的东西可以打印出结果。如果G为0或不能被3整除,则捕获bot +/- 3((|!G%G3),打印none,否则打印以下列表的总和:[not(G+H)*"Grime",(G==H)*"strongly ","nontransitive"]。对于问题中的定义,我认为布尔值是不言自明的。请注意,此处G不能为零,因为先前的检查已将其捕获。


1

J(204)

时间太长了,如果有一个更有效的系统来挑选正确的弦,可能会打很多球。

f=:3 :'(<,>)/"1+/"2>"1,"2(<,>)/L:0{(,.(1&|.))y'
n=:'nontransitive'
d=:3 :0
if.+/*/a=.f y do.+/*/b=.f<"1>,"2+/L:0{,.~y if.a-:b do.'strongly ',n elseif.a-:-.b do.'Grime-',n elseif.do.n end.else.'none'end.
)

1

Matlab(427)

并不是那么短,我相信它可以打更多的球,我只是想解决这个挑战,因为我认为这是一个非常有趣的任务,所以感谢@MartinBüttner创造了这个挑战!

a=input();b=input();c=input();
m = 'non';l=@(a)ones(numel(a),1)*a;n=@(a,b)sum(sum(l(a)>l(b)'));g=@(a,b)n(a,b)>n(b,a);s=@(a,b,c)sum([g(a,b),g(b,c),g(c,a)]);
x=s(a,b,c);y=s(a,c,b);if x~=3 && y~=3;m=[m,'e'];else m=[m,'transitive'];o=ones(6,1);a=o*a;a=a+a';a=a(:)';b=o*b;b=b+b';b=b(:)';c=o*c;c=c+c';c=c(:)';u=s(a,b,c);
v=s(a,c,b);if u==3|| v==3;if x==3&&u==3 || y==3&&v==3 m=['strongly ',m];else m=['Grime-',m];end;end;end;disp(m);

如果您想尝试了解发生了什么,请在此处提供带有一些注释的完整代码。我包括了一些测试用例,并省略了输入命令:

%nontransitive
% a = [1 2 2 4 6 6];
% b = [1 2 3 5 5 5];
% c = [2 3 4 4 4 4];

%none
% a = [1 2 3 4 5 6];
% b = [6 5 4 3 2 1];
% c = [1 3 5 2 4 6];

%grime nontransitive
% a = [3 3 3 3 3 6];
% b = [2 2 2 5 5 5];
% c = [1 4 4 4 4 4];

%strongly nontransitive
% a = [2 2 2 5 5 5];
% b = [2 3 3 3 5 5];
% c = [1 1 4 5 5 5];

m = 'non';

l=@(a)ones(numel(a),1)*a;
n=@(a,b)sum(sum(l(a)>l(b)'));
%input as row vector, tests whether the left one beats the right one:
g=@(a,b)n(a,b)>n(b,a);
s=@(a,b,c)sum([g(a,b),g(b,c),g(c,a)]);
%if one of those x,y has the value 3, we'll have intransitivity
x=s(a,b,c); 
y=s(a,c,b);
if x~=3 && y~=3 %nontransitive
    m=[m,'e'];
else %transitive
    m=[m,'transitive'];
    o=ones(6,1);
    a=o*a;a=a+a';a=a(:)'; %all possible sums of two elements of a
    b=o*b;b=b+b';b=b(:)';
    c=o*c;c=c+c';c=c(:)';
    u=s(a,b,c);
    v=s(a,c,b);

    %again: is u or v equal to 3 then we have transitivity
    if u==3 || v==3 %grime OR strongly
        % if e.g. x==3 and u==3 then the 'intransitivity' is in the same
        % 'order', that means stronlgy transitive
        if x==3 && u==3 || y==3 && v==3%strongly
            m=['strongly ',m];
        else %grime
            m=['Grime-',m];
        end   
    end
end

disp(m);

如果读取一个数组input()然后将三个元素分配给它,它会更短a,b,c吗?另外,请使用精确的字符串在规范(nonenontransitive,和资本Grime)......或许应该甚至为您节省字节。
马丁·恩德

是的,这可能会更短,我来看看。字符串将恰好是我刚刚删除的disp长版命令中的字符串,它们仅用于测试程序,但最终消息存储在中m。我更正了G
瑕疵的

0

JavaScript-276字节

function(l){r=function(i){return l[i][Math.random()*6|0]};p=q=0;for(i=0;j=(i+1)%3,i<3;++i)for(k=0;k<1e5;++k){p+=(r(i)>r(j))-(r(i)<r(j));q+=(r(i)+r(i)>r(j)+r(j))-(r(i)+r(i)<r(j)+r(j))}alert((a=Math.abs)(p)>5e3?((a(q)>5e3?p*q>0?'strongly ':'Grime-':'')+'nontransitive'):'none')}

我的机率不是很高,因此,为了确保我的成绩,我宁愿只掷骰子数十万次。

该表达式的值等于一个函数,应仅使用一个参数调用该函数:三个整数数组的数组。检查小提琴以能够自己运行代码。

这是非高尔夫版本:

function (diceList) {
    var getRandomValue = function (idDie) {
        return diceList[idDie][Math.floor(Math.random() * 6)];
    };

    var probabilitySimpleThrow = 0;
    var probabilityDoubleThrow = 0;

    for (var idDieA = 0; idDieA < 3; ++idDieA)
    {
        var idDieB = (idDieA + 1) % 3;
        for (var idThrow = 0; idThrow < 1e5; ++idThrow)
        {
            probabilitySimpleThrow += getRandomValue(idDieA) > getRandomValue(idDieB);
            probabilitySimpleThrow -= getRandomValue(idDieA) < getRandomValue(idDieB);

            probabilityDoubleThrow += getRandomValue(idDieA) + getRandomValue(idDieA) > getRandomValue(idDieB) + getRandomValue(idDieB);
            probabilityDoubleThrow -= getRandomValue(idDieA) + getRandomValue(idDieA) < getRandomValue(idDieB) + getRandomValue(idDieB);
        }
    }

    if (Math.abs(probabilitySimpleThrow) > 5e3) {
        if (Math.abs(probabilityDoubleThrow) > 5e3) {
            if (probabilitySimpleThrow * probabilityDoubleThrow > 0) {
                var result = 'strongly ';
            }
            else {
                var result = 'Grime-';
            }
        }
        else {
            var result = '';
        }

        result += 'nontransitive';
    }
    else {
        var result = 'none';
    }

    alert(result);
}

嗯,我认为这并不是挑战的精神。您基本上将其从概率论挑战变成了统计挑战。;)...您可以简单地枚举所有可能的抛出一次,而不是随机抛出。这样可以为您提供准确的结果(并且运行速度会更快)。
马丁·恩德

我将检查这是否导致更简洁的脚本。谢谢你的建议 :)。
Blackhole,2015年
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.