예제 #1
0
    def replace_at_index(s: str, r: str, idx: int) -> str:
        return s[:idx] + r + s[idx + 1:]


def part_a():
    decoder = Decoder()
    for cmd, args in data:
        decoder.interpret(cmd, args)
    return decoder.calc_sum()


def part_b():
    decoder = QuantumDecoder()
    for cmd, args in data:
        decoder.interpret(cmd, args)
    return decoder.calc_sum()


def load():
    return [(match.group(1), match.groups()[1:])
            for line in problem.data()
            for match in [p.match(line) for p in PATTERNS] if match]


if __name__ == '__main__':
    problem = Problem(14)
    data = load()

    problem.submit(part_a(), 'a')  # 6513443633260
    problem.submit(part_b(), 'b')  # 3442819875191
예제 #2
0
    with open('entries.txt', 'w') as fh:
        for entry in entries.items():
            node, children = entry
            fh.write(f"{node}: {children}\n")


def pickle_trees():
    entries = parse_nodes(problem.data())
    trees = build_trees(entries)
    with open('trees.pkl', 'wb') as fh:
        pkl.dump(trees, fh)


def load():
    with open('trees.pkl', 'rb') as fh:
        return pkl.load(fh)


if __name__ == '__main__':
    problem = Problem(7)
    # pickle_trees()
    trees = load()

    # Collect every 'shiny gold bag' nodes in all trees
    shiny_gold_bags = list()
    for tree in trees:
        find_nodes('shiny gold bag', tree, shiny_gold_bags)

    problem.submit(part_a(), 'a')  # 124
    problem.submit(part_b(), 'b')  # 34862
예제 #3
0
    def adj(self, ref: Tile) -> list:
        return [tile for tile in self.tiles.values() if tile.is_adj(*ref.pos)]


def part_a(instructions: list):
    hexgrid = HexGrid()
    hexgrid.find_and_flip(instructions)
    return hexgrid.count_color(BLACK)


def part_b(instructions: list):
    hexgrid = HexGrid()
    hexgrid.find_and_flip(instructions)
    print(hexgrid.count_color(BLACK))
    hexgrid.live(iterations=100)
    return hexgrid.count_color(BLACK)


def load(p: Problem):
    return [re.findall(PATTERN, instr) for instr in p.data()]


if __name__ == '__main__':
    problem = Problem(24, test=False)

    # print(part_a(load(problem)))
    # print(part_b(load(problem)))

    # problem.submit(part_a(load(problem)), 'a')
    problem.submit(part_b(load(problem)), 'b')
예제 #4
0
from src.problem import Problem
import itertools


def part_a():
    comb = itertools.combinations(data, 2)
    comb = [(a, b) for a, b in comb if a + b == 2020]
    return comb[0][0] * comb[0][1]


def part_b():
    comb = itertools.combinations(data, 3)
    comb = [(a, b, c) for a, b, c in comb if a + b + c == 2020]
    return comb[0][0] * comb[0][1] * comb[0][2]


def load():
    return problem.data(dtype=int)


if __name__ == '__main__':
    problem = Problem(1)
    data = load()

    problem.submit(part_a(), 'a')  # 960075
    problem.submit(part_b(), 'b')  # 212900130
예제 #5
0
def part_a():
    pocket_dim = np.expand_dims(data, axis=0)
    for _ in range(6):
        pocket_dim = convolve_cubes(pocket_dim, KERNEL_3D)
    return np.count_nonzero(pocket_dim == 1)


def part_b():
    pocket_dim = np.expand_dims(np.expand_dims(data, axis=0), axis=0)
    for _ in range(6):
        pocket_dim = convolve_cubes(pocket_dim, KERNEL_4D)
    return np.count_nonzero(pocket_dim == 1)


def convolve_cubes(grid: np.ndarray, kernel: np.ndarray):
    c = convolve(grid, kernel)
    return np.vectorize(lambda elem: elem in [3, 102, 103])(c)


def load():
    return np.array([list(line) for line in problem.data()]) == '#'


if __name__ == '__main__':
    problem = Problem(17)
    data = load()

    problem.submit(part_a(), 'a')  # 295
    problem.submit(part_b(), 'b')  # 1972
예제 #6
0

def part_a():
    for i, num in enumerate(data[26:]):
        preamble = data[i:26 + i]
        if num not in [sum(pair) for pair in it.combinations(preamble, 2)]:
            return num


def part_b():
    for start, _ in enumerate(data):
        for end, acc in enumerate(it.accumulate(data[start:]), start):
            if acc == invalid_num:
                return min(data[start:end]) + max(data[start:end])
            if acc > invalid_num:
                break


def load():
    return problem.data(dtype=int)


if __name__ == '__main__':
    problem = Problem(9)
    data = load()

    invalid_num = part_a()

    problem.submit(invalid_num, 'a')  # 85848519
    problem.submit(part_b(), 'b')  # 13414198
예제 #7
0
    # Diagonal up-left
    for r, c in zip(reversed(range(0, r0)), reversed(range(0, c0))):
        if seats[r][c] == OCCUPIED:
            n += 1
            break
        if seats[r][c] == FREE:
            break
    # Diagonal down-left
    for r, c in zip(range(r0 + 1, len(seats)), reversed(range(0, c0))):
        if seats[r][c] == OCCUPIED:
            n += 1
            break
        if seats[r][c] == FREE:
            break
    # Diagonal up-right
    for r, c in zip(reversed(range(0, r0)), range(c0 + 1, len(seats[0]))):
        if seats[r][c] == OCCUPIED:
            n += 1
            break
        if seats[r][c] == FREE:
            break
    return n


