from fractions import Fraction
P = [[0, 3, 3], [0, 3, 1], [1, 3, 1]]
mod = 4
# 1, 1, 0, -1, -1, 0, ...
def seq(n):
    return [1, 1, 0, -1, -1, 0][n % 6]
   
def show(m):
    return "\n".join(" ".join(map(str, r)) for r in m) + "\n"
    
# move(P, 0, 1, 1, mod)
# print(show(P))
# move(P, 0, 2, 3, mod)
# print(show(P))
# ##########
# move(P, 1, 1, 3, mod)
# print(show(P))
# move(P, 1, 2, 2, mod)
# print(show(P))
# ###########
# move(P, 2, 0, 2, mod)
# print(show(P))
# move(P, 2, 1, 2, mod)
# print(show(P))

class Dict:
    def __init__(self, d):
        self.d = d

    def __add__(self, other):
        d = {}
        for k in set(self.d.keys()) | set(other.d.keys()):
            d[k] = self.d.get(k, 0) + other.d.get(k, 0)
        return Dict(d)

    def __sub__(self, other):
        d = {}
        for k in set(self.d.keys()) | set(other.d.keys()):
            d[k] = self.d.get(k, 0) - other.d.get(k, 0)
        return Dict(d)
        
    def __neg__(self):
        return Dict({k: -v for k, v in self.d.items()})

    def __rmul__(self, c):
        assert type(c) == int, "Multiplication impossible"
        return Dict({k: c * v for k, v in self.d.items()})

    def __mul__(self, c):
        assert type(c) == int, "Multiplication impossible"
        return Dict({k: c * v for k, v in self.d.items()})

    def __repr__(self):
        return f"{{{', '.join('{}: {}'.format(k, v) for k, v in self.d.items())}}}"

def get_next_row(m, row):
    m = len(row)
    if m % 3 == 2:
        return get_next_row(m - 1, row[:-1]) + [0]
    inv = (
        lambda i, j: (-1 if (i + j) % 2 else 1)
        * (seq(min(i + 1, j + 1) - 1) * seq(m - max(i + 1, j + 1)))
        // seq(m)
    )
    res = []
    for i in range(m):
        r = Dict({})
        for j in range(m):
            r -= inv(i, j) * row[j]
        res.append(r)
    return res

def move(B, x, y, add):
    n, m = len(B), len(B[0])
    for dx in (-1, 0, 1):
        for dy in (-1, 0, 1):
            u, v = x + dx, y + dy
            if 0 <= u < n and 0 <= v < m:
                B[u][v] = B[u][v] + add


def gauss(arr):
    n, m = len(arr), len(arr[0])
    h, k = 0, 0
    while h < n and k < m:
        idx = next((i for i in range(h, n) if arr[i][k] != 0), None)
        if idx is None:
            k += 1
        else:
            arr[idx], arr[h] = arr[h], arr[idx]
            for i in range(h + 1, n):
                f = arr[i][k] / arr[h][k]
                arr[i][k] = Fraction(0)
                for j in range(k + 1, m):
                    arr[i][j] -= arr[h][j] * f
            h += 1
            k += 1
    return arr

def gauss_solve(A, B, mod):

    n = len(A)
    arr = [[Fraction(x) for x in A[i]] + [B[i]] for i in range(n)]
    num_vars = len(arr[0]) - 1
    
    # Remove redundant lines
    gauss_arr = [row for row in gauss(arr) if not all(x % mod == 0 for x in row)]
#     print("gauss_arr")
#     for r in gauss_arr:
#         print([int(x) for x in r])
    num_row = len(gauss_arr)

    if len(gauss_arr) == 0:
        line=lambda i:f"q{i + 1} * ({'; '.join(['1' if j == i else '0' for j in range(num_vars)])})"
        sol = ['0'] * num_vars
        return sol

        
    idx = next((j for j in range(num_vars) if gauss_arr[-1][j] != 0), None)
    if idx is None and gauss_arr[-1][-1] != 0:
        return None

    others = set(range(idx + 1, num_vars + 1)) 
    # Last line
    dpts = {idx: {}}
    dpts[idx][num_vars] = gauss_arr[-1][num_vars] / gauss_arr[-1][idx]
    for j in range(idx + 1, num_vars):
        if gauss_arr[-1][j] != 0:
            dpts[idx] [j] = -(gauss_arr[-1][j] / gauss_arr[-1][idx])
    for i in range(num_row - 2, -1, -1):
        _j = next((j for j in range(num_vars) if gauss_arr[i][j] != 0), None)
        
        dpts[_j] = {num_vars: gauss_arr[i][num_vars] / gauss_arr[i][_j]}
        
        for k in range(_j + 1, num_vars):
            if gauss_arr[i][k] != 0:
                dpts[_j][k] = -(gauss_arr[i][k] / gauss_arr[i][_j])

        others |= set([k for k in range(_j + 1, min(others)) if not k in dpts])
        while any(not k in others and k != num_vars for k in dpts[_j]):
            k = next(_k for _k in dpts[_j] if not _k in sorted(others) and k != num_vars)
            for key, value in dpts[k].items():
                dpts[_j][key] = dpts[_j].get(key, 0) + dpts[_j][k] * value
            # Remove value from dict
            del dpts[_j][k]

    for o in others:
        if o != num_vars:
            dpts[o] = {o: 1}
    sol = []
    for i in sorted(others, reverse=True):
        r = []
        for key in sorted(dpts.keys()):
            r.append(dpts[key].get(i, 0))
        sol.append(r[:])
    return sol[0]

    



def solve(A, mod):
    n, m = len(A), len(A[0])
    arr = [[Dict({'c': A[i][j]}) for j in range(m)] for i in range(n)]
    for i in range(2):
        for j in range(1, m - 1):
            arr[i][j] += Dict({j - 1: 1, j: 1, j + 1: 1})
        arr[i][0] += Dict({0: 1, 1: 1})
        arr[i][m - 1] += Dict({m - 2: 1, m - 1: 1})

    seq = [[Dict({i: 1}) for i in range(m)]]
    for i in range(n - 1):
        s = get_next_row(m, arr[i])
        seq.append(s)
        for j, c in enumerate(s):
            move(arr, i + 1, j, c)
    mat = []
    b = []
    for s in arr[-1]:
        r = []
        for j in range(m):
            r.append(s.d.get(j, 0))
        b.append(-s.d.get('c', 0))
        mat.append(r)
    gs = [int(x) % mod for x in gauss_solve(mat, b, mod)]
    print("seq")
    print(seq)
    ans = []
    res = []
    for i, ele in enumerate(seq):
        row = []
        for j, dct in enumerate(ele):
            _sum = 0
            for key, val in dct.d.items():
                _sum += gs[key] * val if key != 'c' else val
            sum_mod = _sum % mod
            row.append(sum_mod)
            if sum_mod != 0:
                res.append((i, j, sum_mod))
        ans.append(row)
    print(ans)
    print(res)
    return (seq, arr[-1])
    
r, s = solve(P, mod)
for d in r:
    print(d)
print("system")
print(s)



        
        

Embed on website

To embed this program on your website, copy the following code and paste it into your website's HTML: