backtrack.py

This commit is contained in:
Timo Schmidt 2023-03-26 06:59:17 +02:00
parent 38eff0354b
commit 845e6dcb81
1 changed files with 30 additions and 29 deletions

View File

@ -35,10 +35,10 @@ def get_col(board: list, pos: int) -> list:
]
return column
def get_candidates(board: list, next_candidate_index: int) -> int:
def get_candidates(board: list, next_cell_idx: int) -> list:
all_candidates = set(range(1 + get_board_dim(board)))
row = get_row(board, next_candidate_index)
column = get_col(board, next_candidate_index)
row = get_row(board, next_cell_idx)
column = get_col(board, next_cell_idx)
for candidate in all_candidates.copy():
if candidate in row:
@ -49,7 +49,7 @@ def get_candidates(board: list, next_candidate_index: int) -> int:
continue
return all_candidates
def get_constraints(board: list, border: list, pos: int) -> list:
def get_clues(board: list, border: list, pos: int) -> list:
board_dim = get_board_dim(board)
col_idx = pos // board_dim
row_idx = pos % board_dim
@ -57,11 +57,11 @@ def get_constraints(board: list, border: list, pos: int) -> list:
coldown = border[row_idx + board_dim]
rowleft = border[col_idx + board_dim * 2]
rowright = border[col_idx + board_dim * 3]
constraints = [colup, coldown, rowleft, rowright]
return constraints
clues = [colup, coldown, rowleft, rowright]
return clues
def check_constraint(slice: list, constraint: int) -> bool:
constraint = int(constraint)
def check_clue(slice: list, clue: int) -> bool:
clue = int(clue)
peak = 0
visible_towers = 0
@ -73,26 +73,27 @@ def check_constraint(slice: list, constraint: int) -> bool:
if tower > peak:
peak = tower
visible_towers += 1
if visible_towers > constraint:
if visible_towers > clue:
return False
if constraint + tower > board_dim + 1 + i:
if clue + tower > board_dim + 1 + i:
return False
if 0 not in slice:
return visible_towers == constraint
return visible_towers == clue
else:
return True
def is_valid_state(board: list, border: list, next_candidate_index: int) -> bool:
row = get_row(board, next_candidate_index)
column = get_col(board, next_candidate_index)
constraints = get_constraints(board, border, next_candidate_index)
satisfies_constraints = all([
check_constraint(column, constraints[0]),
check_constraint(row, constraints[2]),
check_constraint(column[::-1], constraints[1]),
check_constraint(row[::-1], constraints[3]),
def is_valid_state(board: list, border: list, next_cell_idx: int) -> bool:
clues = get_clues(board, border, next_cell_idx)
row = get_row(board, next_cell_idx)
column = get_col(board, next_cell_idx)
satisfies_clues = all([
check_clue(column, clues[0]),
check_clue(row, clues[2]),
check_clue(column[::-1], clues[1]),
check_clue(row[::-1], clues[3]),
])
return satisfies_constraints
return satisfies_clues
def print_board(board: list, border: list) -> None:
padding = ' ' * PADDING
@ -115,17 +116,17 @@ def backtrack_skyscrapers(board: list, sols: list, border: list) -> None:
sols.append(board)
print_board(sols[0], border)
sys.exit(0)
next_candidate_index = board.index(0)
candidates = get_candidates(board, next_candidate_index)
next_cell_idx = board.index(0)
candidates = get_candidates(board, next_cell_idx)
for candidate in candidates:
board[next_candidate_index] = candidate
board[next_cell_idx] = candidate
if DEBUG:
input()
os.system('clear')
# os.system('clear')
print_board(board, border)
if is_valid_state(board, border, next_candidate_index):
if is_valid_state(board, border, next_cell_idx):
backtrack_skyscrapers(board, sols, border)
board[next_candidate_index] = 0
board[next_cell_idx] = 0
def main(*args, **kwargs) -> None:
if kwargs:
@ -163,5 +164,5 @@ if __name__ == '__main__':
# main('2 1 2 3 3 2 3 1 3 2 2 1 3 3 2 3 4 2 1 2') # 5 x 5
# main('1 2 2 4 3 5 4 4 2 2 2 1 1 2 3 4 2 4 5 3 3 2 2 1') # 6 x 6
# main('6 3 1 3 3 3 2 1 2 3 3 3 3 3 3 7 3 4 3 2 1 2 1 2 2 3 3 4') # 7 x 7
# main('7 4 2 3 3 2 1 1 2 2 2 3 4 6 6 5 4 2 3 2 1 1 2 2 4 2 4 4') # 7 x 7
main('4 3 4 1 5 4 3 2 2 4 2 4 1 3 5 4 3 3 5 2 3 1 3 2 2 1 2 3 2 4 3 3') # 8 x 8
main('7 4 2 3 3 2 1 1 2 2 2 3 4 6 6 5 4 2 3 2 1 1 2 2 4 2 4 4') # 7 x 7
# main('4 3 4 1 5 4 3 2 2 4 2 4 1 3 5 4 3 3 5 2 3 1 3 2 2 1 2 3 2 4 3 3') # 8 x 8