if __name__ == '__main__':
    problem = Problem(11)
    data = load()

    problem.submit(part_a(), 'a')  # 2243
    problem.submit(part_b(), 'b')  # 2027
예제 #8
0
                  "W": lambda u, ship: ship.move_waypoint(Cardinal.WEST, u),
                  "L": lambda d, ship: ship.turn_waypoint(Direction.LEFT, d),
                  "R": lambda d, ship: ship.turn_waypoint(Direction.RIGHT, d),
                  "F": lambda u, ship: ship.forward_waypoint(u)}


def part_a():
    ship = Ship()
    for instr, param in data:
        INSTRUCTIONS_A[instr](param, ship)
    return abs(ship.position[0]) + abs(ship.position[1])


def part_b():
    ship = Ship()
    for instr, param in data:
        INSTRUCTIONS_B[instr](param, ship)
    return abs(ship.position[0]) + abs(ship.position[1])


def load():
    return [(i[0], int(i[1:])) for i in problem.data()]


if __name__ == '__main__':
    problem = Problem(12)
    data = load()

    problem.submit(part_a(), 'a')  # 1032
    problem.submit(part_b(), 'b')  # 156735
예제 #9
0
            if all(rules[r](ticket.split(',')[pos]) for ticket in tickets):
                if unique_rule:  # If more then one rule applies to the position, skip the position
                    unique_rule = None
                    break
                unique_rule = (r, pos)
        # If unique rule was found, return it
        if unique_rule:
            return unique_rule


def load():
    data = problem.data()
    your_ticket = data.index('your ticket:')
    nearby_tickets = data.index('nearby tickets:')
    return [
        data[:your_ticket - 1], data[your_ticket + 1],
        data[nearby_tickets + 1:]
    ]


if __name__ == '__main__':
    problem = Problem(16)
    data = load()

    rules = {(m := RULE_PATTERN.match(line)).group(1):
             _rule_closure(m.group(2), m.group(3), m.group(4), m.group(5))
             for line in data[0]}

    problem.submit(part_a(), 'a')  # 20091
    problem.submit(part_b(), 'b')  # 2325343130651
예제 #10
0
def part_a():
    return sum([
        len(answer) for answer in [
            set([answer for person in group.split('\n') for answer in person])
            for group in data
        ]
    ])


def part_b():
    return sum([
        len(answer) for answer in [
            set.intersection(*[
                set(answer for answer in person)
                for person in group.split('\n')
            ]) for group in data
        ]
    ])


def load():
    return problem.data(delim='\n\n')


if __name__ == '__main__':
    problem = Problem(6)
    data = load()

    problem.submit(part_a(), 'a')  # 6625
    problem.submit(part_b(), 'b')  # 3360
예제 #11
0
        occ = password.count(letter)
        if min_occ <= occ <= max_occ:
            valid_entries += 1

    return valid_entries


def part_b():
    valid_entries = 0
    for entry in data:
        pos1 = int(entry.split("-")[0]) - 1
        pos2 = int(entry.split("-")[1].split(" ")[0]) - 1
        letter = entry.split(" ")[1].split(":")[0]
        password = entry.split(" ")[2]
        if (password[pos1] == letter) ^ (password[pos2] == letter):
            valid_entries += 1

    return valid_entries


def load():
    return problem.data()


if __name__ == '__main__':
    problem = Problem(2)
    data = load()

    problem.submit(part_a(), 'a')  # 600
    problem.submit(part_b(), 'b')  # 245
예제 #12
0
            term = self._expr()
            self._check(Token.Kind.rpar)
        else:
            raise RuntimeError("Term must be called with number or lpar token")
        return term


def part_a(data: str):
    parser = LRParser(data)
    for _ in range(len(data.split('\n'))):
        parser.parse()
    return sum(parser.results)


def part_b(data: str):
    parser = PunstriParser(data)
    for _ in range(len(data.split('\n'))):
        parser.parse()
    return sum(parser.results)


def load(p: Problem):
    return p.raw_data()


if __name__ == '__main__':
    problem = Problem(18)

    problem.submit(part_a(load(problem)), 'a')  # 8929569623593
    problem.submit(part_b(load(problem)), 'b')  # 231235959382961
예제 #13
0
                return False
        elif key == 'hcl':
            if value[0] == '#':
                rgb = value[1:]
                for c in rgb:
                    if not (c.isdigit() or 'a' <= c <= 'f'):
                        return False
            else:
                return False
        elif key == 'ecl':
            if value not in ['amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth']:
                return False
        elif key == 'pid':
            if len(value) != 9:
                return False
        elif key == 'cid':
            pass  # ignore cid
    return True


def load():
    return problem.data(delim='\n\n')


if __name__ == '__main__':
    problem = Problem(4)
    data = load()

    problem.submit(part_a(), 'a')  # 210
    problem.submit(part_b(), 'b')  # 131
예제 #14
0
        row_area = binary_partitioning(row_area, row_action)
    for col_action in col_actions:
        col_area = binary_partitioning(col_area, col_action)

    assert row_area[0] == row_area[1]
    assert col_area[0] == col_area[1]

    return row_area[0], col_area[0]


def binary_partitioning(area, action):
    lower = area[0]
    upper = area[1]
    middle = int((upper + lower) / 2)
    if action == 'F' or action == 'L':
        return [lower, middle]
    if action == 'B' or action == 'R':
        return [middle + 1, upper]


def load():
    return problem.data()


if __name__ == '__main__':
    problem = Problem(5)
    data = load()

    problem.submit(part_a(), 'a')  # 974
    problem.submit(part_b(), 'b')  # 646