Quandle QuandaryエピソードI:有限カンドルの識別


20

与えられた行列がカンドルを表すかどうかを判断するプログラムを作成します。quandleは以下の公理に従う単一(非可換、非会合)操作◃を備えたセットです。

  • 操作は閉じられます。つまり、a◃b = cは、セットの要素である場合a、常にセットのb要素です。
  • 操作は、自己分散型です(a◃b)◃c = (a◃c)◃(b◃c)
  • 操作は右割り可能です:aおよびの任意のペアに対して、次のようなb単一の一意性cがあります。c◃a = b
  • 操作はべき等です: a◃a = a

有限のカンドルは正方行列として表すことができます。以下は、5次カンドル(source)の例です。

0 0 1 1 1
1 1 0 0 0
3 4 2 4 3
4 2 4 3 2
2 3 3 2 4

n番目の行とm番目の列(0から始まる)にある値は、n◃mの値です。たとえば、このカンドルでは、4◃1 = 3。この行列から、カンドルプロパティの一部を簡単に確認できます。

  • この5x5マトリックスには値0〜4のみが表示されるため、閉じられます。
  • 行列の対角が0 1 2 3 4であるため、べき等です。
  • 列に重複値が含まれていないため、右分割可能です。(行は可能であり、通常はそうなります。)

正しい自己分布の特性をテストすることは困難です。ショートカットがあるかもしれませんが、最も簡単な方法は、3つのインデックスの可能な組み合わせを繰り返して、それを検証することm[m[a][b]][c] = m[m[a][c]][m[b][c]]です。

入力

入力は、0インデックスまたは1インデックス(任意)を使用した正方行列の行のリストになります。各エントリは、0to 8(または1through 9)の1桁の数字になります。入力形式に柔軟に対応します。許容される形式には次のものがあります。

  • 以下のような行列やリスト、貴方の言語の最も自然なフォーマット[[0 0 0][2 1 1][1 2 2]](0,0,0,2,1,1,1,2,2)
  • 空白、改行、カンマなどで区切られた値のリスト
  • のように連結されたすべての値で構成される単一の文字列000211122

また、行列の転置を入力として使用することもできます(行を列と交換する)。答えにこれを明記してください。

出力

行列の状態をカンドルとして示す単一の真偽値。

カンドルの例

0

0 0
1 1

0 0 0
2 1 1
1 2 2

0 0 1 1
1 1 0 0
3 3 2 2
2 2 3 3

0 3 4 1 2
2 1 0 4 3
3 4 2 0 1
4 2 1 3 0
1 0 3 2 4

非カンドルの例

閉じていない

1

0 0 0
2 1 1
1 9 2

自己分散的ではない

0 0 1 0
1 1 0 1
2 3 2 2
3 2 3 3

(3◃1)◃2 = 2◃2 = 2
(3◃2)◃(1◃2) = 3◃0 = 3

右割り不可

0 2 3 4 1
0 1 2 3 4
3 4 2 2 2
3 3 3 3 3
4 1 1 1 4

0 1 2 3
3 1 2 0
3 1 2 3
0 1 2 3

dem等ではない

1 1 1 1
3 3 3 3
2 2 2 2
0 0 0 0

2 1 0 4 3
3 4 2 0 1
4 2 1 3 0
1 0 3 2 4
0 3 4 1 2

1
これは線形代数とは何の関係もないため、「マトリックス」という言葉は誤解を招くものです。「テーブル」の方が良いでしょう(または「ケイリーテーブル」かもしれませんが、厳密にはグループにのみ適していると思います)。
ピーターテイラー

回答:


7

パイソン2104の 103 102バイト

t=input();e=enumerate
[0%(a==A[a]in B>C[B[a]]==t[C[b]][C[a]])for(a,A)in e(t)for(b,B)in e(t)for C in t]

入力が転置されます。出力は終了コードを経由するため、0(成功)は真実であり、1(失敗)は偽です。

オンラインでお試しください!

使い方

e(t)入力行列tの列挙された行を返します。これは、演算子を(インデックス、行)のペアとして表します。for(a,A)in e(t)、たとえば、これらを反復処理して、インデックスをaに、行自体をAに格納します。したがってA、のショートカットになりt[a]ます。

前者、、for(b,B)in e(t)およびの間で、デカルト累乗t 3のfor C in tすべての可能な順序付きタプル(a、b、c)を反復します。

これらの各タプルについて、式を評価します

0%(a==A[a]in B>C[B[a]]==t[C[b]][C[a]])

括弧で囲まれたブールの値は、次の個別の比較の1つ以上が同じ場合にのみFalseです。

  • a==A[a]fail がべき等でない場合(ある値の場合)失敗します。

  • A[a]in BBAのすべてのインデックスを含まない場合、失敗します。

    以来、Aが有するn個のインデックスとBは有するn個の要素こと要素、非故障手段Bは、のインデックスと一致Aのように、閉じ、右分割されます。

  • B>C[B[a]] Python 2はイテラブルよりも「小さい」数字を考慮したため、トートロジーです。

  • C[B[a]]==t[C[b]][C[a]]が自己分散的でない場合、何らかの値で失敗します。

比較のいずれかがFalseを返す場合、式(0%...)ZeroDivisionErrorをスローします。また、が閉じられていない場合、A[a]またはIndexErrorをC[b]スローする場合もあります。どちらの場合も、プログラムはステータスコード1(失敗)で終了します。

すべてのテストに合格すると、プログラムはステータスコード0(成功)で正常に終了します。


6

Haskell、100バイト

この答えは転置入力を使用しています。

