slightly improve crossword generation

This commit is contained in:
Jonas Weinz 2022-05-07 14:13:40 +02:00
parent 5c08922bec
commit d18c115a9c
2 changed files with 34 additions and 12 deletions

View File

@ -106,7 +106,7 @@ class LetterField(Field):
class Grid(object): 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._width = width
self._height = height self._height = height
self._lang_code = lang_code self._lang_code = lang_code

View File

@ -662,11 +662,11 @@ class GridCreationState(object):
min_coord_max = min_xmax min_coord_max = min_xmax
max_coord_max = max_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 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_min = random.randint(min_coord_min, max_coord_min)
coord_max = random.randint(min_coord_max, max_coord_max) coord_max = random.randint(min_coord_max, max_coord_max)
length = coord_max - coord_min length = coord_max - coord_min
@ -733,13 +733,32 @@ class GridCreationState(object):
return solved_state return solved_state
return None 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 i = 0
state = self.copy() 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 i += 1
new_state = state.copy() 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: if conflicts is None:
continue continue
if len(conflicts) == 0: if len(conflicts) == 0:
@ -752,8 +771,8 @@ class GridCreationState(object):
if solved_state is not None: if solved_state is not None:
state = solved_state state = solved_state
logging.info("finished after %s iterations, with a density of %s", str( logging.info("finished after %s iterations, with a density of %s (desired density: %s)", str(
i), str(state.get_density())) i), str(state.get_density()), str(target_density))
return state 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) base_grid = GridCreationState(h=h, w=w, db=db, inverted_db=inverted_db)
final_state = base_grid.fill_grid(target_density=target_density, final_state = base_grid.fill_grid(target_density=target_density,
inner_retries=7, inner_retries=10,
conflict_solver_depth=20, conflict_solver_depth=10,
min_length=2, min_length=3,
max_iterations=max(75 * (w+h)/2, 1000)) max_length=int(min(w,h) * 0.6),
max_iterations=5000)
# generate word hints # generate word hints
@ -850,6 +870,8 @@ def create_word_grid(w: int,
if aborted: if aborted:
continue continue
logging.info("solution word: %s", str(random_word))
solution_word_locations = solution solution_word_locations = solution
return final_state.letter_grid, word_hints, solution_word_locations return final_state.letter_grid, word_hints, solution_word_locations