diff --git a/torgan/AbstractGrid.py b/torgan/AbstractGrid.py new file mode 100644 index 0000000..c034c30 --- /dev/null +++ b/torgan/AbstractGrid.py @@ -0,0 +1,44 @@ +from Word import Word + +class AbstractGrid: + """ Presents structure of a grid, contains lists of horizontal and vertical words without words""" + def __init__(self): + self.horizontal_words = [] + self.vertical_words = [] + + def __extract_words_coordinates(self, list): + words_coordinates = [] + j = 0 # index of current cell + length = len(list) + while j < length: + while j < length and list[j] == '_': + j += 1 + if j != length: + x1 = j + while j < length and list[j] == '*': + j += 1 + x2 = j - 1 + if x2 - x1 > 1: + words_coordinates.append((x1, x2)) + return words_coordinates + + def parse_matrix(self, matrix): + for i in xrange(len(matrix)): + words_coordinates = self.__extract_words_coordinates(matrix[i]) + for (x1, x2) in words_coordinates: + self.horizontal_words.append(Word(i, x1, x2)) + for j in xrange(len(matrix[0])): + vertical_list = [list[j] for list in matrix] + words_coordinates = self.__extract_words_coordinates(vertical_list) + for (y1, y2) in words_coordinates: + self.vertical_words.append(Word(j, y1, y2)) + self.__build_tree(self.horizontal_words[0], False) + + def __build_tree(self, parent, is_vertical): + parent.flag = 1 + cross_list = self.horizontal_words if is_vertical else self.vertical_words + for cross in cross_list: + if cross.flag != 1 and parent.check_cross(cross): + parent.children.append(self.__build_tree(cross, not is_vertical)) + return parent + diff --git a/torgan/Crossword.py b/torgan/Crossword.py new file mode 100644 index 0000000..c668f86 --- /dev/null +++ b/torgan/Crossword.py @@ -0,0 +1,46 @@ +from AbstractGrid import AbstractGrid + +class Crossword(AbstractGrid): + """ Class extends empty abstract grid with ability to work with input dictionary words""" + + def fill_with_words(self, word_list): + return self.__dfs(self.horizontal_words[0], word_list) + + def __validate_grid(self): + for word in self.horizontal_words: + for cross in self.vertical_words: + if word.check_cross(cross): + if cross.value is not None and word.value is not None and not word.check_cross_value(cross): + return False + return True + + def __dfs(self, root, available_dict): + copied_dict = available_dict[0:] + is_right = False + + for word in root.get_right_words(available_dict): + root.value = word + if self.__validate_grid(): + is_right = True + copied_dict.remove(word) + for child in root.children: + is_right &= self.__dfs(child, copied_dict) + filled_words = self.__get_filled_words(child) + copied_dict = [item for item in copied_dict if item not in filled_words] + if is_right: + return True + else: + copied_dict.extend(self.__get_filled_words(root)) + self.__clean_up(root) + return is_right + + def __clean_up(self, root): + root.value = None + for child in root.children: + self.__clean_up(child) + + def __get_filled_words(self, root): + values = [root.value] if root.value is not None else [] + for child in root.children: + values.extend(self.__get_filled_words(child)) + return values \ No newline at end of file diff --git a/torgan/Main.py b/torgan/Main.py new file mode 100644 index 0000000..d1973b4 --- /dev/null +++ b/torgan/Main.py @@ -0,0 +1,41 @@ +from Crossword import Crossword + +file = open("grid.txt") +input_grid = [] +for line in file.readlines(): + input_grid.append(line.split()) +file.close() + +file = open("dict.txt") +input_dict = [] +for line in file.readlines(): + input_dict.extend(line.split()) +file.close() + +# TODO: add exception handling for: working with files, validate input - grid's format + +crossword = Crossword() +crossword.parse_matrix(input_grid) +is_right = crossword.fill_with_words(input_dict) + +if is_right: + for word in crossword.horizontal_words: + if word.value is not None: + input_grid[word.item][word.start : word.end + 1] = word.value + for word in crossword.vertical_words: + if word.value is not None: + for line in input_grid: + if word.start <= input_grid.index(line) <= word.end: + line[word.item] = word.value[input_grid.index(line) - word.start] + for line in input_grid: + print line +else: + print "Error! Can not fill crossword with that dictionary!" + + + + + + + + diff --git a/torgan/Word.py b/torgan/Word.py new file mode 100644 index 0000000..dc3509f --- /dev/null +++ b/torgan/Word.py @@ -0,0 +1,25 @@ +class Word: + """ + Presents structure of a grid's word + item - row(or column) at the grid + start, end - start and end coordinates at row(column) + """ + def __init__(self, item, start, end): + self.item = item + self.start = start + self.end = end + self.value = None + self.children = [] + self.flag = 0 # ony for building tree + + def check_cross_value(self, word): + if self.check_cross(word) : + return self.value[word.item - self.start] == word.value[self.item - word.start] + return True + + def check_cross(self, word): + return word.start <= self.item <= word.end and self.start <= word.item <= self.end + + def get_right_words(self, word_list): + result = [word for word in word_list if len(word) == self.end - self.start + 1] + return result \ No newline at end of file diff --git a/torgan/dict.txt b/torgan/dict.txt new file mode 100644 index 0000000..8abae7b --- /dev/null +++ b/torgan/dict.txt @@ -0,0 +1,78 @@ +also +nip +ussr +mohr +parus +fete +odin +stoma +oman +revisionary +itt +ted +aery +ethnic +phloem +axe +tulsa +plaid +nash +miens +erne +acted +fails +leg +tariff +coneys +mana +gun +ode +tridiagonal +tins +adorn +ucla +into +dotes +gamy +sass +les +haas +amor +ana +otis +lode +exact +dina +shiv +testaments +ornith +hera +sos +sent +dint +psidium +farad +nato +cliff +idol +iron +sea +dote +puma +panic +ires +sarah +slogans +yelp +snug +ufo +role +enough +semiyearly +ncaa +stat +mines +alma +rent +deg +lays \ No newline at end of file diff --git a/torgan/grid.txt b/torgan/grid.txt new file mode 100644 index 0000000..a03bb58 --- /dev/null +++ b/torgan/grid.txt @@ -0,0 +1,15 @@ +* * * * _ _ * * * _ _ * * * * +* * * * _ * * * * * _ * * * * +* * * * _ * * * * * _ * * * * +* * * * * * * * * * * _ * * * +_ _ _ * * * _ _ _ * * * * _ _ +_ * * * * * * _ * * * * * * _ +* * * _ * * * * * _ * * * * * +* * * * _ * * * * * _ * * * * +* * * * * _ * * * * * _ * * * +_ * * * * * * _ * * * * * * _ +_ _ * * * * _ _ _ * * * _ _ _ +* * * _ * * * * * * * * * * * +* * * * _ * * * * * _ * * * * +* * * * _ * * * * * _ * * * * +* * * * _ _ * * * _ _ * * * * \ No newline at end of file