コード例 #1
0
ファイル: day_16_2021.py プロジェクト: dequeues/AdventOfCode
from functools import reduce
from typing import Callable

from aoc import utils

inputdata = utils.get_day_data(16, test_data=False)

TYPES: dict[int, Callable[..., int]] = {
    0: sum,
    1: lambda *args: reduce(lambda x, y: x * y, *args, 1),  # type: ignore
    2: min,
    3: max,
    5: lambda x: int(x[0] > x[0]),
    6: lambda x: int(x[0] < x[1]),
    7: lambda x: int(x[0] == x[1]),
}

VERSION_NUMBERS = []


def get_bin_data() -> str:
    data = f"{int(inputdata[0], 16):08b}"
    data = ("0" * (4 - num) + data) if (num := len(data) % 4) else data
    return data


def literal_value(packet: str) -> tuple[int, str]:
    value = ""
    while packet[0] == "1":
        value += packet[1:5]
        packet = packet[5:]
コード例 #2
0
ファイル: day_09_2020.py プロジェクト: dequeues/AdventOfCode
from itertools import permutations
from typing import Union

from aoc import utils


inputdata = list(map(int, utils.get_day_data(9)))
PREAMBLE = 25


def get_invalid() -> int:
    for i in range(PREAMBLE, len(inputdata)):
        solutions = [
            a + b for (a, b) in permutations(inputdata[i - PREAMBLE : i], 2)
        ]
        if inputdata[i] not in solutions:
            return int(inputdata[i])

    return 0


def find_contiguous(
    start: int, check: int
) -> Union[list[int], bool]:  # noqa pylint: disable=unsubscriptable-object
    total = 0
    for i in range(start, len(inputdata)):
        total += inputdata[i]
        if total == check:
            return inputdata[start : (i + 1)]
        elif total > check:
            return False
コード例 #3
0
from collections import Counter

from aoc import utils

inputlist = utils.get_day_data(6, split_delimiter="\n\n")


def part1() -> int:
    total: int = 0
    for group in [x.replace("\n", "") for x in inputlist]:
        total += len(Counter(group).keys())

    return total


def part2() -> int:
    total: int = 0
    for group in inputlist:
        letter_counter = Counter(group)
        people_count = len(group.split("\n"))
        answered_by_each_person = [
            x == people_count for x in letter_counter.values()
        ]
        total += sum(answered_by_each_person)

    return total


utils.print_result(f"Part 1 answer: {part1()}")
utils.print_result(f"Part 2 answer: {part2()}")
コード例 #4
0
ファイル: day_02_2021.py プロジェクト: dequeues/AdventOfCode
from aoc import utils

inputdata = utils.get_day_data(2)

# mypy doesn't yet support match statements :-(
# https://github.com/python/mypy/pull/10191


def part1() -> int:
    horizontal, depth = 0, 0

    for course_command in inputdata:
        direction, str_amount = course_command.split(" ")
        amount = int(str_amount)
        if direction == "forward":
            horizontal += amount
        elif direction == "down":
            depth += amount
        else:
            depth -= amount

    return horizontal * depth


def part2() -> int:
    horizontal, depth, aim = 0, 0, 0

    for course_command in inputdata:
        direction, str_amount = course_command.split(" ")
        amount = int(str_amount)
        if direction == "forward":
コード例 #5
0
from __future__ import annotations

import json
import math
from copy import deepcopy
from itertools import permutations
from typing import Any
from typing import Optional

from aoc import utils

inputdata: list[Any] = utils.get_day_data(18,
                                          test_data=False,
                                          line_format_func=json.loads)


class SnailfishNumber:
    left: Optional[SnailfishNumber] = None
    right: Optional[SnailfishNumber] = None
    value: Optional[int] = None
    parent: Optional[SnailfishNumber]

    def __init__(self,
                 value: Any,
                 parent: SnailfishNumber | None = None) -> None:
        self.parent = parent
        if isinstance(value, list):
            self.left = SnailfishNumber(value[0], self)
            self.right = SnailfishNumber(value[1], self)
            self.value = None
        else:
コード例 #6
0
ファイル: day_09_2021.py プロジェクト: dequeues/AdventOfCode
import numpy as np

from aoc import utils

input_data = utils.get_day_data(9, test_data=False)

