これらのサイコロは非推移的ですか?


31

非推移的なサイコロは、確率理論の直感に反する素敵な小さなおもちゃです。この課題にはいくつかの定義が必要です。

同時にスローされる2つのサイコロABを考えます。私たちは、と言うAが ビート Bを確率あればAよりも大きな数を示すBは確率よりも厳密に大きいBより大きい数を示すAを

次に、ラベルABCを持つ3つのサイコロのセットを考えます。このようなサイコロのセットは、次の場合に非推移的と呼ばれます。

  • いずれかのAはビートBBはビートC及びCはビートAを
  • または、CBをビートし、BAをビートし、ACをビートします。

私のお気に入りの例の1つとして、次の側面を持つグライムダイスについて考えてみましょう

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

興味深いことに、各ダイスの平均は3.5で、通常のダイスと同じです。

次のことを示すことができます。

  • AはビートBを 7/12の確率で。
  • BはビートCを 7/12の確率で。
  • Cは、ビートAを 25/36の確率で。

今、これらの特定のサイコロはさらに奇妙です。各ダイスを2回振って結果を合計すると、反転するビートの順序は次のようになります。

  • BはビートAを 144分の85の確率で。
  • Cは、ビートBを 144分の85の確率で。
  • AはビートCを 1296分の671の確率で。

このプロパティGrime-nontransitiveでサイコロのセットを呼び出しましょう。

一方、2つのスローを使用するときにサイコロが元のサイクルを保持している場合、それらを非推移的に強く呼び出します。(2つのスローにサイクルがない場合、単に非推移的と呼びます。)

チャレンジ

3六面ダイス、このセットは持っている上記の特性の決定、および以下の文字列の出力1を考えます: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は、サイド1から6、平均3.5のサイコロの最大5000セットを分類するリファレンス実装を作成するのに十分親切でした。ペーストビンリンク


非推移的なサイコロを完全に忘れていました。ありがとう:)
npst

最初の非推移的な例は正しいですか?1 2 2 4 6 6, 1 2 3 5 5 5, 2 3 4 4 4 4A <B 17/36、B> C 19/36、C <A 16/36を取得しています。
トビア

@Tobiaあなたはドローが可能であることを忘れています。また、各サイコロが他のサイコロに対してどのくらいの頻度で負けるかを計算し、それが勝率よりも小さいかどうかを確認する必要があります:はい。あなたが言ったように同様に、Cは16/36でAに対する勝利、しかしCはA.を打つように、Cは、唯一14/36でAに対して失う
マーティン・エンダー

回答:


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」)

TAがBをビートし、BがCをビートし、CがAをビートする場合、3を返す関数です。-3が正反対の場合。それ以外の場合は何か。詳細に:

  • 1⌽⍵は1回転です。場合はABCがあり、回転がBCAです。

  • ∘.-2つのベクトル間の減算テーブルを計算します(1 2...10 ∘.× 1 2...10学校で知っている乗算テーブルになります)。の各¨アイテムとの対応するアイテムの間にこれを適用します1⌽⍵

  • × 減算表のすべての数値の符号

  • ∊¨ 各テーブルを平らにします

  • +/¨そしてそれを合計します。現在、残高を表す3つの数値があります。A対B、B対C、C対Aのそれぞれの勝ち負けのケースの数です。

  • × それらのサイン

  • +/

次に、ケースを順番に処理します。

  • 3≠|S←T⍵:'none'T⍵の絶対値が3でない場合、「なし」を返します

  • N←'nontransitive' 私たちはこの言葉をたくさん必要とします

  • S=D←T∘.+⍨¨⍵:'strongly ',NTサイコロのペアを計算し(∘.+⍨¨⍵←→ ⍵((∘.+)¨)⍵)、ABC間の同じ関係がまだ成立している場合は「強く...」を返します

  • S=-D:'Grime-',N relationships関係が反対方向の場合は「グライム」

  • N 他のすべてが失敗した場合、単に「非推移的」


1
あなたはそれに私を打ち負かした!私は3日前にこの問題に取り組んでいましたが、答えを書く直前にやめました。とにかくあなたのものとあまりにも似ているので、ここに投稿します。100文字では少し短くなります{T←{+/×+/¨∊¨×⍵∘.-¨1⌽⍵}⋄3≠|S←T⍵:'none'⋄N←'nontransitive'⋄S=D←T∘.+⍨¨⍵:'strongly ',N⋄S=-D:'Grime-',N⋄N}
。–トビア

