Module 18: Preventing Duplicates (Python code)

This commit is contained in:
David Doblas Jiménez 2021-09-09 15:47:30 +02:00
parent e7a24670b0
commit 9306376de2
1 changed files with 18 additions and 30 deletions

48
a.py
View File

@ -50,11 +50,9 @@ class Words:
class Library: class Library:
def __init__(self): def __init__(self):
# master vector of word self.words_ = Words() # master vector of word
self.words_ = Words()
self.counts_ = {} self.counts_ = {}
# hash table self.word_map_ = {} # hash table
self.word_map_ = {}
# Returns NULL if can't find any matches to the given pattern # Returns NULL if can't find any matches to the given pattern
def FindWord(self, s): def FindWord(self, s):
@ -64,7 +62,6 @@ class Library:
return s in self.word_map_ return s in self.word_map_
def ComputeStats(self): def ComputeStats(self):
# assert self.counts == {}
for i in range(18): for i in range(18):
self.counts_[i] = [] self.counts_[i] = []
for s in self.words_: for s in self.words_:
@ -75,7 +72,6 @@ class Library:
def PrintStats(self): def PrintStats(self):
print("Here are the counts of each word length") print("Here are the counts of each word length")
for k,v in self.counts_.items(): for k,v in self.counts_.items():
# print(v)
if k != 0: if k != 0:
print(f"[{k}] {len(v)}") print(f"[{k}] {len(v)}")
@ -86,15 +82,12 @@ class Library:
def CreatePatternHash(self, w): def CreatePatternHash(self, w):
len_w = len(w) len_w = len(w)
num_patterns = 1 << len_w num_patterns = 1 << len_w
# print(f"PATTERN HASH on {w}")
self.word_map_[w] = [] self.word_map_[w] = []
for i in range(num_patterns): for i in range(num_patterns):
# print(f" {i}")
tmp = list(w) tmp = list(w)
for j in range(len_w): for j in range(len_w):
if ((i >> j) & 1): if ((i >> j) & 1):
tmp[j] = "-" tmp[j] = "-"
# print(f' {"".join(tmp)}')
self.word_map_[w].append("".join(tmp)) self.word_map_[w].append("".join(tmp))
def ReadFromFile(self, filename, max_size): def ReadFromFile(self, filename, max_size):
@ -109,11 +102,10 @@ class Library:
def DebugBuckets(self): def DebugBuckets(self):
for i, (k,v) in enumerate(self.word_map_.items()): for i, (k,v) in enumerate(self.word_map_.items()):
print(f"[{i}] {len(v)}")# {self.word_map_[i]}") print(f"[{i}] {len(v)}")
lib = Library() lib = Library()
## ---------------------------------------------------------------------------- ## ----------------------------------------------------------------------------
##-Attr ##-Attr
class Attr: class Attr:
@ -243,14 +235,12 @@ class Grid:
if not self.in_bounds(p): if not self.in_bounds(p):
return return
startp = copy(p) startp = copy(p)
#print(f"SPAN START: {startp}")
len_ = 0 len_ = 0
keep_going = True keep_going = True
while (keep_going and not self.is_block(p)): while (keep_going and not self.is_block(p)):
keep_going = self.NextStopAtWrap(p, vert) keep_going = self.NextStopAtWrap(p, vert)
len_ += 1 len_ += 1
#print(f"END OF SPAN!!! len={len_}")
self.sp.append(Spans(startp, len_, vert)) self.sp.append(Spans(startp, len_, vert))
def FillSpans(self): def FillSpans(self):
@ -260,7 +250,6 @@ class Grid:
def LoadFromFile(self, filename): def LoadFromFile(self, filename):
with open(filename, 'r') as f: with open(filename, 'r') as f:
for line in f: for line in f:
#print(f"{line.rstrip()} ({len(line.rstrip())})")
if not line.startswith('#'): if not line.startswith('#'):
self.lines.append(list(line.rstrip())) self.lines.append(list(line.rstrip()))
@ -301,6 +290,13 @@ class Solver:
def __init__(self): def __init__(self):
pass pass
def ExistsInSet(self, set_, s):
return s in set_
def AddToSet(self, set_, s):
assert(not self.ExistsInSet(set_, s))
set_.add(s)
def Solve(self, grid): def Solve(self, grid):
print(f"Solving this grid") print(f"Solving this grid")
@ -309,9 +305,6 @@ class Solver:
def Loop(self, grid, depth): def Loop(self, grid, depth):
depth += 1 depth += 1
#if depth > 3:
#print(f"Aborting loop because depth={depth}")
#return
empty_slots = [] empty_slots = []
partial_slots = [] # these are the ones we want to work on partial_slots = [] # these are the ones we want to work on
@ -330,17 +323,19 @@ class Solver:
num_empty = len(empty_slots) num_empty = len(empty_slots)
num_partial = len(partial_slots) num_partial = len(partial_slots)
num_full = len(full_slots) num_full = len(full_slots)
# print(f"empty = {num_empty}")
# print(f"partial = {num_partial}")
# print(f"full = {num_full}")
# need to check that all words so far are valid! # need to check that all words so far are valid!
for slot in full_slots: for slot in full_slots:
#print(f"CHECKING {slot.pattern} if it is a word")
if not lib.IsWord(slot.pattern): if not lib.IsWord(slot.pattern):
#print(" --> NOT! ABORT")
return return
# need to check that all words are unique! no duplicates allowed.
my_set = set()
for slot in full_slots:
if self.ExistsInSet(my_set, slot.pattern):
return
self.AddToSet(my_set, slot.pattern)
if (num_partial == 0 and num_empty == 0): if (num_partial == 0 and num_empty == 0):
print("SOLUTION!!") print("SOLUTION!!")
grid.Print() grid.Print()
@ -351,20 +346,13 @@ class Solver:
def CommitSlot(self, grid, slot, depth): def CommitSlot(self, grid, slot, depth):
grid = deepcopy(grid) grid = deepcopy(grid)
# print(f"COMMIT slot {slot}")
# print(f"Possible word choices for this slot are:")
words = lib.FindWord(slot.pattern) words = lib.FindWord(slot.pattern)
if words: if words:
for w in words: for w in words:
#print(f"{' '.join(words)}")
#print(f" Committing '{w}'!")
grid.WriteString(slot.span, w) grid.WriteString(slot.span, w)
#print("New grid is:")
#grid.Print()
self.Loop(grid, depth) self.Loop(grid, depth)
#else:
#print("NO MATCHES to pattern")
## ---------------------------------------------------------------------------- ## ----------------------------------------------------------------------------
if __name__ == "__main__": if __name__ == "__main__":
grid = Grid("MY GRID") grid = Grid("MY GRID")