q m=and$(elem<$>v<*>m)++[a#a==a&&a#b#c==a#c#(b#c)|a<-v,b<-v,c<-v]where v=[0..length m-1];i#j=m!!j!!i

パターンガードを使用して中置演算子をバインドできないように思えるのでwhere、この場合に使用しています。

(最初のバージョンは108バイトでしたが、べき等性テストを逃し、修正バージョンは120バイトでした。後のバージョンでは108、103、98バイトでしたが、@ nimiのおかげですべて間違っていることを認識しなければなりませんでした。危険な!!操作を行う前に分割可能性テスト(閉じていることを意味します)が、その後のゴルフのアイデアのほとんどを使用できましたが、もう1つは102バイトでしたが、オペランドの順序を変更することで改善されまし#た転置)左への関連付けをより有効に活用するため)

次のように使用します。

*Main> q [[0,1,2,3],[0,1,3,2],[1,0,2,3],[0,1,2,3]]
False


4

JavaScript(ES6)、150バイト

a=>!(a.some((b,i)=>b[i]-i)|a.some(b=>[...new Set(b)].sort()+''!=[...b.keys()])||a.some((_,i)=>a.some((_,j)=>a.some((b,k)=>b[a[j][i]]-a[b[j]][b[i]]))))

入力を整数の列配列の配列として受け取ります。


3

Mathematica、122バイト

(n_±m_:=#[[m,n]];#&@@Union[Sort/@#]==Range@l==Array[#±#&,l=Length@#]&&And@@Flatten@Array[±##2±#==(#2±#)±(#3±#)&,{l,l,l}])&

入力として整数の2D配列(1インデックス付き)を取得し、問題の規約とは行と列を逆にして、Trueまたはを返す純関数False。最初の行は、2項中置演算n_±m_をクアンドル演算として定義しています。

以下のためlのx lアレイ、閉じられ、右分割いくつかの置換である(私の場合)すべての行に相当し{1, ..., l}、そして冪等は正確に主対角線であることに等価です{1, ..., l}。したがって#&@@Union[Sort/@#]==Range@l==Array[#±#&,l=Length@#]、これら3つの条件を検出します。(ここでの使用Sort/@#は、私が行と列を交換することを選んだ理由です。)

正しく分配するために、を使用して文字通りすべての可能性をチェックしArray[±##2±#==(#2±#)±(#3±#)&,{l,l,l}])ます。(配列される3変数純関数の2番目と3番目の引数のシーケンスを表す±##2±#ため(#2±#3)±#、自動的にに展開することに注意してください##2。)次に、&&And@@Flatten@すべてのテストが合格したかどうかをチェックします。一部の閉じられていないカンドルについては、存在しないマトリックスの一部にアクセスしようとするとエラーがスローされる場合がありますが、正しい答えが返されます。


±m__:=#[[m]];おもう。そして、Diagonal組み込みがあります。また±、左結合なので#2±#±(#3±#)、使用できますが、間違えなかった場合は、再割り当て##3て実行する方が短くなります#±#2±#3==#±#3±±##2&。また、Flatten@パーツ全体を(...&~Array~{l,l,l}<>"")
Martin Ender

あなたが移動する必要がある場合、私は疑問に思うl=LengthRange@lその1が最初に評価されなければならないのでかかわらず、あなたが繰り返し機能を使用している場合ので、私が思うに、Rangeまだ取得する前のl、ありませんか?
マーティンエンダー

0

C ++ 14、175バイト

名前のないラムダとして、n同様であるstd::vector<std::vector<int>>と仮定し、参照パラメーターを介して戻ります。0はfalseで、他のすべてはtrueです。

#define F(x);for(x=-1;++x<s;){
[](auto m,int&r){int s=r=m.size(),a,b,c F(a)auto A=m[a];r*=s==A.size()&&A[a]==a;int u=0 F(b)u|=1<<m[b][a];r*=A[b]<s F(c)r*=m[A[b]][c]==m[A[c]][m[b][c]];}}r*=!(u-(1<<s)+1);}}

ゴルフをしないと使用法:

#include<vector>
#include<iostream>

auto f=
#define F(x);for(x=-1;++x<s;){
[](auto m,int&r){
 int s=r=m.size(),a,b,c
 F(a)
  auto A=m[a];               //shortcut for this row
  r*=s==A.size()&&A[a]==a;   //square and idempotet
  int u=0                    //bitset for uniqueness in col
  F(b)
   u|=1<<m[b][a];            //count this item
   r*=A[b]<s                 //closed
   F(c)
    r*=m[A[b]][c]==m[A[c]][m[b][c]];
   }
  }
  r*=!(u-(1<<s)+1);          //check right-divisibility
 }
}
;

int main(){
 int r;
 std::vector<std::vector<int>>
  A = {
   {0, 0, 1, 1},
   {1, 1, 0, 0},
   {3, 3, 2, 2},
   {2, 2, 3, 3},
  },
  B = {
   {0, 2, 3, 4, 1},
   {0, 1, 2, 3, 4},
   {3, 4, 2, 2, 2},
   {3, 3, 3, 3, 3},
   {4, 1, 1, 1, 4},
  };
 f(A,r);
 std::cout << r << "\n";
 f(B,r);
 std::cout << r << "\n";
}

int a,b,c,u,s=r=m.size()F代わりにint s=r=m.size(),a,b,c F、のu=0;r*=s==A.size()&&a==A[a]F代わりにr*=s==A.size()&&A[a]==a;int u=0 F、のr*=s>A[b]F代わりにr*=A[b]<s F、の~u+(1<<s)代わりにu-(1<<s)+1
提案します
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.