Contando soluciones para el latin suqare de 3×3

En el post anterior tuvimos

import numpy as np
from random import *

def random3():
 aux1 = 3*random()
 if aux1 > 0 and aux1<=1: aux2=1
 if aux1 > 1 and aux1<=2: aux2=2
 if aux1 > 2 and aux1<=3: aux2=3
 return aux2
print(random3())

def busca2(A):
 solucion = 1 # Es una bandera, solucion 1 se asume temporalmente que es solucion, 0 Se demuestra que NO es solucion
 if solucion ==1:  # Checando el primer renglon...
  if A[0,0] == A[0,1] or A[0,0] == A[0,2] or A[0,1]==A[0,2]:
   solucion = 0
 if solucion ==1:  # Checando el segundo renglon...
  if A[1,0] == A[1,1] or A[1,0] == A[1,2] or A[1,1]==A[1,2]:
   solucion = 0
 if solucion ==1:  # Checando el segundo renglon...
  if A[2,0] == A[2,1] or A[2,0] == A[2,2] or A[2,1]==A[2,2]:
   solucion = 0
 if solucion ==1:  # Checando la primer columna...
  if A[0,0] == A[1,0] or A[0,0] == A[2,0] or A[1,0]==A[2,0]:
   solucion = 0
 if solucion ==1:  # Checando la segunda columna...
  if A[0,1] == A[1,1] or A[0,1] == A[2,1] or A[1,1]==A[2,1]:
   solucion = 0
 if solucion ==1:  # Checando la tercer columna...
  if A[0,2] == A[1,2] or A[0,2] == A[2,2] or A[1,2]==A[2,2]:
   solucion = 0
 return solucion

#############################################

cuenta=0
N=500
A=np.zeros((3,3))

for k in range(N):
    
 for i in range(3):
  for j in range(3):
   A[i,j]=random3() 
   z2=busca2(A)
   if z2==1:
    print(z2,'una solucion')
    print(A)
    cuenta=cuenta+1
print(cuenta)

que por ejemplo, puede arrojar

1
1 una solucion
[[3. 2. 1.]
 [2. 1. 3.]
 [1. 3. 2.]]
1 una solucion
[[3. 2. 1.]
 [2. 1. 3.]
 [1. 3. 2.]]
1 una solucion
[[3. 2. 1.]
 [1. 3. 2.]
 [2. 1. 3.]]
1 una solucion
[[3. 2. 1.]
 [1. 3. 2.]
 [2. 1. 3.]]
1 una solucion
[[3. 2. 1.]
 [1. 3. 2.]
 [2. 1. 3.]]
1 una solucion
[[1. 3. 2.]
 [2. 1. 3.]
 [3. 2. 1.]]
1 una solucion
[[1. 3. 2.]
 [2. 1. 3.]
 [3. 2. 1.]]
7

?Como podemos quedarnos solamente con las soluciones distintas? La respuesta NO es sencilla. Primero vamos a encontrar la manera de guardar todas las soluciones. Para lograrlo, consideremos la intruccion np.append que funciona d ela siguiente manera

a = np.array([0,1,2])
print(a)
# [0 1 2]

a_append = np.append(a, 3)
print(a_append)
# [0 1 2 3]

print(a)

Consideremos el programa

cuenta=0
N=500
A=np.zeros((3,3))

for k in range(N):
    
 for i in range(3):
  for j in range(3):
   A[i,j]=random3() 
   z2=busca2(A)
   if z2==1:
    print(z2,'una solucion')
    print(A)
    if cuenta==0:
     B=np.array([A[0,0],A[0,1],A[0,2],A[1,0],A[1,1],A[1,2],A[2,0],A[2,1],A[2,2]])
    else:
     B=np.append(B,[A[0,0],A[0,1],A[0,2],A[1,0],A[1,1],A[1,2],A[2,0],A[2,1],A[2,2]])
    cuenta=cuenta+1
print(cuenta)
print(B)

Si se corre el programa 1000 veces

cuenta=0
N=1000
A=np.zeros((3,3))

for k in range(N):
    
 for i in range(3):
  for j in range(3):
   A[i,j]=int(random3()) 
   z2=busca2(A)
   if z2==1:
    print(z2,'una solucion')
    print(A)
    if cuenta==0:
     B=np.array([A[0,0],A[0,1],A[0,2],A[1,0],A[1,1],A[1,2],A[2,0],A[2,1],A[2,2]])
    if cuenta>0:
     B=np.append(B,[A[0,0],A[0,1],A[0,2],A[1,0],A[1,1],A[1,2],A[2,0],A[2,1],A[2,2]])
     print('van ',B.size/9,' soluciones ..., el tamanio de B es ',B.size)   
    cuenta=cuenta+1
print(cuenta)
print(B)
cuenta=0
N=1000
A=np.zeros((3,3))

