def test() -> None: # For testing this class on its own, without needing OuterSolver locations = Clues.get_locations_from_grid(GRID) clue_list = Clues.create_from_text(ACROSS, DOWN, locations) solution = { 'H': 1, 'E': 2, 'S': 3, 'N': 4, 'I': 5, 'G': 6, 'L': 7, 'R': 8, 'T': 9, 'D': 10, 'A': 11, } letter_values = { Letter(letter): value for letter, value in solution.items() } # Evaluate each of the clues clue_values = { clue: clue.evaluators[0](letter_values) for clue in clue_list } solver = InnerSolver(clue_list, clue_values, letter_values) solver.solve(debug=False)
def run() -> None: locations = Clues.get_locations_from_grid(LOCATIONS) clue_list = Clues.create_from_text(ACROSS, DOWN, locations) solver = EquationSolver(clue_list, items=tuple(range(1, 17)), allow_duplicates=True) solver.verify_is_four_fold_symmetric() solver.solve()
def create_clue_list(alt: bool = False) -> Sequence[Clue]: locations = Clues.get_locations_from_grid(GRID) result: List[Clue] = [] for lines, is_across, letter in ((ACROSS, True, 'a'), (DOWN, False, 'd')): for line in lines.splitlines(): line = line.strip() if not line: continue match = re.fullmatch(r'(\d+) (.*) \((\d+)\)', line) assert match number = int(match.group(1)) expression = match.group(2) location = locations[number - 1] if '”' in expression: if alt: expression = '+'.join(f'str({ch})' for ch in expression[1:-1]) expression = f'@ int({expression})' clue = Clue(f'{number}{letter}', is_across, location, int(match.group(3)), expression=expression) result.append(clue) else: for ch in expression[1:-1]: length = 1 if ch in 'TOM' else 2 clue = Clue(f'{number}{ch}{letter}', is_across, location, length, expression=ch) result.append(clue) (row, column) = location location = (row, column + length) if is_across else (row + length, column) else: if not alt and number == 47: clue = Clue(f'{number}{letter}', is_across, location, int(match.group(3))) elif not alt and number in (5, 15, 16): continue else: clue = Clue(f'{number}{letter}', is_across, location, int(match.group(3)), expression=expression) result.append(clue) return result
def make_clue_list(self) -> Sequence[Clue]: locations = Clues.get_locations_from_grid(GRID) clues = [] for lines, is_across, letter in ((ACROSS, True, 'a'), (DOWN, False, 'd')): for line in lines.splitlines(): line = line.strip() if not line: continue match = re.fullmatch(r'(\d+) (.*) \((\d+)\)', line) assert match number = int(match.group(1)) equation = match.group(2) length = int(match.group(3)) location = locations[number - 1] # Put an exponent (e.g. **a, **b, **c) after each number. def replacer(xmatch: Match[str]) -> str: variable = chr(xmatch.end(0) + ord('A')) return xmatch.group(0) + '**' + variable equation = re.sub(r'(\d+)', replacer, equation) clue = Clue(f'{number}{letter}', is_across, location, length, expression=equation, generator=self.generator) clues.append(clue) return clues
def make_clue_list() -> Sequence[Clue]: locations = Clues.get_locations_from_grid( GRID) # first location is index 0 clues = [ Clue(str(i), i in ACROSSES, locations[i - 1], LENGTHS[i]) for i in range(1, len(LENGTHS)) ] return clues
def make_clue_list() -> Sequence[Clue]: locations = Clues.get_locations_from_grid(GRID) clues = [] for (is_across, clue_info, suffix) in (True, ACROSS, 'a'), (False, DOWN, 'd'): for name, length, generator, in clue_info: generator = generator or all_values clue = Clue(name + suffix, is_across, locations[int(name, 16) - 1], length, generator=generator) clues.append(clue) return clues
def run() -> None: grid = Clues.get_locations_from_grid(GRID) clues = OuterSolver.create_from_text(ACROSS, DOWN, grid) solver = OuterSolver(clues) for clue in clues: if clue.name in ('8d', '24d', '29d'): solver.add_constraint([clue], lambda value: value == value[::-1]) else: solver.add_constraint([clue], lambda value: value != value[::-1]) solver.solve(debug=True)
def make_clue_list( lines: str, acrosses: Sequence[Tuple[int, int, ClueValueGenerator]], downs: Sequence[Tuple[int, int, ClueValueGenerator]]) -> List[Clue]: locations = Clues.get_locations_from_grid(lines) clues = [ Clue(f'{location}{suffix}', is_across, locations[location - 1], length, generator=generator) for is_across, suffix, clue_set in ((True, 'a', acrosses), (False, 'd', downs)) for (location, length, generator) in clue_set ] return clues
def test() -> None: letters = (('A', 3), ('T', 7), ('K', 18), ('V', 17), ('B', 10), ('R', 5), ('N', 9), ('L', 11), ('M', 19), ('E', 6), ('S', 1), ('I', 8), ('W', 13), ('G', 4), ('D', 15), ('C', 2), ('O', 14), ('U', 16), ('H', 12)) print(', '.join(x for x, _ in letters), '=', ', '.join(str(x) for _, x in letters)) letter_values = {Letter(letter): value for letter, value in letters} grid = Clues.get_locations_from_grid(GRID) clues = OuterSolver.create_from_text(ACROSS, DOWN, grid) clue_values: KnownClueDict = { clue: clue.evaluators[0](letter_values) for clue in clues } solver = InnerSolver(clues, clue_values, letter_values) solver.solve(debug=True)
def get_clue_list() -> Sequence[Clue]: grid_locations = Clues.get_locations_from_grid(GRID) def generator(clue: Clue) -> Sequence[int]: length = clue.length delta = cast(int, clue.context) return make_puzzle_table()[length, delta] clues = [] for lines, is_across, letter in ((INUNDATION, True, 'i'), (HARVEST, False, 'h'), (PLANTING, False, 'p')): for line in lines.splitlines(): line = line.strip() if not line: continue match = re.fullmatch(r'(\d+) (\d+) \((\d+)\)', line) assert match number, delta, length = int(match.group(1)), int( match.group(2)), int(match.group(3)) (row, column) = grid_locations[number - 1] if letter == 'i': locations = [(row, column + i) for i in range(length)] elif letter == 'h': locations = [(row, column)] while len(locations) < length: row, column = (row, column - 1) if column % 2 == 0 else (row - 1, column + 1) locations.append((row, column)) else: locations = [(row, column)] while len(locations) < length: row, column = (row, column - 1) if column % 2 == 1 else (row + 1, column - 1) locations.append((row, column)) clue = Clue(f'{number}{letter}', is_across, (row, column), length, locations=locations, context=delta, generator=generator) clues.append(clue) return clues
def get_clue_list() -> Sequence[Clue]: grid_locations = [None] + Clues.get_locations_from_grid(GRID) clues = [ Clue("1a", True, grid_locations[1], 3, generator=filtering(lambda x: factor_count(x) == 6)), Clue("3a", True, grid_locations[3], 2, generator=allvalues), Clue("5a", True, grid_locations[5], 2, generator=filtering( lambda x: factor_count(factor_sum(x)) == 15)), Clue("6a", True, grid_locations[6], 3, generator=allvalues), Clue("8a", True, grid_locations[8], 3, generator=allvalues), Clue("10a", True, grid_locations[10], 3, generator=allvalues), Clue("12a", True, grid_locations[12], 2, generator=allvalues), Clue("14a", True, grid_locations[14], 2, generator=allvalues), Clue("15a", True, grid_locations[15], 3, generator=allvalues), Clue("1d", False, grid_locations[1], 2, generator=allvalues), Clue("2d", False, grid_locations[2], 3, generator=filtering( lambda x: factor_count(factor_sum(x)) == 16)), Clue("3d", False, grid_locations[3], 2, generator=allvalues), Clue("4d", False, grid_locations[4], 3, generator=allvalues), Clue("6d", False, grid_locations[6], 3, generator=allvalues), Clue("7d", False, grid_locations[7], 3, generator=generators.cube), Clue("9d", False, grid_locations[9], 3, generator=allvalues), Clue("11d", False, grid_locations[11], 2, generator=allvalues), Clue("13d", False, grid_locations[13], 2, generator=allvalues), ] return clues
def make_clue_list(self) -> Sequence[Clue]: def square_or_triangular(clue: Clue) -> Iterator[int]: yield from generators.square(clue) yield from generators.triangular(clue) locations = Clues.get_locations_from_grid(GRID) clues = [ Clue('1a', True, locations[0], 3, generator=generators.known(*[start for (start, _) in self.start_to_harshards.keys()])), Clue('2a', True, locations[1], 3, generator=generators.allvalues), Clue('4a', True, locations[3], 3, generator=square_or_triangular), Clue('8a', True, locations[7], 3, generator=square_or_triangular), Clue('9a', True, locations[8], 3, generator=generators.allvalues), Clue('10a', True, locations[9], 3, generator=generators.allvalues), Clue('1d', False, locations[0], 3, generator=generators.allvalues), Clue('3d', False, locations[2], 3, generator=generators.triangular), Clue('4d', False, locations[3], 3, generator=generators.known(*[delta for (_, delta) in self.start_to_harshards.keys()])), Clue('5d', False, locations[4], 2, generator=generators.allvalues), Clue('6d', False, locations[5], 2, generator=generators.allvalues), Clue('7d', False, locations[6], 3, generator=generators.allvalues), ] return clues
def run() -> None: locations = Clues.get_locations_from_grid(GRID) clue_list = Clues.create_from_text(ACROSS, DOWN, locations) solver = OuterSolver(clue_list, items=range(1, 12)) solver.verify_is_180_symmetric() solver.solve()
def make_clue_list(self) -> Sequence[Clue]: locations = Clues.get_locations_from_grid(GRID) return Clues.create_from_text(ACROSS, DOWN, locations)
def run() -> None: grid = Clues.get_locations_from_grid(GRID) clues = Clues.create_from_text(ACROSS, DOWN, grid) solver = OuterSolver(clues) solver.solve()
def run() -> None: locations = Clues.get_locations_from_grid(GRID) clue_list = Clues.create_from_text(ACROSS, DOWN, locations) solver = MySolver(clue_list, items=(2, 3, 5, 7, 11, 13, 4, 9, 25, 49, 121, 169)) solver.verify_is_180_symmetric() solver.solve(debug=False)