Quandle Quandary Episodio I: Identificando Quandles Finitos

20

Escriba un programa que determine si una matriz dada representa un quandle. Un quandle es un conjunto equipado con una sola operación (no conmutativa, no asociativa) ◃ que obedece a los siguientes axiomas:

  • La operación está cerrada, lo que significa que a◃b = csiempre es un elemento del conjunto si ay bson elementos del conjunto.
  • El funcionamiento es correcto-autodistributiva: (a◃b)◃c = (a◃c)◃(b◃c).
  • La operación es divisible a la derecha: para cualquier par de ay b, hay un único único ctal quec◃a = b
  • La operación es idempotente: a◃a = a

Un quandle finito se puede representar como una matriz cuadrada. A continuación se muestra un ejemplo de un quandle de orden 5 ( fuente ).

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

El valor ubicado en la fila n-ésima y la columna m-ésima (indexada a 0) es el valor de n◃m. Por ejemplo, en este quandle, 4◃1 = 3. Algunas de las propiedades de quandle son fáciles de ver desde esta matriz:

  • Está cerrado porque solo los valores 0-4 aparecen en esta matriz de 5x5.
  • Es idempotente porque la diagonal de la matriz es 0 1 2 3 4
  • Es divisible a la derecha porque ninguna columna contiene valores duplicados. (Las filas pueden, y generalmente lo harán).

La propiedad de la auto-distributividad correcta es más difícil de probar. Puede haber un atajo, pero el método más simple es iterar sobre cada combinación posible de tres índices para verificar eso m[m[a][b]][c] = m[m[a][c]][m[b][c]].

Entrada

La entrada será la lista de filas de una matriz cuadrada, usando 0-indexing o 1-index (su elección). Cada entrada será un número de un solo dígito desde 0hasta 8(o 1hasta 9). Seré flexible en el formato de entrada. Algunos formatos aceptables incluyen:

  • El formato más natural de su idioma para matrices o listas, como [[0 0 0][2 1 1][1 2 2]]o (0,0,0,2,1,1,1,2,2).
  • La lista de valores delimitados por espacios en blanco, líneas nuevas, comas, etc.
  • Una sola cadena que consta de todos los valores concatenados juntos, como 000211122.

También se le permite tomar la transposición de la matriz como entrada (intercambiando filas con columnas). Solo asegúrese de indicar esto en su respuesta.

Salida

Un solo valor de verdad / falsey que indica el estado de la matriz como quandle.

Ejemplos de quandles

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

Ejemplos de no quandles

no se ha cerrado

1

0 0 0
2 1 1
1 9 2

no correcto-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

no divisible a la derecha

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

no 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
PhiNotPi
fuente
1
La palabra "matriz" es engañosa, porque esto no tiene nada que ver con el álgebra lineal. "Tabla" sería mejor (o tal vez "tabla de Cayley", pero creo que eso es estrictamente apropiado para un grupo).
Peter Taylor

Respuestas:

7

Python 2 , 104 103 102 bytes

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]

La entrada se transpone. La salida es a través del código de salida, por lo que 0 (éxito) es verdadero y 1 (fracaso) es falso.

Pruébalo en línea!

Cómo funciona

e(t)devuelve las filas enumeradas de la matriz de entrada t , que representa un operador , como pares (índice, fila). for(a,A)in e(t), Por ejemplo, itera sobre estos, almacenar el índice en una y la misma fila en A , por lo que Ase convierte en un acceso directo para t[a].

Entre los primeros, for(b,B)in e(t)y for C in t, iteramos sobre todas las tuplas ordenadas posibles (a, b, c) en el poder cartesiano t 3 .

Para cada una de estas tuplas, evaluamos la expresión

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

El valor del booleano entre paréntesis es Falso si y solo si una o más de las siguientes comparaciones individuales hacen lo mismo.

  • a==A[a]fallará (para algún valor de a ) si no es idempotente.

  • A[a]in Bfallará si B no contiene todos los índices de una .

    Como A tiene n índices y B tiene n elementos, la no falla significa que los elementos de B coinciden con los índices de A , por lo que es cerrado y divisible a la derecha.

  • B>C[B[a]] es una tautología, ya que Python 2 consideraba los números "más pequeños" que los iterables.

  • C[B[a]]==t[C[b]][C[a]]fallará por algún valor si no es auto-distributivo correcto.

