diff --git a/server/crossword.py b/server/crossword.py index 299c14b..5e5c873 100644 --- a/server/crossword.py +++ b/server/crossword.py @@ -106,7 +106,7 @@ class LetterField(Field): class Grid(object): - def __init__(self, width: int, height: int, lang_code: str, density=0.8, difficulty: int = 0): + def __init__(self, width: int, height: int, lang_code: str, density=0.81, difficulty: int = 0): self._width = width self._height = height self._lang_code = lang_code diff --git a/server/crossword_generator.py b/server/crossword_generator.py index 032425c..702aff7 100644 --- a/server/crossword_generator.py +++ b/server/crossword_generator.py @@ -662,11 +662,11 @@ class GridCreationState(object): min_coord_max = min_xmax max_coord_max = max_xmax - n_options = max_coord_max - min_coord_max + max_coord_min - min_coord_min + n_options = (max_coord_max - min_coord_max) * (max_coord_min - min_coord_min) solved = False - for _ in range(min(n_options, n_retries)): + for _ in range(int(n_options * 1.5)): coord_min = random.randint(min_coord_min, max_coord_min) coord_max = random.randint(min_coord_max, max_coord_max) length = coord_max - coord_min @@ -733,13 +733,32 @@ class GridCreationState(object): return solved_state return None - def fill_grid(self, target_density: float = 0.6, inner_retries: int = 5, conflict_retries: int = 10, conflict_solver_depth=5, min_length: int = 4, max_length: int = 10, max_iterations: int = 1000): + def fill_grid(self, target_density: float = 0.6, inner_retries: int = 5, conflict_solver_depth=5, min_length: int = 4, max_length: int = 10, max_iterations: int = 1000): i = 0 state = self.copy() - while i < max_iterations and state.get_density() < target_density: + current_density = state.get_density() + while i < max_iterations and current_density < target_density: + current_density = state.get_density() i += 1 new_state = state.copy() - conflicts = new_state.place_random_word(min_length, max_length) + + + # try semi-dynamic word length (try longer words at the beginning) + min_length_offset = 0 + max_length_offset = 0 + + #min_length_offset = int((i / max_iterations) * (max_length - min_length)) + + #if current_density < 0.5 * target_density: + # min_length_offset = int(0.5 * (max_length - min_length) * (1 - (current_density / target_density))) + # #logging.info("mi %s",str(min_length_offset)) + + #if current_density > 0.9 * target_density: + # max_length_offset = - int(0.5 * (max_length - min_length) * ((current_density / target_density))) + # #logging.info("max %s",str(max_length_offset)) + + + conflicts = new_state.place_random_word(min_length + min_length_offset, max_length + max_length_offset) if conflicts is None: continue if len(conflicts) == 0: @@ -752,8 +771,8 @@ class GridCreationState(object): if solved_state is not None: state = solved_state - logging.info("finished after %s iterations, with a density of %s", str( - i), str(state.get_density())) + logging.info("finished after %s iterations, with a density of %s (desired density: %s)", str( + i), str(state.get_density()), str(target_density)) return state @@ -776,10 +795,11 @@ def create_word_grid(w: int, base_grid = GridCreationState(h=h, w=w, db=db, inverted_db=inverted_db) final_state = base_grid.fill_grid(target_density=target_density, - inner_retries=7, - conflict_solver_depth=20, - min_length=2, - max_iterations=max(75 * (w+h)/2, 1000)) + inner_retries=10, + conflict_solver_depth=10, + min_length=3, + max_length=int(min(w,h) * 0.6), + max_iterations=5000) # generate word hints @@ -849,6 +869,8 @@ def create_word_grid(w: int, if aborted: continue + + logging.info("solution word: %s", str(random_word)) solution_word_locations = solution