for k in range(N):
    
 for i in range(3):
  for j in range(3):
   A[i,j]=int(random3()) 
   z2=busca2(A)
   if z2==1:
    print(z2,'una solucion')
    print(A)
    if cuenta==0:
     B=np.array([A[0,0],A[0,1],A[0,2],A[1,0],A[1,1],A[1,2],A[2,0],A[2,1],A[2,2]])
    if cuenta>0:
     B=np.append(B,[A[0,0],A[0,1],A[0,2],A[1,0],A[1,1],A[1,2],A[2,0],A[2,1],A[2,2]])
     print('van ',B.size/9,' soluciones ..., el tamanio de B es ',B.size)   
    cuenta=cuenta+1
print(cuenta)
print(B)

1 una solucion
[[1. 2. 3.]
 [2. 3. 1.]
 [3. 1. 2.]]
1 una solucion
[[3. 1. 2.]
 [1. 2. 3.]
 [2. 3. 1.]]
van  2.0  soluciones ..., el tamanio de B es  18
1 una solucion
[[3. 1. 2.]
 [1. 2. 3.]
 [2. 3. 1.]]
van  3.0  soluciones ..., el tamanio de B es  27
1 una solucion
[[3. 1. 2.]
 [1. 2. 3.]
 [2. 3. 1.]]
van  4.0  soluciones ..., el tamanio de B es  36
1 una solucion
[[1. 2. 3.]
 [2. 3. 1.]
 [3. 1. 2.]]
van  5.0  soluciones ..., el tamanio de B es  45
1 una solucion
[[1. 2. 3.]
 [2. 3. 1.]
 [3. 1. 2.]]
van  6.0  soluciones ..., el tamanio de B es  54
1 una solucion
[[2. 3. 1.]
 [3. 1. 2.]
 [1. 2. 3.]]
