def hadamard(n): """Vrne logični izraz, ki je izpolnljiv, ko obstaja Hadamardova matrika reda n.""" if n == 1: return prop.Literal("r0c0") if n % 2 == 1: return prop.Fls() # Prva vrstica in stolpec l = ["r0c0"] for i in range(1, n): l.append("r0c%d" % i) l.append("r%dc0" % i) # Štejemo resnične vrednosti XORa i-te in j-te vrstice for i in range(n): for j in range(i+1, n): # Resničnih je n/2 l.append("r%dr%df%dn%d" % (i, j, n, n//2)) # Pravili za prvega l.append("r%dr%df1n0" % (i, j)) l.append(prop.Not("r%dr%df1n1" % (i, j))) for k in range(1, n): # Ali do indeksa k ni nobenega resničnega? l.append(prop.iff("r%dr%df%dn0" % (i, j, k+1), prop.And("r%dr%df%dn0" % (i, j, k), prop.iff("r%dc%d" % (i, k), "r%dc%d" % (j, k))))) if k < n//2: # Ali so do indeksa k vsi resnični? l.append(prop.iff("r%dr%df%dn%d" % (i, j, k+1, k+1), prop.And("r%dr%df%dn%d" % (i, j, k, k), prop.Not(prop.iff("r%dc%d" % (i, k), "r%dc%d" % (j, k)))))) for m in range(min(k, n//2)): # Ali je do indeksa k m+1 resničnih? l.append(prop.iff("r%dr%df%dn%d" % (i, j, k+1, m+1), prop.Or(prop.And("r%dr%df%dn%d" % (i, j, k, m), prop.Not(prop.iff("r%dc%d" % (i, k), "r%dc%d" % (j, k)))), prop.And("r%dr%df%dn%d" % (i, j, k, m+1), prop.iff("r%dc%d" % (i, k), "r%dc%d" % (j, k)))))) return prop.And(l)
def sudoku(s, abc): """Vrne logični izraz, ki opisuje sudoku s z abecedo abc.""" n = len(abc) r = int(math.sqrt(n)) if isinstance(abc, basestring): s = [[None if s[i][j] in [None, ""] else str(s[i][j]) for j in range(n)] for i in range(n)] assert all([all([x == None or (len(x) == 1 and x in abc) for x in l]) for l in s]), "Sudoku vsebuje neveljavne simbole!" else: assert None not in abc, "Abeceda ne sme vsebovati None!" assert all([all([x == None or x in abc for x in l]) for l in s]), "Sudoku vsebuje neveljavne simbole!" assert n == r*r, "Velikost abecede ni popoln kvadrat!" assert len(s) == n, "Število vrstic se ne ujema s številom znakov!" assert all([len(l) == n for l in s]), "Število stolpcev se ne ujema s številom znakov!" l = [] for i in range(n): for j in range(n): if s[i][j] != None: # Obstoječa števila t = abc.index(s[i][j]) for k in range(n): if k == t: l.append("r%dc%dv%d" % (i, j, k)) else: l.append(prop.Not("r%dc%dv%d" % (i, j, k))) else: # Vsako polje ima natanko eno vrednost for k in range(n): l.append(prop.iff("r%dc%do%d" % (i, j, k), prop.And([("r%dc%dv%d" % (i, j, x) if x == k else prop.Not("r%dc%dv%d" % (i, j, x))) for x in range(n)]))) l.append(prop.Or(["r%dc%do%d" % (i, j, k) for k in range(n)])) # V vsaki vrstici se pojavi vsaka vrednost l.append(prop.Or(["r%dc%dv%d" % (j, x, i) for x in range(n)])) # V vsakem stolpcu se pojavi vsaka vrednost l.append(prop.Or(["r%dc%dv%d" % (x, j, i) for x in range(n)])) # V vsakem kvadratu se pojavi vsaka vrednost for j in range(r): for k in range(r): l.append(prop.Or(sum([["r%dc%dv%d" % (r*j+x, r*k+y, i) for x in range(r)] for y in range(r)], []))) return prop.And(l)