Quandle Quandary Episodio I: Identificazione di Quandles finiti


20

Scrivi un programma che determinerà se una data matrice rappresenta un dilemma. Un dilemma è un set dotato di una singola operazione (non commutativa, non associativa) ◃ che obbedisce ai seguenti assiomi:

  • L'operazione è chiusa, il che significa che a◃b = cè sempre un elemento dell'insieme se ae bsono elementi dell'insieme.
  • L'operazione è di destra-self-distributiva: (a◃b)◃c = (a◃c)◃(b◃c).
  • L'operazione è divisibile a destra: per ogni coppia scelta di ae b, esiste un unico unico ctalec◃a = b
  • L'operazione è idempotente: a◃a = a

Un dilemma finito può essere rappresentato come una matrice quadrata. Di seguito è riportato un esempio di un quandle ordine-5 ( sorgente ).

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

Il valore situato nella riga n-esima e nella colonna m-esima (indicizzato 0) è il valore di n◃m. Ad esempio, in questo quandle, 4◃1 = 3. Alcune delle proprietà dei quandle sono facili da vedere da questa matrice:

  • È chiuso perché in questa matrice 5x5 compaiono solo i valori 0-4.
  • È idempotente perché la diagonale della matrice è 0 1 2 3 4
  • È divisibile a destra perché nessuna colonna contiene valori duplicati. (Le righe possono, e di solito lo faranno.)

La proprietà dell'autodisciplina è più difficile da testare. Potrebbe esserci un collegamento, ma il metodo più semplice è quello di scorrere su ogni possibile combinazione di tre indici per verificarlo m[m[a][b]][c] = m[m[a][c]][m[b][c]].

Ingresso

L'input sarà l'elenco di righe di una matrice quadrata, usando 0-indexing o 1-index (a tua scelta). Ogni voce sarà un numero a una cifra da 0a 8(o 1attraverso 9). Sarò flessibile sul formato di input. Alcuni formati accettabili includono:

  • La formattazione più naturale della tua lingua per matrici o elenchi, come [[0 0 0][2 1 1][1 2 2]]o (0,0,0,2,1,1,1,2,2).
  • L'elenco di valori delimitati da spazi bianchi, newline, virgole, ecc.
  • Una singola stringa composta da tutti i valori concatenati insieme, ad esempio 000211122.

Puoi anche prendere la trasposizione della matrice come input (scambiando righe con colonne). Assicurati di dichiararlo nella tua risposta.

Produzione

Un singolo valore di verità / falsità che indica lo stato della matrice come dilemma.

Esempi di dilemmi

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

Esempi di non-quandles

non chiuso

1

0 0 0
2 1 1
1 9 2

non giusto auto-distributivo

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

non divisibile a destra

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

non idempotente

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
La parola "matrice" è fuorviante, perché non ha nulla a che fare con l'algebra lineare. "Tavolo" sarebbe meglio (o forse "tavolo Cayley", ma penso che sia strettamente appropriato solo per un gruppo).
Peter Taylor,

Risposte:


7

Python 2 , 104 103 102 byte

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]

L'ingresso è trasposto. L'output avviene tramite il codice di uscita, quindi 0 (esito positivo) è veritiero e 1 (esito negativo) è errato.

Provalo online!

Come funziona

e(t)restituisce le righe enumerate della matrice di input t - che rappresenta un operatore - come coppie (indice, riga). for(a,A)in e(t), Ad esempio, itera su questi, memorizzare l'indice in una e la stessa riga A , quindi Adiventa un collegamento per t[a].

Tra i primi ,, for(b,B)in e(t)e for C in t, ripetiamo su tutte le possibili tuple ordinate (a, b, c) nel potere cartesiano t 3 .

Per ciascuna di queste tuple, valutiamo l'espressione

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

Il valore del valore booleano tra parentesi è False se e solo se uno o più dei seguenti confronti individuali fanno lo stesso.

  • a==A[a] fallirà (per un certo valore di a ) se non è idempotente.

  • A[a]in Bdeteriorarsi se B non contiene tutti gli indici di A .

    Poiché A ha n indici e B ha n elementi, il non-fallimento significa che gli elementi di B corrispondono agli indici di A , quindi è chiuso e divisibile a destra.

  • B>C[B[a]] è una tautologia, poiché Python 2 ha considerato i numeri "più piccoli" degli iterabili.

  • C[B[a]]==t[C[b]][C[a]]fallirà per qualche valore se non è giusto auto-distributivo.

