# Creates matrix a n by n matrix from a string 
def make_matrix(string,n):
    m = []
    row = []
    for i in range(0,n * n):
        if string[i] == '\n':
            continue

        if string[i] == ' ':
            continue

        row.append(Integer(string[i]) + 1)

        if len(row) == n:
            m.append(row)
            row = []

    return matrix(m)

# Applies symbol permutations to a matrix
def permute_matrix(matrix, permutation,n):
    copy = deepcopy(matrix)

    for i in range(0, n):
        for j in range(0 , n):
            copy[i,j] = permutation[copy[i][j] - 1]

    return copy 

# Gets Matrices from a text file
def fetch_matrices(file_name,n):
    matrices = []

    with open(file_name) as f:
        L = f.readlines()

    for i in L:
        matrices.append(make_matrix(i,n))

    return matrices

# This applies all symbol permutations to the Isotopy
# classes of order n which are read in from a file
def create_determinant_list(file_name,n):
    the_list = []

    permu = (Permutations(n)).list()

    matrices = fetch_matrices(file_name,n)
    print "Making Determinant list..."

    for i in range(0,len(matrices)):
        for j in permu:
            copy = permute_matrix(matrices[i],j,n)
            the_list.append([i,j,copy.determinant()])

    print "Finished making determinant list for order ", n
    return the_list

# This gets the Distinct determinants from 
# order n Latin Squares
def get_Dn(sets,index):
    determinants = []

    for i in sets:
        determinants.append(i[index])

    for i in range(0,len(determinants)):
        if determinants[i] < 0:
            determinants[i] *= -1

    determinants = uniq(determinants)
    determinants = sorted(determinants)

    return determinants

# Sorts Isotopy Classes by Determinants they produce
# Example: classes_with_deter[i] is the group of 
# Isotopy Classes that produce the determinant in Dn[i] 
def sort_determinants_into_groups(triples, Dn):

    classes_with_deter = []

    for i in Dn:
        temp = []
        
        for j in triples:
            if abs(j[2]) == i:
                temp.append(j[0])

        temp = uniq(temp)
        classes_with_deter.append(temp)

    return classes_with_deter

def count_unique_determinants(file,order):

    count = 0
    Isotopy_class = create_determinant_list(file,order)
    D_n = get_Dn(Isotopy_class, 2)
    SG_n = sort_determinants_into_groups(Isotopy_class,D_n)

    # Counts how many determinants only come 
    # from one Isotopy class
    for i in SG_n:
        if len(i) == 1:
            count += 1

    return count 

def count_isotopy_classes_with_distinct_determinants(file,order):

    Isotopy_classes = []
    Isotopy_class = create_determinant_list(file,order)
    D_n = get_Dn(Isotopy_class, 2)
    SG_n = sort_determinants_into_groups(Isotopy_class,D_n)

    # checks if the a determinant only 
    # comes from one Isotopy Class
    for i in SG_n:
        if len(i) == 1:
            Isotopy_classes.append(i[0])

    # The length of this list is the entry in the sequence
    Isotopy_classes = uniq(Isotopy_classes)

    return Isotopy_classes 

def sequence_A309088():

    file_for_4 = "latin_is4.txt"
    file_for_5 = "latin_is5.txt"
    file_for_6 = "latin_is6.txt"
    # Order 7 takes around 40 minutes to compute
    file_for_7 = "latin_is7.txt"
    files = [file_for_4,file_for_5,file_for_6,file_for_7]
    sequence = []

    for i, isotopy in enumerate(files):
        print "Working on order ", i+4, " now..."
        sequence.append(len(count_isotopy_classes_with_distinct_determinants(isotopy,i+4)))

    return sequence