def make_clue_list(clue_map: ClueMap) -> Sequence[Clue]: def generator(clue_value: int) -> ClueValueGenerator: def result(_: Clue) -> Iterable[str]: values_list = [v for (v, _) in clue_map[clue_value]] for values in values_list: string = ''.join(map(str, values)) for i in range(5): temp = ''.join(string[i:] + string[:i]) yield temp yield temp[::-1] return result clues = [] for (letter, value), location in zip(ACROSS, itertools.product((1, 3, 5, 7, 9), (1, 5))): clues.append( Clue(letter.upper(), True, location, 5, context=value, generator=generator(value))) for (letter, value), location in zip(DOWNS, itertools.product((1, 5), (1, 3, 5, 7, 9))): clues.append( Clue(letter, False, location, 5, context=value, generator=generator(value))) return clues
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 get_clue_list() -> Sequence[Clue]: possibilities = ((3, 3), (2, 2, 2), (1, 2, 3), (1, 3, 2), (3, 1, 2), (3, 2, 1), (2, 1, 3), (2, 3, 1), (1, 2, 1, 2), (2, 1, 2, 1), (1, 2, 2, 1)) for rows in itertools.product(possibilities, repeat=3): acrosses: Dict[Tuple[int, int], int] = {} downs: Dict[Tuple[int, int], int] = {} for row, lengths in enumerate(rows, start=1): column = 1 for length in lengths: if length != 1: acrosses[row, column] = length downs[column, 7 - row] = length acrosses[7 - row, 7 - column - (length - 1)] = length downs[7 - column - (length - 1), row] = length column += length assert column == 7 number_to_clue_start = Solver212.verify_is_legal_grid(acrosses, downs) if number_to_clue_start: result = [] for number, clue_start in number_to_clue_start.items(): if clue_start in acrosses: result.append(Clue(f'{number}a', True, clue_start, acrosses[clue_start])) if clue_start in downs: result.append(Clue(f'{number}d', False, clue_start, downs[clue_start])) return result return ()
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(name: str, base_location: Location, length: int, generator: ClueValueGenerator) -> Clue: return Clue(name, name[0] == 'A', base_location, length, generator=generators.using_current_base(generator))
def make(name: str, base_location: Location, length: int, generator: Optional[ClueValueGenerator]) -> Clue: return Clue(name, name[0] == 'A', base_location, length, generator=generator)
def make_clue_list() -> Sequence[Clue]: locations = {} for row, line in enumerate(MAP.split()): for column, item in enumerate(line): if item != '.': locations[item] = row + 1, column + 1 clues = [] for is_across, suffix, clue_info in ((True, 'a', ACROSS), (False, 'd', DOWN)): for line in clue_info.split('\n'): if not line: continue match = re.fullmatch( r'([a-z])\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s*', line) assert match letter = match.group(1) values = [int(match.group(i)) for i in range(2, 7)] length = int(match.group(7)) location = locations[letter] clue = Clue(f'{letter}{suffix}', is_across, location, length, generator=generator(values)) 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_expressions() -> Sequence[Clue]: clues = [] for line in CLUES.splitlines(): name = line[0] expression = line[2:] expression = re.sub(r"([A-Z])(\d)", r"(\1**\2)", expression) clue = Clue(name, True, (0, 0), 1, expression=expression) clues.append(clue) return tuple(clues)
def make(name: str, expression: str, num_letters: int, length: int, base_location: Location) -> 'Clue': return Clue(name, name.isupper(), base_location, length, context=expression, generator=my_generator(num_letters), expression=expression)
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 make(name: str, length: int, base_location: Location, *, generator: Optional[ClueValueGenerator] = None) -> 'Clue': return Clue(name, name.isupper(), base_location, length, generator=generator or generators.allvalues)
def make_clue_list(info: str) -> Sequence[Clue]: clues = [] for line in info.splitlines(): if not line: continue match = re.fullmatch(r'(\d+) (\d) (.*)', line) assert match # We don't care about the location. We just care about the length clue = Clue(match.group(1), True, (1, 1), int(match.group(2)), expression=match.group(3)) clues.append(clue) return clues
def run(entries: Sequence[ClueValue]) -> None: def generator(a_clue: Clue) -> Iterable[str]: return (entry for entry in entries if len(entry) == a_clue.length) clues = [] for suffix, is_across, clue_info in (('a', True, ACROSS), ('d', False, DOWN)): for xy, length in clue_info: q, r = divmod(xy - 11, 10) clue = Clue(f'{xy}{suffix}', is_across, (q + 1, r + 1), length, generator=generator) clues.append(clue) solver = InnerSolver(clues) solver.solve()
def create_from_text(across: str, down: str, locations: Sequence[Location]) -> Sequence[Clue]: 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+)\) \((\d+)\)', line) assert match number = int(match.group(1)) location = locations[number - 1] clue = Clue(f'{number}{letter}', is_across, location, int(match.group(3)), expression=match.group(2)) clue.context = int(match.group(4)) result.append(clue) return result
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 create_to_type_dict() -> Dict[str, AnswerType]: # Creates a map from legal entry values to the answer type of that entry. Values are only allowed to belong # to one type. creator: Tuple[Tuple[AnswerType, ClueValueGenerator], ...] = ( (AnswerType.Fibonacci, generators.fibonacci), (AnswerType.Square, generators.square), (AnswerType.Triangle, generators.triangular), (AnswerType.Prime, generators.prime), (AnswerType.Palindrome, generators.palindrome)) items = [(length, answer_type, str(value)) for length in (1, 2, 3) for answer_type, generator in creator for value in generator(Clue('fake', True, (1, 1), length))] # count the number of times each value appears in the list of items. counter = collections.Counter(value for _, _, value in items) # create a map from the value to the type of the value, for those values that are a member # of only one group. return {value: answer_type for (_, answer_type, value) in items if counter[value] == 1}
def create(length_1a: int, length_4a: int, length_5a: int, length_2d: int, length_3d: int, location_5a: Location, grid: Optional[str] = None) -> "Solver204": clues = [ Clue('1a', True, (1, 1), length_1a, generator=GENERATOR_1a), Clue('4a', True, (2, 1), length_4a, generator=GENERATOR_4a), Clue('5a', True, location_5a, length_5a, generator=GENERATOR_5a), Clue('2d', False, (1, 2), length_2d, generator=GENERATOR_2d), Clue('3d', False, (1, 3), length_3d, generator=GENERATOR_3d), Clue('4d', False, (2, 1), 2, generator=GENERATOR_4d) ] grid = grid or f'{length_1a}{length_4a}{length_5a}{length_2d}{length_3d}{location_5a[1]}' return Solver204(grid, clues)
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 create_clue_list() -> Sequence[Clue]: locations = [(0, 0)] for row, line in enumerate(GRID.split()): for column, item in enumerate(line): if item == 'X': locations.append((row + 1, column + 1)) result: List[Clue] = [] for lines, is_across, suffix in ((ACROSS, True, 'a'), (DOWN, False, 'd'), (THROUGH, False, 't')): 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)) location = locations[number] expression = match.group(2) length = int(match.group(3)) row, column = location if suffix == 'd': location_list = [(row + i, column) for i in range(length)] elif suffix == 't': location_list = [(row + 4 * i, column) for i in range(length)] elif suffix == 'a': temp = [(row, column + i) for i in range(length)] location_list = [(row + ((column - 1) // 4) * 4, ((column - 1) % 4) + 1) for (row, column) in temp] else: assert False clue = Clue(f'{number}{suffix}', is_across, location, length, expression=expression, locations=location_list) result.append(clue) return result
def make_clue_list(lines: str, acrosses: str, downs: str) -> List[Clue]: locations = [(0, 0)] for row, line in enumerate(lines.split()): for column, item in enumerate(line): if item == 'X': locations.append((row + 1, column + 1)) clues = [] for is_across, suffix, clue_info in ((True, 'a', acrosses), (False, 'd', downs)): for line in clue_info.split('\n'): if not line: continue match = re.fullmatch(r'(\d+) (\d+)', line) assert match number = int(match.group(1)) info = match.group(2) clue = Clue(f'{number}{suffix}', is_across, locations[number], len(info), generator=generators.known(*MY_TABLE[info])) clues.append(clue) 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 make_clue_list(self) -> List[Clue]: known = [value for _, value in self.clue_primes] generator = generators.known(*known) return [ Clue('a', True, (1, 2), 2, generator=generator), Clue('b', True, (1, 4), 2, generator=generator), Clue('c', True, (2, 1), 2, generator=generator), Clue('d', True, (2, 3), 3, generator=generator), Clue('e', True, (3, 2), 3, generator=generator), Clue('f', True, (4, 1), 3, generator=generator), Clue('g', True, (4, 4), 2, generator=generator), Clue('h', True, (5, 1), 2, generator=generator), Clue('i', True, (5, 3), 2, generator=generator), Clue('j', False, (1, 1), 2, generator=generator), Clue('k', False, (1, 2), 3, generator=generator), Clue('l', False, (1, 4), 2, generator=generator), Clue('m', False, (2, 3), 3, generator=generator), Clue('n', False, (2, 5), 2, generator=generator), Clue('o', False, (3, 1), 2, generator=generator), Clue('p', False, (3, 4), 3, generator=generator), Clue('q', False, (4, 2), 2, generator=generator), Clue('r', False, (4, 5), 2, generator=generator), ]
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