コード例 #1
0
ファイル: d19.py プロジェクト: shahroudy/Advent-of-Code
class TractorBeam:
    def __init__(self, filename):
        self.program = read_int_list(filename)
        self.computer = IntcodeComputer(self.program.copy())

    def read(self, x, y):
        return bool(self.computer.compute(deque([x, y])).pop())

    def affected_in_50x50(self):
        return sum([self.read(*p) for p in product(range(50), repeat=2)])

    def detect_100x100_square(self):
        start_cols = defaultdict(int)
        row = 0
        while True:
            row += 1
            start = start_cols[row - 1]
            for col in range(start, start + 50):
                if self.read(col, row):
                    break
            else:
                continue
            start_cols[row] = col
            if (start_cols[col - 99] > 0 and self.read(col + 99, row)
                    and col >= start_cols[col - 99]
                    and self.read(col + 99, row - 99)):
                return col * 10000 + row - 99
コード例 #2
0
from collections import defaultdict
from myutils.file_reader import read_int_list
from aoc2019.day09.d09 import IntcodeComputer

prog = read_int_list('input.txt')

for puzzle in [1, 2]:
    panels = defaultdict(bool)  # false is black
    ic = IntcodeComputer(prog)
    if puzzle == 2:
        panels[(0, 0)] = True
    x, y = 0, 0
    dx, dy = 0, -1

    painted = set()

    while not ic.halted:
        input = 1 if panels[(x, y)] else 0
        out = ic.step(input)
        code = out.popleft()
        move = out.popleft()
        if code == 0:
            panels[(x, y)] = False
        elif code == 1:
            panels[(x, y)] = True
        else:
            raise Exception('Invalid output code!')
        if puzzle == 1:
            painted.add((x, y))
        if move == 0:
            dx, dy = dy, -dx
コード例 #3
0
ファイル: d15.py プロジェクト: shahroudy/Advent-of-Code
class OxygenSystem:
    def __init__(self, filename):
        self.program = read_int_list(filename)

    def reset(self):
        self.computer = IntcodeComputer(self.program.copy())
        self.map = defaultdict(int)  # 0: unknown, 1: open, -1: blocked

    def display_map(self):
        minx = miny = -5
        maxx = maxy = 5
        for x, y in self.map.keys():
            minx = min(minx, x)
            maxx = max(maxx, x)
            miny = min(miny, y)
            maxy = max(maxy, y)
        os.system('clear')
        print()
        for j in range(miny, maxy + 1):
            for i in range(minx, maxx + 1):
                if (i, j) == self.oxygen:
                    ch = 'O'
                elif j == self.y and i == self.x:
                    ch = 'd'
                else:
                    m = self.map[(i, j)]
                    if m > 0:
                        ch = '.'
                    elif m < 0:
                        ch = '#'
                    else:
                        ch = ' '
                print(ch, end='')
            print()
        time.sleep(0.05)

    def neighbours(self, x, y):
        return [(x + i, y + j) for i, j in [(-1, 0), (1, 0), (0, -1), (0, 1)]]

    def moves_to(self, target):
        conn = dict()
        q = deque([target])
        while q:
            c = q.popleft()
            x, y = c
            for n in self.neighbours(x, y):
                if self.map[n] > 0 and n not in conn:
                    conn[n] = c
                    if n == (self.x, self.y):
                        q.clear()
                        break
                    q.append(n)
        result = deque()
        c = (self.x, self.y)
        while c != target:
            n = conn[c]
            if n[0] > c[0]:
                result.append(4)
            elif n[1] > c[1]:
                result.append(2)
            elif n[0] < c[0]:
                result.append(3)
            elif n[1] < c[1]:
                result.append(1)
            else:
                raise Exception('unknown move')
            c = n
        return result

    def navigate(self, display=False):
        self.reset()
        self.x = self.y = 0
        self.map[(0, 0)] = 1
        to_visit = deque([(0, 1)])  # first must see neighbor
        tape = deque()
        self.oxygen = None
        while to_visit:
            to_visit = deque([p for p in to_visit if self.map[p] == 0])
            ns = [
                n for n in self.neighbours(self.x, self.y) if self.map[n] == 0
            ]
            to_visit.extend(ns)
            while not tape:
                tape = self.moves_to(to_visit.pop())

            move = tape.popleft()

            output = self.computer.step(move)
            if len(output) != 1:
                raise Exception('invalid output')
            output = output[0]

            if move == 1:
                dest = (self.x, self.y - 1)
            elif move == 2:
                dest = (self.x, self.y + 1)
            elif move == 3:
                dest = (self.x - 1, self.y)
            elif move == 4:
                dest = (self.x + 1, self.y)
            else:
                raise Exception('invalid move')

            if output == 0:
                self.map[dest] = -1
            else:
                self.map[dest] = 1
                self.x, self.y = dest
                if output == 2:
                    self.oxygen = dest
            if display:
                self.display_map()
        return

    def calc_oxygen_distance(self):
        self.x, self.y = self.oxygen
        return len(self.moves_to((0, 0)))

    def calc_filling_time(self):
        q = [self.oxygen]
        self.map[self.oxygen] = 2
        t = 0
        while True:
            newq = []
            for c in q:
                for n in self.neighbours(*c):
                    if self.map[n] == 1:
                        newq.append(n)
                        self.map[n] = 2
            if newq:
                t += 1
                q = newq
            else:
                return t
コード例 #4
0
ファイル: d15.py プロジェクト: shahroudy/Advent-of-Code
 def reset(self):
     self.computer = IntcodeComputer(self.program.copy())
     self.map = defaultdict(int)  # 0: unknown, 1: open, -1: blocked