van  7.0  soluciones ..., el tamanio de B es  63
7
[1. 2. 3. 2. 3. 1. 3. 1. 2. 3. 1. 2. 1. 2. 3. 2. 3. 1. 3. 1. 2. 1. 2. 3.
 2. 3. 1. 3. 1. 2. 1. 2. 3. 2. 3. 1. 1. 2. 3. 2

Para entender el problema, consideremos

for i in range(0,int(B.size/3),3):
    print(int(B[i]),int(B[i+1]),int(B[i+2]))

1 2 3
2 3 1
3 1 2
3 1 2
1 2 3
2 3 1
3 1 2

?Como podriamos contar las ternas distintas de tres digitos? Hay 7 en total

import numpy as np
import matplotlib.pyplot as plt

B=np.zeros(21)

B = [1, 2, 3, 2, 3, 1, 3, 1, 2, 3, 1, 2, 1, 2, 3, 2, 3, 1, 3, 1, 2]
-----------------
for rana in range (0,21):
 print('B[',rana,']=',B[rana])
 ------------------
 
 renglon=1
for rana in range (0,21,3):
 triada = np.array([B[rana+0],B[rana+1],B[rana+2]])
 print('renglon ',renglon,' con la triada ',triada,'---> rana=',rana)
 renglon = renglon+1
 --------------
 
renglon=1
for rana in range (0,21,3):
 triada = np.array([B[rana+0],B[rana+1],B[rana+2]])
 print('renglon ',renglon,' con la triada ',triada,'---> rana=',rana)

 if renglon == 1:
  bolsa=triada_new
  print('en la bolsa',bolsa)

 if renglon == 2:
  print('tamanio de la bolsa',bolsa.size)
  print('porque hay ',int(bolsa.size/3),'soluciones')
    
 renglon = renglon+1
 
 ------------
 
 renglon=1
for rana in range (0,21,3):
 triada = np.array([B[rana+0],B[rana+1],B[rana+2]])
 print('renglon ',renglon,' con la triada ',triada,'---> rana=',rana)

 if renglon == 1:
  bolsa=triada
  print('en la bolsa',bolsa)

 if renglon == 2:
  print('tamanio de la bolsa',bolsa.size)
  print('porque hay ',int(bolsa.size/3),'soluciones')
  aux1 = np.array([bolsa[(int(bolsa.size/3)-1)+0],bolsa[(int(bolsa.size/3)-1)+1],bolsa[(int(bolsa.size/3)-1)+2]])
  print('aux1',aux1,'triada',triada)

    
 renglon = renglon+1
 
 ---------------
 
 renglon=1
for rana in range (0,21,3):
 triada = np.array([B[rana+0],B[rana+1],B[rana+2]])
 print('renglon ',renglon,' con la triada ',triada,'---> rana=',rana)

 if renglon == 1:
  bolsa=triada
  print('en la bolsa',bolsa)

 if renglon == 2:
  print('tamanio de la bolsa',bolsa.size)
  print('porque hay ',int(bolsa.size/3),'soluciones')
  aux1 = np.array([bolsa[(int(bolsa.size/3)-1)+0],bolsa[(int(bolsa.size/3)-1)+1],bolsa[(int(bolsa.size/3)-1)+2]])
  print('aux1',aux1,'triada',triada)
  if aux1[0] != triada[0]: print('primer elemento no igual')
  if aux1[1] != triada[1]: print('segundo elemento no igual')
  if aux1[2] != triada[2]: print('tercer elemento no igual')
    
 renglon = renglon+1
 
 ----------------
 
 renglon=1
for rana in range (0,21,3):
 triada = np.array([B[rana+0],B[rana+1],B[rana+2]])
 print('renglon ',renglon,' con la triada ',triada,'---> rana=',rana)

 if renglon == 1:
  bolsa=triada
  print('en la bolsa',bolsa)

 if renglon == 2:
  print('tamanio de la bolsa',bolsa.size)
  print('porque hay ',int(bolsa.size/3),'soluciones')
  aux1 = np.array([bolsa[(int(bolsa.size/3)-1)+0],bolsa[(int(bolsa.size/3)-1)+1],bolsa[(int(bolsa.size/3)-1)+2]])
  print('aux1',aux1,'triada',triada)
  if aux1[0] != triada[0] and aux1[1] != triada[1] and aux1[2] != triada[2]: 
    print('todos los elementos no son iguales')
    bolsa=np.append(bolsa,triada)
    print('en la bolsa ', bolsa)
    
 renglon = renglon+1
 
 ----
 
 
 renglon=1
for rana in range (0,21,3):
 triada = np.array([B[rana+0],B[rana+1],B[rana+2]])


 if renglon == 1:
  bolsa=triada


 if renglon == 2:
  aux1 = np.array([bolsa[(int(bolsa.size/3)-1)+0],bolsa[(int(bolsa.size/3)-1)+1],bolsa[(int(bolsa.size/3)-1)+2]])
  if aux1[0] != triada[0] and aux1[1] != triada[1] and aux1[2] != triada[2]: 
    bolsa=np.append(bolsa,triada)


 if renglon == 3:
  print('en este renglon la triada es ',triada)
  print('y en la bolsa hay ',bolsa)
    
 renglon = renglon+1
 
 
 ---------
 
 renglon=1
for rana in range (0,21,3):
 triada = np.array([B[rana+0],B[rana+1],B[rana+2]])


 if renglon == 1:
  bolsa=triada


 if renglon == 2:
  aux1 = np.array([bolsa[(int(bolsa.size/3)-1)+0],bolsa[(int(bolsa.size/3)-1)+1],bolsa[(int(bolsa.size/3)-1)+2]])
  if aux1[0] != triada[0] and aux1[1] != triada[1] and aux1[2] != triada[2]: 
    bolsa=np.append(bolsa,triada)


 if renglon == 3:
  print('en este renglon la triada es ',triada)
  print('y en la bolsa hay ',bolsa,bolsa.size)
  for i1 in range(0,int(bolsa.size),3):
     print(i1)
    
 renglon = renglon+1
 
 
 ----------
 
 
 renglon=1
for rana in range (0,21,3):
 triada = np.array([B[rana+0],B[rana+1],B[rana+2]])


 if renglon == 1:
  bolsa=triada


 if renglon == 2:
  aux1 = np.array([bolsa[(int(bolsa.size/3)-1)+0],bolsa[(int(bolsa.size/3)-1)+1],bolsa[(int(bolsa.size/3)-1)+2]])
  if aux1[0] != triada[0] and aux1[1] != triada[1] and aux1[2] != triada[2]: 
    bolsa=np.append(bolsa,triada)


 if renglon == 3:
  print('en este renglon la triada es ',triada)
  print('y en la bolsa hay ',bolsa,bolsa.size)
  for i1 in range(0,int(bolsa.size),3):
     print(i1,' -- ',bolsa[i1+0],bolsa[i1+1],bolsa[i1+2],triada)
    
 renglon = renglon+1
 
 
 ----------
 
 renglon=1
for rana in range (0,21,3):
 triada = np.array([B[rana+0],B[rana+1],B[rana+2]])


 if renglon == 1:
  bolsa=triada


 if renglon == 2:
  aux1 = np.array([bolsa[(int(bolsa.size/3)-1)+0],bolsa[(int(bolsa.size/3)-1)+1],bolsa[(int(bolsa.size/3)-1)+2]])
  if aux1[0] != triada[0] and aux1[1] != triada[1] and aux1[2] != triada[2]: 
    bolsa=np.append(bolsa,triada)


 if renglon == 3:
  print('en este renglon la triada es ',triada)
  print('y en la bolsa hay ',bolsa,bolsa.size)
  for i1 in range(0,int(bolsa.size),3):
      
     print(i1,' -- ',bolsa[i1+0],bolsa[i1+1],bolsa[i1+2],triada)
     if bolsa[i1+0] != triada[0] and bolsa[i1+1] != triada[1] and bolsa[i1+2] != triada[2] : print('no iguales')
    
 renglon = renglon+1