diff options
Diffstat (limited to 'solutions')
| -rw-r--r-- | solutions/py/d15.py | 337 | ||||
| -rw-r--r-- | solutions/py/main.py | 4 |
2 files changed, 221 insertions, 120 deletions
diff --git a/solutions/py/d15.py b/solutions/py/d15.py index 7315d1a..9ee3f65 100644 --- a/solutions/py/d15.py +++ b/solutions/py/d15.py @@ -3,96 +3,51 @@ import heapq as heap import collections import time -size = 2 -def draw(board, droid=None, path=None, visited=None): - min_x=max_x=min_y=max_y = 0 - for p in board: - min_x = min(p[0], min_x) - max_x = max(p[0], max_x) - min_y = min(p[1], min_y) - max_y = max(p[1], max_y) - s = "" - for y in range(min_y-1, max_y+2): - s += "\n" - for x in range(min_x-1, max_x+2): - point = (x, y) - if droid is not None and point == droid: - s += "D" * size - elif path is not None and point in path: - s += "\u2591" * size - elif visited is not None and point in visited: - s += "." * size - elif point in board: - if board[point] == "#": - s += "\u2588" * size - elif board[point] == "S": - s += "\u2591" * size - else: - s += " " * size - else: - s += "." * size - return s - def neighbours(p): return [(p[0]+1, p[1]), (p[0]-1, p[1]), \ (p[0], p[1]+1), (p[0], p[1]-1)] -def get_path(start, end, board): - #print("get_path", start, end) +def get_path(start, end, board, draw_search=False): if start == end: return collections.deque() visited = set() h = [] heap.heappush(h, (0, start, collections.deque())) while True: - #print("h", h) cur = heap.heappop(h) for n in neighbours(cur[1]): - #print("n", n) if n == end: - #print("done") cur[2].append(n) - #print(cur[2]) + if draw_search: + print(draw(board, path=cur[2], visited=visited)) return cur[2] - if n in visited: - #print("visited") + if n in visited or n not in board or board[n] == "#": continue - if n not in board: - #print("not in board") - continue - if board[n] == "#": - #print("wall") - continue - #print("adding") new_path = collections.deque(cur[2]) new_path.append(n) visited.add(n) - #print(draw(board, path=new_path, visited=visited)) - #time.sleep(0.01) heap.heappush(h, (cur[0] + 1, n, new_path)) + if draw_search: + time.sleep(0.005) + print(draw(board, path=new_path, visited=visited)) + +def pt1(input): + cur_x = cur_y = 0 + q = collections.deque() + q.append((0,0)) + path = collections.deque() + board = {} + board[(0,0)] = "." + + c = intcode.Computer([int(x) for x in input[0].split(",")]) -cur_x = cur_y = 0 -q = collections.deque() -q.append((0,0)) -path = collections.deque() -board = {} -board[(0,0)] = "." -oxygen = (0,0) - -f = open("../input/15", "r").readlines() -c = intcode.Computer([int(x) for x in f[0].split(",")]) - -auto = True -steps = 0 -while not c.SIG_HALT: - if auto and len(q) == 0: - print("queue empty") - break - c.step() - if c.SIG_INPUT: - direction = 0 - prev_x, prev_y = cur_x, cur_y - if auto: + while not c.SIG_HALT: + if len(q) == 0: + break + c.step() + if c.SIG_INPUT: + direction = 0 + prev_x, prev_y = cur_x, cur_y if len(path) == 0: # find new path for n in neighbours((cur_x, cur_y)): @@ -100,7 +55,6 @@ while not c.SIG_HALT: q.append(n) if (cur_x, cur_y) in q: q.remove((cur_x, cur_y)) - #print(q) next = q.pop() path = get_path((cur_x, cur_y), next, board) next_step = path.popleft() @@ -119,63 +73,208 @@ while not c.SIG_HALT: else: print("invalid path") break - else: # manual - next_step = input() - if next_step == "w": + c.input = direction + c.SIG_INPUT = False + if c.SIG_OUTPUT: + if c.output == 0: + board[(cur_x, cur_y)] = "#" + cur_x, cur_y = prev_x, prev_y + elif c.output == 1: + board[(cur_x, cur_y)] = "." + elif c.output == 2: + board[(cur_x, cur_y)] = "S" + oxygen = (cur_x, cur_y) + else: + break + c.output = None + c.SIG_OUTPUT = False + return len(get_path((0,0), oxygen, board)) + +def pt2(input): + cur_x = cur_y = 0 + q = collections.deque() + q.append((0,0)) + path = collections.deque() + board = {} + board[(0,0)] = "." + oxygen = (0,0) + + c = intcode.Computer([int(x) for x in input[0].split(",")]) + + while not c.SIG_HALT: + if len(q) == 0: + break + c.step() + if c.SIG_INPUT: + direction = 0 + prev_x, prev_y = cur_x, cur_y + if len(path) == 0: + # find new path + for n in neighbours((cur_x, cur_y)): + if n not in q and n not in board: + q.append(n) + if (cur_x, cur_y) in q: + q.remove((cur_x, cur_y)) + next = q.pop() + path = get_path((cur_x, cur_y), next, board) + next_step = path.popleft() + if next_step[1] == cur_y-1: direction = 1 cur_y -= 1 - elif next_step == "s": + elif next_step[1] == cur_y+1: direction = 2 cur_y += 1 - elif next_step == "a": + elif next_step[0] == cur_x-1: direction = 3 cur_x -= 1 - elif next_step == "d": + elif next_step[0] == cur_x+1: direction = 4 cur_x += 1 else: - continue - c.input = direction + print("invalid path") + break + c.input = direction + c.SIG_INPUT = False + if c.SIG_OUTPUT: + if c.output == 0: + board[(cur_x, cur_y)] = "#" + cur_x, cur_y = prev_x, prev_y + elif c.output == 1: + board[(cur_x, cur_y)] = "." + elif c.output == 2: + board[(cur_x, cur_y)] = "S" + oxygen = (cur_x, cur_y) + else: + break + c.output = None + c.SIG_OUTPUT = False + + steps = 0 + visited = set(oxygen) + cur_layer = [] + next_layer = [oxygen] + while True: + cur_layer = next_layer.copy() + next_layer = [] + for p in cur_layer: + for n in neighbours(p): + if n in board and board[n] != "#" and n not in visited: + visited.add(n) + next_layer.append(n) + if len(next_layer) == 0: + break steps += 1 - c.SIG_INPUT = False - if c.SIG_OUTPUT: - time.sleep(0.01) - print(draw(board, droid=(cur_x, cur_y))) - if c.output == 0: - #print("found wall") - board[(cur_x, cur_y)] = "#" - cur_x, cur_y = prev_x, prev_y - elif c.output == 1: - #print("found empty") - board[(cur_x, cur_y)] = "." - elif c.output == 2: - #print("found oxygen at", (cur_x, cur_y)) - board[(cur_x, cur_y)] = "S" - oxygen = (cur_x, cur_y) - else: + return steps + +def draw(board, droid=None, path=None, visited=None): + min_x=max_x=min_y=max_y = 0 + for p in board: + min_x = min(p[0], min_x) + max_x = max(p[0], max_x) + min_y = min(p[1], min_y) + max_y = max(p[1], max_y) + s = "" + for y in range(min_y-1, max_y+2): + s += "\n" + for x in range(min_x-1, max_x+2): + point = (x, y) + if droid is not None and point == droid: + s += "D" * 2 + elif path is not None and point in path: + s += "\u2591" * 2 + elif visited is not None and point in visited: + s += "." * 2 + elif point in board: + if board[point] == "#": + s += "\u2588" * 2 + elif board[point] == "S": + s += "\u2591" * 2 + else: + s += " " * 2 + else: + s += "." * 2 + return s + +def visualize(input): + cur_x = cur_y = 0 + q = collections.deque() + q.append((0,0)) + path = collections.deque() + board = {} + board[(0,0)] = "." + + c = intcode.Computer([int(x) for x in input[0].split(",")]) + + while not c.SIG_HALT: + if len(q) == 0: + break + c.step() + if c.SIG_INPUT: + direction = 0 + prev_x, prev_y = cur_x, cur_y + if len(path) == 0: + # find new path + for n in neighbours((cur_x, cur_y)): + if n not in q and n not in board: + q.append(n) + if (cur_x, cur_y) in q: + q.remove((cur_x, cur_y)) + next = q.pop() + path = get_path((cur_x, cur_y), next, board) + next_step = path.popleft() + if next_step[1] == cur_y-1: + direction = 1 + cur_y -= 1 + elif next_step[1] == cur_y+1: + direction = 2 + cur_y += 1 + elif next_step[0] == cur_x-1: + direction = 3 + cur_x -= 1 + elif next_step[0] == cur_x+1: + direction = 4 + cur_x += 1 + else: + print("invalid path") + break + c.input = direction + c.SIG_INPUT = False + if c.SIG_OUTPUT: + if c.output == 0: + board[(cur_x, cur_y)] = "#" + cur_x, cur_y = prev_x, prev_y + elif c.output == 1: + board[(cur_x, cur_y)] = "." + elif c.output == 2: + board[(cur_x, cur_y)] = "S" + oxygen = (cur_x, cur_y) + else: + break + time.sleep(0.0075) + print(draw(board, droid=(cur_x, cur_y))) + c.output = None + c.SIG_OUTPUT = False + + get_path((0,0), oxygen, board, draw_search=True) + + steps = 0 + visited = set(oxygen) + cur_layer = [] + next_layer = [oxygen] + while True: + cur_layer = next_layer.copy() + next_layer = [] + for p in cur_layer: + for n in neighbours(p): + if n in board and board[n] != "#" and n not in visited: + visited.add(n) + next_layer.append(n) + if len(next_layer) == 0: break - c.output = None - c.SIG_OUTPUT = False - if not auto: - print(draw(board, (cur_x, cur_y))) -print(draw(board)) -print(draw(board, path=get_path((0,0), oxygen, board))) -print(len(get_path((0,0), oxygen, board))) -print(steps) - -steps = 0 -visited = set(oxygen) -cur_layer = [] -next_layer = [oxygen] -while True: - cur_layer = next_layer.copy() - next_layer = [] - for p in cur_layer: - for n in neighbours(p): - if n in board and board[n] != "#" and n not in visited: - visited.add(n) - next_layer.append(n) - if len(next_layer) == 0: - break - steps += 1 -print(steps) + steps += 1 + +if __name__ == "__main__": + input = open("../input/15", "r").readlines() + print(pt1(input)) + print(pt2(input)) + visualize(input) diff --git a/solutions/py/main.py b/solutions/py/main.py index db4150e..aa7a4e2 100644 --- a/solutions/py/main.py +++ b/solutions/py/main.py @@ -13,8 +13,10 @@ import d10 import d11 import d12 import d13 +import d14 +import d15 -mods = [d01, d02, d03, d04, d05, d06, d07, d08, d09, d10, d11, d12, d13] +mods = [d01, d02, d03, d04, d05, d06, d07, d08, d09, d10, d11, d12, d13, d14, d15] timings = [[0 for _ in range(2)] for _ in range(len(mods))] clock_type = time.CLOCK_MONOTONIC |