コード例 #5
0
class CarePackage:
    def __init__(self, filename):
        self.program = read_int_list(filename)

    def reset(self):
        self.computer = IntcodeComputer(self.program)
        self.board = defaultdict(int)
        self.score = 0
        self.ball_x = 0
        self.paddle_x = 0

    def apply_output(self, out):
        while out:
            x, y, obj = out.popleft(), out.popleft(), out.popleft()
            if x >= 0:
                self.board[(y, x)] = obj
                if obj == 3:
                    self.paddle_x = x
                elif obj == 4:
                    self.ball_x = x
            else:
                self.score = obj

    def read_board(self):
        self.apply_output(self.computer.step())

    def play_move(self, input):
        self.apply_output(self.computer.step(input))

    def count_blocks(self):
        self.reset()
        self.read_board()
        count = 0
        for v in self.board.values():
            if v == 2:
                count += 1
        return count

    @staticmethod
    def display_char(object):
        if object == 0:
            print(' ', end='')
        elif object == 1:
            print('#', end='')
        elif object == 2:
            print('x', end='')
        elif object == 3:
            print('T', end='')
        elif object == 4:
            print('o', end='')

    def display_board(self):
        xmin = xmax = ymin = ymax = 0
        for k in self.board.keys():
            y, x = k
            xmin = min(xmin, x)
            xmax = max(xmax, x)
            ymin = min(ymin, y)
            ymax = max(ymax, y)
        os.system('clear')
        print(f'Score: {self.score}')
        for y in range(ymin, ymax + 1):
            for x in range(xmin, xmax + 1):
                self.display_char(self.board[(y, x)])
            print()

    def play_arcade(self, display=False):
        self.reset()
        self.read_board()
        self.computer.program[0] = 2
        self.computer.halted = False
        while not self.computer.halted:
            if display:
                self.display_board()
                time.sleep(0.04)
            diff = self.ball_x - self.paddle_x
            if diff == 0:
                input = 0
            elif diff > 0:
                input = 1
            else:
                input = -1
            self.play_move(input)
        return self.score
コード例 #6
0
 def reset(self):
     self.computer = IntcodeComputer(self.program)
     self.board = defaultdict(int)
     self.score = 0
     self.ball_x = 0
     self.paddle_x = 0
コード例 #7
0
ファイル: d19.py プロジェクト: shahroudy/Advent-of-Code
 def __init__(self, filename):
     self.program = read_int_list(filename)
     self.computer = IntcodeComputer(self.program.copy())
コード例 #8
0
 def reset(self):
     self.computer = IntcodeComputer(self.program.copy())
コード例 #9
0
class SetAndForget:
    def __init__(self, filename):
        self.program = read_int_list(filename)

    def reset(self):
        self.computer = IntcodeComputer(self.program.copy())

    def analyze_output(self, input, just_final_output=False):
        output = self.computer.compute(input)
        if just_final_output:
            return output.pop()
        output = ''.join(map(chr, output))
        self.map = defaultdict(int)  # 0: ., 1: #
        row, col = 0, 0
        self.cols = 0
        for cell in output:
            if cell == '\n':
                if self.cols == 0:
                    self.cols = col
                col = 0
                row += 1
                continue
            if cell in 'v^><':
                self.y, self.x = row, col
                if cell == '^':
                    self.dy, self.dx = -1, 0
                elif cell == 'v':
                    self.dy, self.dx = 1, 0
                elif cell == '<':
                    self.dy, self.dx = 0, -1
                elif cell == '>':
                    self.dy, self.dx = 0, 1
            elif cell == '#':
                self.map[(row, col)] = 1
            elif cell == '.':
                self.map[(row, col)] = 0
            else:
                break
            col += 1
        self.rows = row
        print(output)

    def alignment(self):
        self.reset()
        self.analyze_output([])
        mask = [[0, 0], [-1, 0], [1, 0], [0, -1], [0, 1]]
        total = 0
        for cell in list(self.map.keys()):
            y, x = cell
            for mask_cell in mask:
                dy, dx = mask_cell
                if not self.map[(y + dy, x + dx)]:
                    break
            else:
                total += x * y
                self.map[(y, x)] = 2
        return total

    def calculate_plain_program(self):
        input = []
        map = self.map.copy()
        y, x = self.y, self.x
        dy, dx = self.dy, self.dx
        fc = 0
        while True:
            rcount = 0
            while map[(y + dy, x + dx)] == 0 and rcount < 4:
                dy, dx = -dx, dy
                rcount += 1
            if rcount == 0:
                fc += 1
                y += dy
                x += dx
                map[(y, x)] -= 1
            else:
                if fc:
                    input.append(str(fc))
                    fc = 0
                if rcount == 1:
                    input.append('L')
                elif rcount == 3:
                    input.append('R')
                elif rcount == 4:
                    break
                else:
                    raise Exception('Rotated Back!')
        return input

    def cleaning(self):
        self.program[0] = 2
        self.reset()
        input = self.calculate_plain_program()
        print(','.join(input))

        # Manually analyzed!
        input = \
            'A,A,C,B,C,B,C,B,B,A\n'\
            'L,10,R,8,R,8\n'\
            'R,10,L,12,R,10\n'\
            'L,10,L,12,R,8,R,10\n'\
            'n\n'
        input = deque(map(ord, input))
        collected = \
            self.analyze_output(
                input,
                just_final_output=True)
        print(f'Collected Dust: {collected}')