Skip to content
97 changes: 97 additions & 0 deletions dancing_links/python/KelKum/algorithm_x.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import incidence_matrix
import pentominos
import examples
import copy

class Algorithm_X(object):
def __init__(self, matrix):
self.matrix = matrix
#print(self.matrix.columnObjectOfName.keys())
#self.o = []
self.search(0, [])
#print(self.matrix.representation())

def search(self, k, o):
#print("search k = " + str(k) + " R[h] = " + str(self.matrix.h.right.name))
if self.matrix.h.right == self.matrix.h:
print("All pentominos placed")
print_current_solution(o)
return
c = self.chooseColumnObj()
self.matrix.coverColumn(c)
#print("column c covered")
#print(str(c.representation()))
r = c.down
while r is not c:
#print(str(r.name) + " " + str(c.down.name))
#o.append(r)
j = r.right
while j is not r:
#print(str(j.name) + " " + str(j.listHeader.name))
self.matrix.coverColumn(j.listHeader)
j = j.right
self.search(k + 1, o + [r])
j = r.left
while j is not r:
self.matrix.uncoverColumn(j.listHeader)
j = j.left
r = r.down
self.matrix.uncoverColumn(c)

def print_current_solution(self, o):
for obj in o:
s = str(obj.listHeader.name)
r = obj.right
while r is not obj:
s += " " + str(r.listHeader.name)
r = r.right
print(s + "\n")
print("\n")

def chooseColumnObj(self):
#print("choose column object")
c = self.matrix.h
s = 1e100000
j = self.matrix.h.right
while j is not self.matrix.h and not incidence_matrix.is_number(j.name):
if j.size < s:
c = j
s = j.size
j = j.right
#print(str(c.representation()))
return c

def append_all_possible_placements(matrix):
names = []
tiles = []
currentColumnObject = matrix.h.right
while currentColumnObject.name is not "root":
if incidence_matrix.is_number(currentColumnObject.name):
tiles.append(currentColumnObject.name)
else:
names.append(currentColumnObject.name)
currentColumnObject = currentColumnObject.right
pset = pentominos.fixed_pentominos_of_name_list(names)
#print(str(len(names)) + " " + str(pset.size()))
max0 = max([int(s[0]) for s in tiles])
max1 = max([int(s[1]) for s in tiles])
#print(str(max0) + " " + str(max1))
for p in pset.set:
for i in range(0, max0):
for j in range(0, max1):
q = copy.deepcopy(p)
q.translate_by([i, j])
if matrix.is_valid_placement(q.coos):
matrix.appendRow(q.name, [str(c[0]) + str(c[1]) for c in q.coos])

def run_scott_example():
matrix = examples.scott_example()
#print(str(matrix.representation()))
append_all_possible_placements(matrix)
#print(str(matrix.representation()))
Algorithm_X(matrix)

if __name__ == '__main__':
run_scott_example()


26 changes: 26 additions & 0 deletions dancing_links/python/KelKum/examples.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import incidence_matrix

def running_example():
I = incidence_matrix.IncidenceMatrix(["A", "B", "C", "D", "E", "F", "G"])
I.appendRow("C", ["E", "F"])
I.appendRow("A", ["D", "G"])
I.appendRow("B", ["C", "F"])
I.appendRow("A", ["D"])
I.appendRow("B", ["G"])
I.appendRow("D", ["E", "G"])
return I

def AllowOutsideHole(c):
if c not in [[3,3],[3,4],[4,3],[4,4]]:
return True
else:
return False

def scott_example():
names = ["F", "I", "L", "P", "N", "T", "U", "V", "W", "X", "Y", "Z"]
for i in range(8):
for j in range(8):
if AllowOutsideHole([i,j]):
names.append(str(i)+str(j))
return incidence_matrix.IncidenceMatrix(names)

156 changes: 156 additions & 0 deletions dancing_links/python/KelKum/incidence_matrix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
def is_number(string):
try:
float(string)
return True
except ValueError:
pass
return False


class IncidenceCell(object):
def __init__(self, left, right, up, down, listHeader, name):
self.left = left
self.right = right
self.up = up
self.down = down
self.listHeader = listHeader
self.name = name