@MartinBüttner:バイトの量はAPLシンボルのエンコードに使用される文字セットによって異なるため、タイトルの正しい用語は「文字」です。従来は、ASCIIの後に8ビットバイトの上半分でエンコードされていました。現在、UTF-8を使用していますが、古い文字セットは依然として有用です。主に、ゴルフの際にバイト数を文字数に減らすために!
トビア

@Tobiaコードゴルフでは、短い方が早く切りますので、勝ちます!私はゴルフのエチケットにあまり精通していませんが、それは実質的に異なっており、あなたが独立して到着したので、別の回答として投稿すべきだと思います。
ngn

@Tobia私はので、多分それは我々がそれらを呼び出す...本当にたいしたない、=文字があまりにも、文字にカウントすることを好むが、古典的なエンコーディングが暗示されている場合、その後、バイト
NGN

@Tobiaまあ、バイト単位でスコアを付けるチャレンジで文字数を提供するのは絶対に役に立ちません。ただし、UTF-8バイトで得点していると言う人はいません。実際、タグwikiは、ASCIIの範囲外の文字に対して異なる既存のエンコーディングを使用できると明示的に述べています。また、APLには独自のコードページがあるため、文字セット全体が1バイトに収まります。PPCGのポリシーは、このコードページを使用してAPLをカウントすることです。APLをASCIIよりも古いものとして罰することはほとんどありません。
マーティンエンダー

13

Python 2、269

以下は、関数に評価される素敵な小さな式です。整数の3つのリストを受け入れます。すべてのテストケースに合格します。

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最初のサイコロが2番目のサイコロを打つかどうかを伝える2つの配列を取るダイアッドとして定義され、
h2回投げて合計するかどうかを告げる2つの配列を取るダイアッドとして定義されます。
fます正しい答え

編集:グライム・非推移状態で間違いを修正しました。(置き換え,*


改善のための提案をお待ちしています。:)
ジェイボサミヤ

@MartinBüttner、私は最初にそれを試しましたが、コードの長さをさらに増やすことなく複数行(またはJで知られているように文)を連結する方法を知りませんでした...「動名詞」について学ぶことで同様に、コードを短くしてしまい、多くの文章一つに...
ジェイBosamiya

1

ピス 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))

これは、Martinのすべてのテストケースに合格しました。Peterのすべてのケースを処理するわけではありません。

説明(これはすごいことになります)

Lmsd^b2

非常に簡単yで、反復可能な値の各デカルトペアの合計を返す関数を作成します。と同等:def y(b):return map(lambda d:sum(d),product(b,repeats=2))。これは、通常のダイスを2回投げることをシミュレートする多面ダイスを作成するために使用されます。

Msmsm>bkGH

gダイスが別のダイスを打つ回数を返す2つの引数の関数を定義します。と同等def g(G,H):return sum(map(lambda k:sum(map(lambda b:b>k,G)),H)です。

DPNK-ghNeNgeNhNR?^tZ<KZKZ

P引数として2つのサイコロのリストを受け取る機能を定義します。これは、最初のダイスが「負けた」場合は-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割り当ては、Python 2組の割り当てのように作用します。本質的にG,H=(result)

msdCm,PkP,yhkyekm,@Qb@QhbUQ

マップを逆方向に説明します。 m,@Qb@QhbUQb = 0..2を反復処理し、インデックスbとインデックスb + 1のサイコロの2タプルを生成します。これにより、サイコロ(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により、最初のタプルにすべてのシングルダイスの「ビート」値が、2番目のタプルにダブルダイスの値が発生します。

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

結果を印刷する大まかなもの。Gが0であるか、3で割り切れない場合、これはボット+/- 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);

配列の1つを読み取ってinput()から3つの要素を割り当てると、短くなりません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')}

私は確率があまりよくないので、結果を確認するために、サイコロを数十万回投げる方が好きです。

式は関数に評価され、1つの引数(整数の3つの配列の配列)のみで呼び出す必要があります。Fiddleチェックして、自分でコードを実行できるようにします。

以下は、バージョン化されていないバージョンです。

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);
}

うーん、私はこれが本当に挑戦の精神にあるとは思いません。あなたは基本的にそれを確率論的挑戦から統計的挑戦に変えました。;)...ランダムスローの代わりに、考えられるすべてのスローを1回だけ列挙することができます。これにより、正確な結果が得られます(そして、はるかに速く実行されます)。
マーティンエンダー

これがより簡潔なスクリプトにつながるかどうかを確認します。アドバイスをしてくれてありがとう :)。
ブラックホール
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.