Skip to content

Increase speed by removing symetrical solutions #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 29 additions & 15 deletions magic_hexagon.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,23 @@
FLOORS = 3
ROWS_NB = 2*FLOORS-1
CELLS_NB = 3*FLOORS*(FLOORS-1)+1
NUMBERS = list(range(1, CELLS_NB+1))
NUMBERS = range(1, CELLS_NB+1)
LINE_SUM = sum(range(1, CELLS_NB+1)) // ROWS_NB

# Algo global variables
assert FLOORS == 3
BOARD_INDEXES_STR = """
00. 01. 02.
11. 12. 13. 03.
10. 17. 18. 14. 04.
09. 16. 15. 05.
08. 07. 06.
00. 01. 03.
02. 13. 14. 05.
04. 12. 18. 15. 06.
11. 17. 16. 07.
10. 09. 08.
"""
X_LINES = [[0, 1, 2], [11, 12, 13, 3], [10, 17, 18, 14, 4], [9, 16, 15, 5], [8, 7, 6]]
Y_LINES = [[0, 11, 10], [1, 12, 17, 9], [2, 13, 18, 16, 8], [3, 14, 15, 7], [4, 5, 6]]
Z_LINES = [[10, 9, 8], [11, 17, 16, 7], [0, 12, 18, 15, 6], [1, 13, 14, 5], [2, 3, 4]]
# Modified snail
X_LINES = [[0, 1, 3], [2, 13, 14, 5], [4, 12, 18, 15, 6], [11, 17, 16, 7], [10, 9, 8]]
Y_LINES = [[0, 2, 4], [1, 13, 12, 11], [3, 14, 18, 17, 10], [5, 15, 16, 9], [6, 7, 8]]
Z_LINES = [[4, 11, 10], [2, 12, 17, 9], [0, 13, 18, 16, 8], [1, 14, 15, 7], [3, 5, 6]]

LINES_ENDED_BY_STEP = [
[
line
Expand All @@ -30,6 +32,8 @@
] for i in range(19)
]
CORNERS_EXCEPT_FIRST = {2, 4, 6, 8, 10}
FIRST_SIDE = 1
LAST_SIDE = 2


def display_board(board: List[int]):
Expand All @@ -47,6 +51,7 @@ def look_for_solutions_(

# Cache
corners_tested: Set[int],
first_side_test: Set[int],
start_time: float,
) -> None:
"""Look for solutions given board state and step to start from
Expand All @@ -63,16 +68,20 @@ def look_for_solutions_(
start_time i the time in secs when the search has started
"""
if not remaining_numbers:
print(f'Solution found in {time() - start_time}s:')
print(f'Solution found in {(time() - start_time)*1000:.1f}ms')
display_board(board)
return

for _ in range(CELLS_NB-step):
# If step is on corner and number has already been tested as a corner, skip it
# # Avoid rotations this way
number = remaining_numbers.pop()
if number in corners_tested and step in CORNERS_EXCEPT_FIRST:
remaining_numbers.appendleft(number)
number = remaining_numbers.popleft()
if step in CORNERS_EXCEPT_FIRST and number in corners_tested:
remaining_numbers.append(number)
continue
# Remove symetrical solutions
if step == LAST_SIDE and number in first_side_test:
remaining_numbers.append(number)
continue

# Add number to board and get next remaining numbers
Expand All @@ -93,14 +102,18 @@ def look_for_solutions_(
remaining_numbers,
step+1,
corners_tested=corners_tested,
first_side_test=first_side_test,
start_time=start_time,
)

# Add the removed number for the next iteration
remaining_numbers.appendleft(number)
remaining_numbers.append(number)
# Number has been fully explored as first corner
if step == 0:
corners_tested.add(number)
first_side_test=set()
if step == FIRST_SIDE:
first_side_test.add(number)

return

Expand All @@ -112,9 +125,10 @@ def look_for_solutions():
remaining_numbers=deque(NUMBERS),
step=0,
corners_tested=set(),
first_side_test=set(),
start_time=start,
)
print(f'Full run ended in {time()-start}s')
print(f'Full run ended in {(time() - start)*1000:.1f}ms')


if __name__ == '__main__':
Expand Down