def representation(self):
rep = ["c", self.name]
for c in [self.left, self.right, self.up, self.down]:
rep.append(c.name)
return rep


class ColumnObject(IncidenceCell):
def __init__(self, left, right, up, down, name):
IncidenceCell.__init__(self, left, right, up, down, self, name)
self.size = 0

def representation(self):
hrep = ["h(" + str(self.size) + ")", self.name]
for c in [self.left, self.right, self.up, self.down]:
hrep.append(c.name)
rep = [[hrep]]

currentCell = self.down
while currentCell is not self:
rep[0].append(currentCell.representation())
currentCell = currentCell.down

return rep


class IncidenceMatrix(object):
def __init__(self, names):
self.h = ColumnObject(None, None, None, None, "root")
self.h.left = self.h.right = self.h.up = self.h.down = self.h

currentColumnObject = self.h
self.columnObjectOfName = dict()
self.columnObjectOfName["root"] = self.h

self.indexOfPiecePlacement = dict()
for n in names:
self.indexOfPiecePlacement[n] = 0
self.insertColumnObject(currentColumnObject, self.h, n)
currentColumnObject = currentColumnObject.right
self.columnObjectOfName[n] = currentColumnObject

self.rows = 0

def representation(self):
currentColumnObject = self.h

rep = currentColumnObject.representation()
currentColumnObject = currentColumnObject.right

while currentColumnObject.name is not "root":
rep += currentColumnObject.representation()
currentColumnObject = currentColumnObject.right

return rep

def rowRepresentation(self):
rowRep = []
currentColumnObject = self.h.right
while currentColumnObject.name is not "root" and not is_number(currentColumnObject.name):
head_elt = currentColumnObject.down
while head_elt is not currentColumnObject:
row = [ head_elt.name ]
current_elt = head_elt.right
while current_elt is not head_elt:
row.append(current_elt.listHeader.name)
current_elt = current_elt.right
rowRep.append(row)
head_elt = head_elt.down
currentColumnObject = currentColumnObject.right
return rowRep

def insertColumnObject(self, left, right, name):
colobj = ColumnObject(left, right, None, None, name)
colobj.up = colobj.down = colobj
left.right = colobj
right.left = colobj

def appendRow(self, tileName, placement):
""" a placement is a list of coordinates that indicates which squares the piece named tileName covers"""
tile = self.columnObjectOfName[tileName]
cell = IncidenceCell(None, None, tile.up, tile, tile, str(tile.name) + "[" + str(self.indexOfPiecePlacement[tileName]) + "]")
self.indexOfPiecePlacement[tileName] += 1
tile.up.down = tile.up = cell
tile.size += 1
for place in placement:
pcol = self.columnObjectOfName[place]
pcell = IncidenceCell(None, None, pcol.up, pcol, pcol, str(tile.name) + str(pcol.name))
pcol.up.down = pcell
pcol.up = pcell
pcell.left = cell
cell.right = pcell
cell = pcell
pcol.size += 1
cell.right = tile.up
tile.up.left = cell

def coverColumn(self, c):
#print(str(c.name))
c.right.left = c.left
c.left.right = c.right
currow = c.down
while currow is not c:
curcell = currow.right
while curcell is not currow:
curcell.down.up = curcell.up
curcell.up.down = curcell.down
curcell.listHeader.size -= 1
curcell = curcell.right
#print(str(currow.name) + " " + str(curcell.name))
currow = currow.down

def uncoverColumn(self, c):
currow = c.up
while currow is not c:
curcell = currow.left
while curcell is not currow:
curcell.down.up = curcell
curcell.up.down = curcell
curcell.listHeader.size += 1
curcell = curcell.left
currow = currow.up
c.right.left = c
c.left.right = c

def is_valid_placement(self, coos):
tiles = []
j = self.h.right
while j is not self.h:
if is_number(j.name):
tiles.append(j.name)
j = j.right
for c in coos:
if str(c[0]) + str(c[1]) not in tiles:
#print(str(coos) + " is not valid")
return False
return True

Loading