heightmap = np.array([list(line) for line in input_data], dtype=int)
low_adj = []
low_points = []


def part1() -> int:
    for i in range(heightmap.shape[0]):
        for j in range(heightmap.shape[1]):
            if get_window_max([i, j], heightmap):
                low_adj.append(heightmap[i][j] + 1)
                low_points.append([i, j])
    return sum(low_adj)


def part2() -> int:
    basins = []
    for loc_min in low_points:
        data = heightmap.copy()

        flood_fill(data, loc_min[0], loc_min[1])

        basin = data == 10
        basin_size = len(data[basin])
        basins.append(basin_size)
        top_3_basins = sorted(basins)[-3:]
コード例 #7
0
import numpy as np

from aoc import utils

inputdata = utils.get_day_data(7, test_data=False, split_delimiter=",")


def part1() -> int:
    crabs = list(map(int, inputdata.copy()))

    median = np.round(np.median(crabs))

    return int(sum([np.abs(median - x) for x in crabs]))


def part2() -> int:
    data = list(map(int, inputdata.copy()))

    mean = int(np.mean(data))

    return int(
        sum(np.abs(x - mean) * (np.abs(x - mean) + 1) // 2 for x in data))


utils.print_result(f"Part 1 answer: {part1()}")
utils.print_result(f"Part 2 answer: {part2()}")
コード例 #8
0
from itertools import permutations

from aoc import utils


inputdata = utils.get_day_data(
    8, test_data=False, line_format_func=lambda x: x.split(" | ")
)

combinations: dict[str, int] = {
    "abcefg": 0,
    "cf": 1,
    "acdeg": 2,
    "acdfg": 3,
    "bcdf": 4,
    "abdfg": 5,
    "abdefg": 6,
    "acf": 7,
    "abcdefg": 8,
    "abcdfg": 9,
}


def part1() -> int:
    data = inputdata.copy()

    return_no = 0
    for line in data:
        _, output_data = line[0].split(" "), line[1].split(" ")
        return_no += sum(len(code) in [2, 3, 4, 7] for code in output_data)
コード例 #9
0
ファイル: day_02_2020.py プロジェクト: dequeues/AdventOfCode
def format_input(input_data: list[str]) -> list[tuple[int, int, str, str]]:
    outlist: list[tuple[int, int, str, str]] = []
    part_re = re.compile("([0-9]+)-([0-9]+) ([a-zA-Z]): ([a-zA-Z]+)")
    for line in input_data:
        split = part_re.match(line)
        if split:
            outlist.append((
                int(split.group(1)),
                int(split.group(2)),
                str(split.group(3)),
                str(split.group(4)),
            ))
    return outlist


input_list: list[str] = utils.get_day_data(2)
formatted_input = format_input(input_list)


def part1() -> int:
    valid_passwords: int = 0
    for tup in formatted_input:
        password_min, password_max, password_char, password = tup
        charcount: int = password.count(password_char)
        if password_max >= charcount >= password_min:
            valid_passwords += 1

    return valid_passwords


def part2() -> int:
コード例 #10
0
ファイル: day_04_2021.py プロジェクト: dequeues/AdventOfCode
from re import sub
from typing import Union

import numpy as np

from aoc import utils


inputdata = utils.get_day_data(4, split_delimiter="\n")


def part1() -> int:
    drawn_numbers, cards = process_and_get_input()
    for drawn in drawn_numbers:
        cards = np.where(cards == drawn, np.nan, cards)
        states = np.array([does_board_have_a_winner(board) for board in cards])
        if np.any(states):
            return int(np.nansum(cards[np.argmax(states)]) * drawn)

    return 0


def part2() -> int:
    drawn_numbers, cards = process_and_get_input()
    last = -1
    for drawn in drawn_numbers:
        cards = np.where(cards == drawn, np.nan, cards)
        states = np.array([does_board_have_a_winner(board) for board in cards])
        if np.count_nonzero(~states) == 1:
            last = int(np.argmin(states))
コード例 #11
0
ファイル: day_04_2020.py プロジェクト: dequeues/AdventOfCode
    "iyr": (lambda n: int(n) and len(n) == 4 and 2010 <= int(n) <= 2020),
    "eyr": (lambda n: int(n) and len(n) == 4 and 2020 <= int(n) <= 2030),
    "hgt": (
        lambda n: int(n[:-2])
        and n[-2:] in ["cm", "in"]
        and (
            (n[-2:] == "cm" and 150 <= int(n[:-2]) <= 193)
            or (n[-2:] == "in" and 59 <= int(n[:-2]) <= 76)
        )
    ),
    "hcl": (lambda n: len(n) == 7 and match("#[0-9a-f]{6}", n)),
    "ecl": (lambda n: n in ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"]),
    "pid": (lambda n: int(n) and len(n) == 9),
}

input_as_list = utils.get_day_data(4, split_delimiter="\n\n")


def get_passports_dict_from_list() -> list[dict[str, str]]:
    passport_list: list[dict[str, str]] = []
    for line in input_as_list:
        line = line.replace("\n", " ").replace(" ", ",")
        sections = line.split(",")
        keyval = [section.split(":") for section in sections]
        passport_list.append({key: value for (key, value) in keyval})

    return passport_list


def has_all_required_fields(passport: dict[str, str]) -> bool:
    return all(field in passport for field in REQUIRED_FIELDS)
コード例 #12
0
import re

from aoc import utils


BAG_RULE = re.compile(r"(\d+) ([\w ]+) bag")
BAG_COLOR = "shiny gold"

inputlist: list[str] = utils.get_day_data(7)


def get_tree(data: list[str]) -> dict[str, list[tuple[int, str]]]:
    rules = {}
    for line in data:
        color, contents = line.split(" bags contain ")
        bag_content = BAG_RULE.findall(contents)
        rules[color] = [(int(n), inner) for n, inner in bag_content]

    return rules


def count_bags_of(target, tree) -> int:
    count = 0
    for color in tree:
        if has_bag(color, target, tree):
            count += 1
    return count


def has_bag(color, target, tree) -> bool:
    contents = tree[color]
コード例 #13
0
ファイル: day_01_2020.py プロジェクト: dequeues/AdventOfCode
from aoc import utils

input_list: list[int] = utils.convert_list_to_ints(utils.get_day_data(1))


def part1() -> int:
    for i in input_list:
        for j in input_list:
            if i + j == 2020:
                return i * j
    return 0


def part2() -> int:
    for i in input_list:
        for j in input_list:
            for k in input_list:
                if i + j + k == 2020:
                    return i * j * k
    return 0


utils.print_result(f"Part 1 answer: {part1()}")
utils.print_result(f"Part 2 answer: {part2()}")
コード例 #14
0
ファイル: day_05_2020.py プロジェクト: dequeues/AdventOfCode
            ) for line in file.read().split("\n")
        ]