Se uno dei confronti restituisce False , l'espressione (0%...)genererà ZeroDivisionError . Inoltre, se non è chiuso A[a]o C[b]può anche generare un IndexError . In entrambi i casi, il programma termina con il codice di stato 1 (errore).

Se tutti i test hanno superato, il programma uscirà normalmente con il codice di stato 0 (successo).


6

Haskell, 100 byte

Questa risposta utilizza input trasposto .

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

Sembra che non riesca a usare un pattern guard per legare un operatore infix, quindi sto usando wherein questo caso.

(La prima versione era di 108 byte ma mancava il test di idempotenza, la versione fissa era di 120 byte, le versioni successive avevano 108, 103 e 98 byte, ma ho dovuto rendermi conto grazie a @nimi che erano tutti sbagliati: ovviamente ho bisogno di fare il giusto- test di divisibilità (che implica la chiusura) prima di fare qualsiasi !!operazione pericolosa , ma potrei ancora usare la maggior parte delle mie idee golfistiche successive e con un'altra, erano 102 byte, ora migliorati cambiando l'ordine degli operandi di #(che è comunque migliore per compensare il trasposizione) per sfruttare meglio la sua associazione a sinistra)

Usa così:

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

4

Python 2 , 138 byte

def f(m):R=range(len(m));return all(m[i][i]==i<set(zip(*m)[i])==set(R)>m[m[j][k]][i]==m[m[j][i]][m[k][i]]for i in R for j in R for k in R)

m è un elenco di elenchi di numeri interi.

Provalo online!


4

JavaScript (ES6), 150 byte

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

Accetta l'input come una matrice di array di colonne di numeri interi.


3

Mathematica, 122 byte

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

Funzione pura che accetta come input una matrice 2D di numeri interi (1 indicizzati), con righe e colonne invertite rispetto alla convenzione nella domanda e ritorno Trueo False. La prima riga definisce l'operazione n_±m_di infissione binaria come operazione di dilemma.

Per un array lx l, chiuso e divisibile a destra equivale ad ogni riga (nel mio caso) essendo una permutazione di {1, ..., l}, e idempotente equivale esattamente alla diagonale principale {1, ..., l}. Quindi #&@@Union[Sort/@#]==Range@l==Array[#±#&,l=Length@#]rileva per queste tre condizioni. (L'uso diSort/@# qui è il motivo per cui ho scelto di scambiare righe e colonne.)

Per la distribuzione corretta, controlliamo letteralmente tutte le possibilità usando Array[±##2±#==(#2±#)±(#3±#)&,{l,l,l}]). (Si noti che ±##2±#si espande automaticamente a (#2±#3)±#, poiché ##2rappresenta la sequenza del secondo e del terzo argomento per la funzione pura a tre variabili su cui è stato eseguito il array.) Quindi &&And@@Flatten@controlla se ogni singolo test è stato superato. Per alcuni dilemmi non chiusi, è possibile che vengano generati errori quando si tenta di accedere a una parte di una matrice che non esiste, ma viene comunque restituita la risposta corretta.


±m__:=#[[m]];Penso. E c'è un Diagonalbuilt-in. E ±che resta associativo in modo da poter usare #2±#±(#3±#), ma se non ho fatto un errore, allora è più breve di riassegnare #a #3e fare #±#2±#3==#±#3±±##2&. E dovrebbe anche essere possibile sostituire l'intera Flatten@parte con(...&~Array~{l,l,l}<>"")
Martin Ender

Mi chiedo se si debba spostare l=Lengthin Range@lanche perché quello dovrebbe essere valutato prima, quindi se si utilizza la funzione più volte, penso Rangeche ottiene ancora il precedente l, no?
Martin Ender,

0

C ++ 14, 175 byte

Come lambda senza nome, assumendo nche sia simile std::vector<std::vector<int>>e che ritorni tramite parametro di riferimento. 0 è falso, tutto il resto è vero.

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

Ungolfed e utilizzo:

#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";
}

Suggerisci int a,b,c,u,s=r=m.size()Finvece di int s=r=m.size(),a,b,c F, u=0;r*=s==A.size()&&a==A[a]Finvece di r*=s==A.size()&&A[a]==a;int u=0 F, r*=s>A[b]Fanziché r*=A[b]<s Fe ~u+(1<<s)invece diu-(1<<s)+1
ceilingcat il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.