Backtrack almost working
This commit is contained in:
parent
c78fb015ec
commit
ace1cfe04e
|
@ -0,0 +1,119 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
PADDING = int(os.popen('tput cols').read()) // 3 # '// 2 - 6' for exact middle for n=4
|
||||
|
||||
def get_board_dim(board: list) -> int:
|
||||
return int(len(board) ** 0.5)
|
||||
|
||||
def get_row(board: list, pos: int) -> list:
|
||||
board_dim = get_board_dim(board)
|
||||
row_start = pos // board_dim * board_dim
|
||||
row = board[
|
||||
row_start
|
||||
:
|
||||
row_start + board_dim
|
||||
:
|
||||
1
|
||||
]
|
||||
return row
|
||||
|
||||
def get_col(board: list, pos: int) -> list:
|
||||
board_dim = get_board_dim(board)
|
||||
column_start = pos % board_dim
|
||||
column = board[
|
||||
column_start
|
||||
:
|
||||
board_dim**2 - (board_dim - column_start) + 1
|
||||
:
|
||||
board_dim
|
||||
]
|
||||
return column
|
||||
|
||||
def get_candidates(board: list, next_candidate_index: int) -> int:
|
||||
all_candidates = set(range(1 + get_board_dim(board)))
|
||||
row = get_row(board, next_candidate_index)
|
||||
column = get_col(board, next_candidate_index)
|
||||
|
||||
for candidate in all_candidates.copy():
|
||||
if candidate in row:
|
||||
all_candidates.discard(candidate)
|
||||
continue
|
||||
if candidate in column:
|
||||
all_candidates.discard(candidate)
|
||||
continue
|
||||
return all_candidates
|
||||
|
||||
def get_constraints(board: list, border: list, pos: int) -> list:
|
||||
pass
|
||||
|
||||
def is_valid_state(board: list, border: list, next_candidate_index: int) -> bool:
|
||||
board_dim = get_board_dim(board)
|
||||
print_board(board, border)
|
||||
row = get_row(board, next_candidate_index)
|
||||
column = get_col(board, next_candidate_index)
|
||||
constraints = get_constraints(board, border, next_candidate_index)
|
||||
print(constraints, row, column)
|
||||
return True
|
||||
|
||||
def print_board(board: list, border: list) -> None:
|
||||
padding = ' ' * PADDING
|
||||
board_dim = get_board_dim(board)
|
||||
print(end=padding + ' ')
|
||||
print(' '.join(border[:board_dim]))
|
||||
for i in range(board_dim):
|
||||
print(end=padding + border[i + board_dim * 2] + '|')
|
||||
for j in range(board_dim):
|
||||
print(board[j + i * board_dim], end=' ')
|
||||
print(end='\b|')
|
||||
print(end=border[i + board_dim * 3])
|
||||
print(end='\b\n')
|
||||
print(end=padding + ' ')
|
||||
print(' '.join(border[board_dim:board_dim * 2]))
|
||||
print()
|
||||
|
||||
def backtrack(board: list, sols: list, border: list) -> None:
|
||||
if board.count(0) == 0:
|
||||
sols.append(board)
|
||||
print("Solutions")
|
||||
print_board(sols[0], border)
|
||||
print("Done")
|
||||
sys.exit(0)
|
||||
next_candidate_index = board.index(0)
|
||||
candidates = get_candidates(board, next_candidate_index)
|
||||
for candidate in candidates:
|
||||
board[next_candidate_index] = candidate
|
||||
if is_valid_state(board, border, next_candidate_index):
|
||||
backtrack(board, sols, border)
|
||||
continue
|
||||
|
||||
def main(*args, **kwargs) -> None:
|
||||
|
||||
if kwargs:
|
||||
print('Error (kwargs)')
|
||||
sys.exit(1)
|
||||
if len(args) != 1:
|
||||
print('Error (args)')
|
||||
sys.exit(2)
|
||||
|
||||
try:
|
||||
border = args[0].split()
|
||||
except:
|
||||
print('Error (could not split)')
|
||||
sys.exit(3)
|
||||
board_dim = len(border) / 4
|
||||
if board_dim != int(board_dim):
|
||||
print('Board is not square')
|
||||
sys.exit(4)
|
||||
else:
|
||||
board_dim = int(board_dim)
|
||||
|
||||
board = [
|
||||
0 for _ in range(board_dim ** 2)
|
||||
]
|
||||
number_of_sols = backtrack(board, [], border)
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main('4 3 2 1 1 2 2 2 4 3 2 1 1 2 2 2'))
|
Loading…
Reference in New Issue