Spaces:
Sleeping
Sleeping
| # utils.py | |
| from collections import deque | |
| def to_tuple_set(blocks): | |
| return set(tuple(b) for b in blocks) | |
| def to_list(blocks_set): | |
| return [list(b) for b in sorted(blocks_set)] | |
| def get_neighbors(block, dimension): | |
| neighbors = [] | |
| if dimension == 2: | |
| x, y = block | |
| moves = [(1, 0), (-1, 0), (0, 1), (0, -1)] | |
| for dx, dy in moves: | |
| neighbors.append((x + dx, y + dy)) | |
| else: | |
| x, y, z = block | |
| moves = [ | |
| (1, 0, 0), (-1, 0, 0), | |
| (0, 1, 0), (0, -1, 0), | |
| (0, 0, 1), (0, 0, -1) | |
| ] | |
| for dx, dy, dz in moves: | |
| neighbors.append((x + dx, y + dy, z + dz)) | |
| return neighbors | |
| def is_connected(blocks_set, dimension): | |
| if not blocks_set: | |
| return True | |
| start_node = next(iter(blocks_set)) | |
| visited = {start_node} | |
| queue = deque([start_node]) | |
| while queue: | |
| curr = queue.popleft() | |
| for neighbor in get_neighbors(curr, dimension): | |
| if neighbor in blocks_set and neighbor not in visited: | |
| visited.add(neighbor) | |
| queue.append(neighbor) | |
| return len(visited) == len(blocks_set) | |
| def apply_move(blocks_set, from_coord, to_coord): | |
| new_set = set(blocks_set) | |
| if from_coord not in new_set: | |
| raise ValueError("from_coord is not in the configuration.") | |
| if to_coord in new_set: | |
| raise ValueError("to_coord is already occupied.") | |
| new_set.remove(from_coord) | |
| new_set.add(to_coord) | |
| return new_set | |
| def is_move_connected(blocks_set, from_coord, to_coord, dimension): | |
| # Điều kiện trong bài báo: C \ {c} phải liên thông trong khi cube đang move | |
| temp_set = set(blocks_set) | |
| temp_set.remove(from_coord) | |
| if not is_connected(temp_set, dimension): | |
| return False | |
| # Sau khi đặt cube xuống vị trí mới, cấu hình cũng nên liên thông | |
| new_set = apply_move(blocks_set, from_coord, to_coord) | |
| return is_connected(new_set, dimension) | |
| def potential(blocks, dimension): | |
| """ | |
| Potential theo bài báo: | |
| Πc = wc(cx + 2cy + 4cz) | |
| Với 2D, coi z = 0. | |
| """ | |
| total_potential = 0 | |
| for b in blocks: | |
| x = b[0] | |
| y = b[1] | |
| z = b[2] if dimension == 3 else 0 | |
| if z > 1: | |
| w = 17 | |
| elif z == 1: | |
| w = 16 | |
| else: | |
| if y > 1: | |
| w = 3 | |
| elif y == 1: | |
| w = 2 | |
| else: | |
| w = 1 | |
| total_potential += w * (x + 2 * y + 4 * z) | |
| return total_potential | |
| def is_finished_2d(blocks_set): | |
| """ | |
| Một ô (x,y) finished nếu toàn bộ hình chữ nhật | |
| {0..x} x {0..y} đều có trong cấu hình. | |
| """ | |
| for x, y in blocks_set: | |
| for i in range(x + 1): | |
| for j in range(y + 1): | |
| if (i, j) not in blocks_set: | |
| return False | |
| return True | |
| def is_finished_3d(blocks_set): | |
| """ | |
| Một cube (x,y,z) finished nếu toàn bộ cuboid | |
| {0..x} x {0..y} x {0..z} đều có trong cấu hình. | |
| """ | |
| for x, y, z in blocks_set: | |
| for i in range(x + 1): | |
| for j in range(y + 1): | |
| for k in range(z + 1): | |
| if (i, j, k) not in blocks_set: | |
| return False | |
| return True | |
| def make_step_info( | |
| step_idx, | |
| from_c, | |
| to_c, | |
| move_type, | |
| blocks_before, | |
| blocks_after, | |
| pot_before, | |
| pot_after, | |
| connected_after, | |
| finished_after, | |
| operation=None | |
| ): | |
| step = { | |
| "step": step_idx, | |
| "from": list(from_c), | |
| "to": list(to_c), | |
| "move_type": move_type, | |
| "blocks_before": to_list(blocks_before), | |
| "blocks_after": to_list(blocks_after), | |
| "potential_before": pot_before, | |
| "potential_after": pot_after, | |
| "is_connected_after": connected_after, | |
| "is_finished_after": finished_after | |
| } | |
| if operation is not None: | |
| step["operation"] = operation | |
| return step | |
| def build_response( | |
| success, | |
| message, | |
| dimension, | |
| initial_info, | |
| steps, | |
| final_info, | |
| status, | |
| algorithm="greedy_potential" | |
| ): | |
| return { | |
| "success": success, | |
| "message": message, | |
| "dimension": dimension, | |
| "algorithm": algorithm, | |
| "initial": initial_info, | |
| "steps": steps, | |
| "final": final_info, | |
| "total_steps": len(steps), | |
| "status": status | |
| } |