Si alguna de las comparaciones devuelve False , la expresión (0%...)arrojará un ZeroDivisionError . Además, si no está cerrado A[a]o C[b]también puede arrojar un IndexError . En ambos casos, el programa sale con el código de estado 1 (falla).

Si se pasan todas las pruebas, el programa saldrá normalmente con el código de estado 0 (correcto).

Dennis
fuente
6

Haskell, 100 bytes

Esta respuesta utiliza la entrada transpuesta .

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

Parece que no puedo usar un protector de patrón para unir un operador infijo, así que lo estoy usando whereen este caso.

(La primera versión tenía 108 bytes pero se perdió la prueba de idempotencia, la versión fija tenía 120 bytes, las versiones posteriores tenían 108, 103 y 98 bytes, pero tuve que darme cuenta gracias a @nimi de que todos estaban equivocados: por supuesto, tengo que hacer lo correcto. prueba de divisibilidad (que implica cierre) antes de realizar !!operaciones peligrosas , pero aún podría usar la mayoría de mis ideas de golf posteriores y con una más, era de 102 bytes, ahora mejorada al cambiar el orden de los operandos #(que de todos modos es mejor para compensar el transposición) para hacer un mejor uso de su asociación a la izquierda)

Usar así:

*Main> q [[0,1,2,3],[0,1,3,2],[1,0,2,3],[0,1,2,3]]
False
Christian Sievers
fuente
4

Python 2 , 138 bytes

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 es una lista de listas de enteros.

Pruébalo en línea!

Lynn
fuente
4

JavaScript (ES6), 150 bytes

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

Toma datos como una matriz de columnas de enteros.

Neil
fuente
3

Mathematica, 122 bytes

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

Función pura que toma una matriz 2D de enteros (1 indexado) como entrada, con filas y columnas invertidas de la convención en la pregunta, y devolviendo Trueo False. La primera línea define la operación infijo binaria n_±m_como la operación quandle.

Para una matriz lx l, cerrado y divisible a la derecha es equivalente a que cada fila (en mi caso) sea alguna permutación de {1, ..., l}, e idempotente es equivalente a que la diagonal principal sea exactamente {1, ..., l}. Entonces #&@@Union[Sort/@#]==Range@l==Array[#±#&,l=Length@#]detecta estas tres condiciones. (El uso de Sort/@#aquí es la razón por la que elegí intercambiar filas y columnas).

Para la distribución correcta, verificamos literalmente todas las posibilidades usando Array[±##2±#==(#2±#)±(#3±#)&,{l,l,l}]). (Tenga en cuenta que ±##2±#se expande automáticamente a (#2±#3)±#, ya que ##2representa la secuencia del segundo y tercer argumento de la función pura de tres variables sobre la que se está ordenando). Luego &&And@@Flatten@verifica si se aprobó cada prueba. Para algunos quandles no cerrados, se pueden generar errores cuando intenta acceder a una parte de una matriz que no existe, pero la respuesta correcta aún se devuelve.

Greg Martin
fuente
±m__:=#[[m]];Yo creo que. Y hay un Diagonalincorporado. Y ±es asociativo por la izquierda y lo puede utilizar #2±#±(#3±#), pero si no me equivoco, entonces es más corto para volver a asignar #a #3y hacer #±#2±#3==#±#3±±##2&. Y también debería ser posible reemplazar toda la Flatten@parte con(...&~Array~{l,l,l}<>"")
Martin Ender
Me pregunto si tiene que mover el l=Lengtha Range@lpesar de que debido a que uno se debe evaluar en primer lugar, por lo que si se utiliza la función en repetidas ocasiones, creo que Rangetodavía se pone el anterior l, no?
Martin Ender
0

C ++ 14, 175 bytes

Como lambda sin nombre, suponiendo nque sea como std::vector<std::vector<int>>y que regrese a través del parámetro de referencia. 0 es falso, todo lo demás es cierto.

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

Sin golf y uso:

#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";
}
Karl Napf
fuente
Sugerir en int a,b,c,u,s=r=m.size()Flugar de int s=r=m.size(),a,b,c F, en u=0;r*=s==A.size()&&a==A[a]Flugar de r*=s==A.size()&&A[a]==a;int u=0 F, en r*=s>A[b]Flugar de r*=A[b]<s Fy en ~u+(1<<s)lugar deu-(1<<s)+1
ceilingcat