mirror of
https://github.com/InternLM/InternBootcamp.git
synced 2026-04-19 12:58:04 +00:00
218 lines
No EOL
6.3 KiB
Python
Executable file
218 lines
No EOL
6.3 KiB
Python
Executable file
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) |