def test_overlap_strategy(line, instructions, result_line): overlap_strategy = OverlapStrategy() input_line = CellsLine.parse_line(line) actual_result = overlap_strategy.solve(line=input_line, instructions=instructions) expected_result = CellsLine.parse_line(result_line) assert actual_result == expected_result if line != result_line: assert actual_result != input_line
def test_edge_strategy(line, instructions, result_line): edge_strategy = EdgeStrategy() input_line = CellsLine.parse_line(line) actual_result = edge_strategy.solve(line=input_line, instructions=instructions) expected_result = CellsLine.parse_line(result_line) assert actual_result == expected_result if line != result_line: assert actual_result != input_line
def test_sections_identification_strategy(line, instructions, result_line): sections_identification_strategy = SectionsIdentificationStrategy() input_line = CellsLine.parse_line(line) actual_result = sections_identification_strategy.solve( line=input_line, instructions=instructions) expected_result = CellsLine.parse_line(result_line) assert actual_result == expected_result if line != result_line: assert actual_result != input_line
def test_max_section_identifier_strategy(line, instructions, result_line): max_section_identifier_strategy = MaxSectionIdentifierStrategy() input_line = CellsLine.parse_line(line) actual_result = max_section_identifier_strategy.solve( line=input_line, instructions=instructions) expected_result = CellsLine.parse_line(result_line) assert actual_result == expected_result if line != result_line: assert actual_result != input_line
def test_parse_cells_line(): assert CellsLine.parse_line("X__OOO_X") == CellsLine([ CellMark.CROSSED, CellMark.EMPTY, CellMark.EMPTY, CellMark.FILLED, CellMark.FILLED, CellMark.FILLED, CellMark.EMPTY, CellMark.CROSSED, ])
def test_gaps_filler_strategy(line, instructions, result_line): gaps_filler_strategy = GapsFillerStrategy() input_line = CellsLine.parse_line(line) actual_result = gaps_filler_strategy.solve( line=input_line, instructions=instructions ) expected_result = CellsLine.parse_line(result_line) assert actual_result == expected_result if line != result_line: assert actual_result != input_line
def solve_one_way(self, line: CellsLine, instructions: List[int]) -> CellsLine: number_of_instructions = len(instructions) for instruction_index in range(number_of_instructions): end_index = self.get_end_index(line, instructions, instruction_index) start_index = self.get_start_index(line, instructions, instruction_index) if start_index > end_index: continue line.mark_inclusive(start_index, end_index, CellMark.FILLED) return line
def test_griddlers_board_get_rows_and_columns(): board = GriddlersBoard(rows=2, columns=3) board[0, 0] = CellMark.FILLED board[0, 1] = CellMark.FILLED board[1, 0] = CellMark.CROSSED board[1, 2] = CellMark.FILLED assert str(board) == "OO_\nX_O" assert board.get_row(0) == CellsLine.parse_line("OO_") assert board.get_row(1) == CellsLine.parse_line("X_O") assert board.get_column(0) == CellsLine.parse_line("OX") assert board.get_column(1) == CellsLine.parse_line("O_") assert board.get_column(2) == CellsLine.parse_line("_O")
def get_start_index(self, line: CellsLine, instructions: List[int], instruction_index: int): inverted_index = self.get_end_index( line=line.inverse(), instructions=instructions[::-1], instruction_index=self.inverse_index( index=instruction_index, list_length=len(instructions))) return self.inverse_index(inverted_index, len(line))
def test_cells_line_contains(): cells_line = CellsLine.parse_line("___OOO_O") assert CellMark.EMPTY in cells_line assert CellMark.FILLED in cells_line assert CellMark.CROSSED not in cells_line cells_line[1] = CellMark.CROSSED assert CellMark.CROSSED in cells_line
def test_cells_line_get_item(): cells_line = CellsLine.parse_line("X__OOO_X") assert cells_line[0] == CellMark.CROSSED assert cells_line[1] == CellMark.EMPTY assert cells_line[2] == CellMark.EMPTY assert cells_line[3] == CellMark.FILLED assert cells_line[4] == CellMark.FILLED assert cells_line[5] == CellMark.FILLED assert cells_line[6] == CellMark.EMPTY assert cells_line[7] == CellMark.CROSSED
def test_cells_line_sections_after_set(): cells_line = CellsLine.parse_line("X__OOO_X") cells_line[6] = CellMark.FILLED assert cells_line.sections == [ CellsSection(start=0, end=0, mark=CellMark.CROSSED, blocked_below=True), CellsSection(start=1, end=2, mark=CellMark.EMPTY, blocked_below=True), CellsSection(start=3, end=6, mark=CellMark.FILLED, blocked_above=True), CellsSection(start=7, end=7, mark=CellMark.CROSSED, blocked_above=True), ]
def test_cells_line_is_completed(): cell_line = CellsLine([ CellMark.CROSSED, CellMark.CROSSED, CellMark.FILLED, CellMark.FILLED, CellMark.FILLED, CellMark.FILLED, CellMark.FILLED, CellMark.CROSSED, ]) assert cell_line.is_completed
def test_cells_line_to_str(): cell_line = CellsLine([ CellMark.CROSSED, CellMark.EMPTY, CellMark.EMPTY, CellMark.FILLED, CellMark.FILLED, CellMark.FILLED, CellMark.EMPTY, CellMark.CROSSED, ]) assert str(cell_line) == "X__OOO_X"
def solve_one_way(self, line: CellsLine, instructions: List[int]) -> CellsLine: filled_sections = line.filled_sections if len(filled_sections) != len(instructions): return line for i in range(0, len(filled_sections) - 1): section, next_section = filled_sections[i], filled_sections[i + 1] instruction, next_instruction = instructions[i], instructions[i + 1] if not self.splitted_sections( line=line, section=section, next_section=next_section, instruction=instruction, next_instruction=next_instruction, ): return line for i in range(0, len(filled_sections) - 1): section, next_section = filled_sections[i], filled_sections[i + 1] instruction, next_instruction = instructions[i], instructions[i + 1] cross_start = section.end + instruction - section.length + 1 cross_end = next_section.start - next_instruction + next_section.length - 1 line.mark_inclusive(cross_start, cross_end, CellMark.CROSSED) first_section, last_section = filled_sections[0], filled_sections[-1] first_instruction, last_instruction = instructions[0], instructions[-1] first_cross_end = first_section.start - first_instruction + first_section.length - 1 if 0 <= first_cross_end < first_section.start: line.mark_inclusive(0, first_cross_end, CellMark.CROSSED) last_cross_start = last_section.end + last_instruction - last_section.length + 1 if last_section.end < last_cross_start < len(line): line.mark_inclusive(last_cross_start, len(line) - 1, CellMark.CROSSED) return line
def test_cells_line_sections(): assert CellsLine.parse_line("X_OX_OOO_X").sections == [ CellsSection(start=0, end=0, mark=CellMark.CROSSED, blocked_below=True), CellsSection(start=1, end=1, mark=CellMark.EMPTY, blocked_below=True), CellsSection(start=2, end=2, mark=CellMark.FILLED, blocked_above=True), CellsSection(start=3, end=3, mark=CellMark.CROSSED), CellsSection(start=4, end=4, mark=CellMark.EMPTY, blocked_below=True), CellsSection(start=5, end=7, mark=CellMark.FILLED), CellsSection(start=8, end=8, mark=CellMark.EMPTY, blocked_above=True), CellsSection(start=9, end=9, mark=CellMark.CROSSED, blocked_above=True), ]
def solve_one_way(self, line: CellsLine, instructions: List[int]) -> CellsLine: if line.is_completed: return line first_empty_section = line.empty_sections[0] if (first_empty_section.start != 0 and line[first_empty_section.start - 1] == CellMark.FILLED): return line number_of_known_instructions = len([ section for section in line.filled_sections if section.end < first_empty_section.start ]) remaining_instructions = instructions[number_of_known_instructions:] if len(remaining_instructions) == 0: return line first_remaining_instruction = remaining_instructions[0] min_remaining_instruction = min(remaining_instructions) remaining_sections = [ section for section in line.sections if section.start >= first_empty_section.start ] fill_first_gap = True for i in range(len(remaining_sections)): section = remaining_sections[i] if section.mark == CellMark.FILLED: if not fill_first_gap: continue fill_first_gap = False previous_section = remaining_sections[i - 1] if (previous_section.mark == CellMark.EMPTY and previous_section.length <= first_remaining_instruction): line.mark_inclusive( section.start, previous_section.start + first_remaining_instruction - 1, CellMark.FILLED) if section.blocked_above: line.mark_inclusive( section.end - first_remaining_instruction + 1, section.end, CellMark.FILLED) if section.end - first_remaining_instruction >= 0: line[ section.end - first_remaining_instruction] = CellMark.CROSSED continue if section.mark == CellMark.CROSSED: continue if not section.blocked: continue if section.length >= first_remaining_instruction: fill_first_gap = False if (section.length < min_remaining_instruction or (fill_first_gap and section.length < first_remaining_instruction)): line.mark_inclusive(section.start, section.end, CellMark.CROSSED) return line
def test_griddlers_board_set_column(): board = GriddlersBoard(rows=2, columns=3) board.set_column(0, CellsLine.parse_line("OX")) assert str(board) == "O__\nX__"
def test_cells_line_mark_inclusive(): cells_line = CellsLine.parse_line("X__OXO_X") cells_line.mark_inclusive(2, 5, CellMark.FILLED) assert cells_line == CellsLine.parse_line("X_OOOO_X")
def get_column(self, column_index: int) -> CellsLine: return CellsLine([self[(j, column_index)] for j in range(self.rows)])
def get_row(self, row_index: int) -> CellsLine: return CellsLine([self[(row_index, j)] for j in range(self.columns)])
def test_cells_line_filled_sections(): assert CellsLine.parse_line("X_OOXO_X").filled_sections == [ CellsSection(start=2, end=3, mark=CellMark.FILLED, blocked_above=True), CellsSection(start=5, end=5, mark=CellMark.FILLED, blocked_below=True), ]
def test_cells_line_empty_sections(): assert CellsLine.parse_line("X__OXO_X").empty_sections == [ CellsSection(start=1, end=2, mark=CellMark.EMPTY, blocked_below=True), CellsSection(start=6, end=6, mark=CellMark.EMPTY, blocked_above=True), ]
def test_slice_cells_line(): cells_line = CellsLine.parse_line("X__OXO_X") assert cells_line[1:5] == CellsLine.parse_line("__OX")
def solve(self, line: CellsLine, instructions: List[int]) -> CellsLine: line = self.solve_one_way(deepcopy(line), instructions) if not self.one_way: line = self.solve_one_way(line.inverse(), instructions[::-1]).inverse() return line
def test_cells_line_convert_to_list(): assert list(CellsLine.parse_line("X__OOO_X")) == [ CellMark.CROSSED, CellMark.EMPTY, CellMark.EMPTY, CellMark.FILLED, CellMark.FILLED, CellMark.FILLED, CellMark.EMPTY, CellMark.CROSSED ]
def test_cells_line_length(): assert len(CellsLine.parse_line("X__OOO_X")) == 8 assert len(CellsLine.parse_line("XX_X")) == 4 assert len(CellsLine.parse_line("O")) == 1 assert len(CellsLine.parse_line("")) == 0
def test_cells_line_inverse(): cells_line = CellsLine.parse_line("X__OOO_X") assert cells_line.inverse() == CellsLine.parse_line("X_OOO__X")
def test_cells_line_set_item(): cells_line = CellsLine.parse_line("X__OOO_X") cells_line[1] = CellMark.CROSSED assert cells_line == CellsLine.parse_line("XX_OOO_X")