|
1 |
| -from operator import ne |
| 1 | +""" |
| 2 | +Oversimplified version of a path walker for grading the assignment |
| 3 | +
|
| 4 | +TODO: |
| 5 | + - Implement a recursive algorithm instead of a while true to seach all possible paths instead. |
| 6 | +""" |
2 | 7 | import sys
|
3 |
| -from time import sleep |
4 |
| -from typing import List, Set, Tuple |
| 8 | +import copy |
| 9 | +from typing import List, Tuple |
| 10 | + |
| 11 | + |
| 12 | +class bcolors: |
| 13 | + HEADER = "\033[95m" |
| 14 | + OKBLUE = "\033[94m" |
| 15 | + OKCYAN = "\033[96m" |
| 16 | + OKGREEN = "\033[92m" |
| 17 | + WARNING = "\033[93m" |
| 18 | + FAIL = "\033[91m" |
| 19 | + ENDC = "\033[0m" |
| 20 | + BOLD = "\033[1m" |
| 21 | + UNDERLINE = "\033[4m" |
5 | 22 |
|
6 | 23 |
|
7 |
| -def fail(x: int, y: int, current: str, grid): |
| 24 | +def fail(x: int, y: int, current: str, grid, used): |
8 | 25 | print(f"Board is invalid, see position [{x},{y}], should be {current}")
|
9 |
| - for line in grid: |
10 |
| - print(line) |
| 26 | + for x, line in enumerate(grid): |
| 27 | + for y, ele in enumerate(line): |
| 28 | + if used[x][y]: |
| 29 | + print(bcolors.OKGREEN + f"{ele} ", end="") |
| 30 | + else: |
| 31 | + print(bcolors.WARNING + f"{ele} ", end="") |
| 32 | + print(bcolors.ENDC) |
11 | 33 |
|
12 | 34 |
|
13 | 35 | def sucess():
|
14 |
| - print("Board is valid") |
| 36 | + print(bcolors.BOLD + bcolors.OKGREEN + "Board is valid" + bcolors.ENDC) |
15 | 37 |
|
16 | 38 |
|
17 | 39 | # returns them in [up, right, left, down]
|
18 | 40 | def getneighbor(x: int, y: int, grid: List[List[str]]):
|
19 | 41 | neighbors = [0] * 4
|
20 |
| - neighbors[0] = grid[x - 1][y] if (x - 1) >= 0 else "#" |
| 42 | + neighbors[0] = grid[x - 1][y] if x - 1 >= 0 else "#" |
21 | 43 | neighbors[1] = grid[x][y + 1] if y + 1 < 10 else "#"
|
22 | 44 | neighbors[2] = grid[x][y - 1] if y - 1 >= 0 else "#"
|
23 | 45 | neighbors[3] = grid[x + 1][y] if x + 1 < 10 else "#"
|
24 | 46 | return neighbors
|
25 | 47 |
|
26 | 48 |
|
27 |
| -grid: List[List[str]] = [] |
28 |
| - |
29 |
| -# Grab board from stdin |
30 |
| -for line in sys.stdin: |
31 |
| - grid.append(line.split()) |
32 |
| - |
| 49 | +def move(direction: int, x: int, y: int) -> Tuple[int, int]: |
| 50 | + if direction == 0: |
| 51 | + x = x - 1 |
| 52 | + elif direction == 1: |
| 53 | + y = y + 1 |
| 54 | + elif direction == 2: |
| 55 | + y = y - 1 |
| 56 | + elif direction == 3: |
| 57 | + x = x + 1 |
| 58 | + return (x, y) |
33 | 59 |
|
34 |
| -# Check to see if A starts in top right |
35 |
| -used: Set[Tuple[int, int]] = set() |
36 |
| -current: str = "A" |
37 |
| -x: int = 0 |
38 |
| -y: int = 0 |
39 | 60 |
|
40 |
| -while True: |
| 61 | +def check(current, grid, used, x, y): |
41 | 62 | # Check whether letter is correct
|
42 | 63 | if current != grid[x][y]:
|
43 |
| - fail(x, y, current) |
44 |
| - break |
| 64 | + print("manually review the board, possible mixed paths") |
| 65 | + fail(x, y, current, grid, used) |
| 66 | + return False |
45 | 67 |
|
46 | 68 | # Log position to prevent loops
|
47 |
| - used.add((x, y)) |
| 69 | + used[x][y] = True |
| 70 | + |
48 | 71 | # Increment current
|
49 | 72 | current = chr(ord(current) + 1)
|
50 | 73 | if ord(current) > ord("Z"):
|
51 | 74 | current = "A"
|
| 75 | + |
52 | 76 | # Get neighbors
|
53 | 77 | neighbors = getneighbor(x, y, grid)
|
54 | 78 |
|
55 | 79 | # Check if the next element exists in the neighbors
|
56 | 80 | if current not in neighbors:
|
57 | 81 | # if the next element isn't found, check for empty neighbors
|
58 | 82 | if "." in neighbors:
|
59 |
| - fail(x, y, current, grid) |
60 |
| - break |
| 83 | + fail(x, y, current, grid, used) |
| 84 | + return False |
61 | 85 | else:
|
62 | 86 | # check to see if all have been visited
|
63 |
| - if (x - 1, y) in used or x - 1 < 0: |
64 |
| - if (x, y + 1) in used or y + 1 >= 10: |
65 |
| - if (x, y - 1) in used or y - 1 < 0: |
66 |
| - if (x + 1, y) in used or x + 1 >= 10: |
67 |
| - sucess() |
68 |
| - break |
69 |
| - fail(x, y, current, grid) |
70 |
| - break |
| 87 | + bounds = getneighbor(x, y, used) |
| 88 | + if any([not x for x in bounds]): |
| 89 | + fail(x, y, current, grid, used) |
| 90 | + return False |
| 91 | + return True |
71 | 92 |
|
72 |
| - direction = neighbors.index(current) |
| 93 | + for idx, dir in enumerate(neighbors): |
| 94 | + if dir == current: |
| 95 | + nx, ny = move(idx, x, y) |
| 96 | + if not used[nx][ny]: # If we've reached a new spot |
| 97 | + if check(current, grid, copy.deepcopy(used), nx, ny): |
| 98 | + return True |
| 99 | + return False |
73 | 100 |
|
74 |
| - if direction == 0: |
75 |
| - x = x - 1 |
76 |
| - elif direction == 1: |
77 |
| - y = y + 1 |
78 |
| - elif direction == 2: |
79 |
| - y = y - 1 |
| 101 | + |
| 102 | +grid: List[List[str]] = [] |
| 103 | +# Check to see if A starts in top right |
| 104 | +used: List[List[bool]] = [[False for _ in range(10)] for _ in range(10)] |
| 105 | +current: str = "A" |
| 106 | +x: int = 0 |
| 107 | +y: int = 0 |
| 108 | + |
| 109 | +# Grab board from stdin |
| 110 | +for line in sys.stdin: |
| 111 | + grid.append(line.split()) |
| 112 | + |
| 113 | +try: |
| 114 | + if check(current, grid, used, x, y): |
| 115 | + sucess() |
80 | 116 | else:
|
81 |
| - x = x + 1 |
| 117 | + print("program failed, terminating...") |
| 118 | +except KeyboardInterrupt: |
| 119 | + for line in grid: |
| 120 | + print(line) |
0 commit comments