def format_input_to_seat_bin_list(data: list[str]) -> list[int]:
    return [
        int(
            seat.replace("F", "0").replace("B",
                                           "1").replace("L",
                                                        "0").replace("R", "1"),
            base=2,
        ) for seat in data
    ]


seat_list_raw: list[str] = utils.get_day_data(5)
seat_list: list[int] = format_input_to_seat_bin_list(seat_list_raw)


def part1() -> int:
    return max(seat_list)


def part2() -> int:
    seat = 0
    for i in range(min(seat_list), max(seat_list)):
        if (i not in seat_list and (i - 1) in seat_list
                and (i + 1) in seat_list):
            seat = i
            break
コード例 #15
0
ファイル: day_05_2021.py プロジェクト: dequeues/AdventOfCode
from dataclasses import dataclass
from types import SimpleNamespace

import numpy as np

from aoc import utils

inputdata = utils.get_day_data(5, line_format_func=lambda x: x.split(" -> "))


@dataclass
class Vent:
    x_1: int
    y_1: int
    x_2: int
    y_2: int

    @property
    def is_horizontal(self) -> bool:
        return self.y_1 == self.y_2

    @property
    def is_vertical(self) -> bool:
        return self.x_1 == self.x_2

    def line_coords(self):
        vec = np.sign([self.x_2 - self.x_1, self.y_2 - self.y_1])
        coords = SimpleNamespace(**{"x": [self.x_1], "y": [self.y_1]})

        while coords.x[-1] != self.x_2 or coords.y[-1] != self.y_2:
            coords.x.append(coords.x[-1] + vec[0])