InternBootcamp/internbootcamp/libs/arrowmaze/maze_validor.py
2025-05-23 15:27:15 +08:00

218 lines
No EOL
6.3 KiB
Python
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import re
def parse_candidate_path(answer_str):
"""
Parse a candidate_path string in the format:
"[[1 0 0,0 0 0,0 0 2]]"
into a 2D list of integers.
"""
# 1) Remove the outer brackets "[[" and "]]"
# 2) Split into rows by comma
# 3) Each row is space-separated integers
# Example input: "[[1 0 0,0 0 0,0 0 2]]"
# Trim leading/trailing brackets
trimmed = answer_str.strip()
if trimmed.startswith("[["):
trimmed = trimmed[2:]
if trimmed.endswith("]]"):
trimmed = trimmed[:-2]
# Now we have something like: "1 0 0,0 0 0,0 0 2"
# Split by commas to get rows
row_strs = trimmed.split(",")
grid_of_ints = []
for row_str in row_strs:
# row_str might look like "1 0 0" or "0 0 2"
row_str = row_str.strip()
if not row_str:
continue
# split by spaces
vals = row_str.split()
row_ints = [int(v) for v in vals]
grid_of_ints.append(row_ints)
return grid_of_ints
def arrow_maze_validator(
grid, start_position, answer
):
"""
Validate whether a candidate_path in puzzle's format (e.g. "[[1 0 0,0 0 0,0 0 2]]")
is a correct solution to the arrow maze.
Parameters
----------
grid : list[list[str]]
A 2D grid of arrow symbols or ''.
Example:
[
['', '', ''],
['', '', ''],
['', '', ''],
]
start_position : (int, int)
(row, col) of the starting cell.
answer : list
The proposed solution in the format "[[...]]"
0 => not on path
1 => first visited cell
2 => second visited cell
etc.
Returns
-------
bool
True if the path is valid, False otherwise.
"""
# Directions dictionary: maps arrow symbol -> (dr, dc)
DIRECTIONS = {
'': (-1, 0),
'': ( 1, 0),
'': ( 0, -1),
'': ( 0, 1),
'': (-1, -1),
'': (-1, 1),
'': ( 1, -1),
'': ( 1, 1),
}
rows = len(grid)
cols = len(grid[0]) if rows > 0 else 0
def in_bounds(r, c):
return 0 <= r < rows and 0 <= c < cols
#$candidate_grid = parse_candidate_path(answer_str)
candidate_grid = answer
# Sanity check: the candidate_grid should match the same dimensions as 'grid'
if len(candidate_grid) != rows:
return False
for row_vals in candidate_grid:
if len(row_vals) != cols:
return False
# 2. Extract the labeled cells: (label, (row, col))
# We only care about label > 0
labeled_cells = []
for r in range(rows):
for c in range(cols):
label = candidate_grid[r][c]
if label > 0:
labeled_cells.append((label, (r, c)))
# If no labeled cells, invalid
if not labeled_cells:
return False
# 3. Sort by label ascending
labeled_cells.sort(key=lambda x: x[0]) # sort by label number
# This gives us an ordered path: [ (1, (r1,c1)), (2, (r2,c2)), ... ]
# 4. The path in terms of coordinates:
path = [cell_coord for _, cell_coord in labeled_cells]
# 5. Check that label "1" is at start_position
if path[0] != start_position:
return False
# 6. Validate each consecutive step in path
for i in range(len(path) - 1):
(r1, c1) = path[i]
(r2, c2) = path[i + 1]
if not in_bounds(r1, c1) or not in_bounds(r2, c2):
return False
# If the current cell is the end symbol '○' but we still have more steps, invalid
if grid[r1][c1] == '':
return False
# Arrow in the current cell:
arrow_symbol = grid[r1][c1]
if arrow_symbol not in DIRECTIONS:
return False # not an arrow and not the end symbol
(dr, dc) = DIRECTIONS[arrow_symbol]
delta_r = r2 - r1
delta_c = c2 - c1
# Must move in a positive integer multiple of (dr, dc).
if dr == 0 and dc == 0:
return False # shouldn't happen with valid arrows
# Horizontal or vertical
if dr == 0:
# vertical movement is zero => must move horizontally
# check we didn't move in row, must move in col
if delta_r != 0:
return False
# direction must match sign of dc
if dc > 0 and delta_c <= 0:
return False
if dc < 0 and delta_c >= 0:
return False
elif dc == 0:
# horizontal movement is zero => must move in row
if delta_c != 0:
return False
if dr > 0 and delta_r <= 0:
return False
if dr < 0 and delta_r >= 0:
return False
else:
# diagonal
if delta_r == 0 or delta_c == 0:
return False # can't be diagonal if one is zero
if (dr > 0 and delta_r <= 0) or (dr < 0 and delta_r >= 0):
return False
if (dc > 0 and delta_c <= 0) or (dc < 0 and delta_c >= 0):
return False
# check integer multiples
if (delta_r % dr) != 0 or (delta_c % dc) != 0:
return False
factor_r = delta_r // dr
factor_c = delta_c // dc
if factor_r != factor_c or factor_r <= 0:
return False
# 7. Check last labeled cell is the '○' cell
last_r, last_c = path[-1]
if not in_bounds(last_r, last_c):
return False
if grid[last_r][last_c] != '':
return False
# If all checks pass, it's a valid solution
return True
# ------------------------------
# Example usage:
if __name__ == "__main__":
# A small 3×3 arrow maze with start=(0, 0):
# Grid (3x3):
# → ↙ ↓
# ↖ ↓ ↙
# ↑ ← ○
grid = [
['', '', ''],
['', '', ''],
['', '', ''],
]
start_position = (0, 0)
# Example candidate_path string:
# "[[1 0 0,0 0 0,0 0 2]]"
# This claims:
# row=0 col=0 => 1 (start)
# row=2 col=2 => 2 (end)
candidate_path_str = "[[1 0 2,0 0 0,0 0 3]]"
is_valid = arrow_maze_validator(
grid, start_position, candidate_path_str
)
print("Is the candidate path valid?", is_valid)