예제 #1
0
파일: day02.py 프로젝트: aah/advent
    >>> checksum(['5928', '9473', '3865'])
    (18, 9)
    """
    spreadsheet = [parse_and_sort(row) for row in spreadsheet]
    return (
        sum(row[-1] - row[0] for row in spreadsheet),  # part 1
        sum(quotient(row) for row in spreadsheet)  # part 2
    )


def quotient(row):
    """Find the quotient of the first pair to divide evenly in a sorted row."""
    for a, b in combinations(row, 2):
        if not b % a:
            return b // a
    return 0


def parse_and_sort(row):
    """Cast the values in a row to `int`s and then sort."""
    return sorted(int(n) for n in row)


if __name__ == '__main__':
    import doctest
    doctest.testmod()

    with puzzle_input(2) as f:
        sheet = csv.reader(f, delimiter='\t')
        print(checksum(sheet))
예제 #2
0
            player1.append(p2)
        else:
            player2.append(p2)
            player2.append(p1)

        if len(player1) == 0 or len(player2) == 0:
            winning_player = 1 if len(player2) == 0 else 2
            winning_hand = player1 if len(player2) == 0 else player2
            score = sum(
                (i + 1) * c for i, c in enumerate(reversed(winning_hand)))
            return turn, winning_player, winning_hand, score

        print()


with puzzle_input(21, example, False) as f:
    player1 = deque([
        31,
        33,
        27,
        43,
        29,
        25,
        36,
        11,
        15,
        5,
        14,
        34,
        7,
        18,
예제 #3
0
    "4",
    "2",
    "34",
    "10",
    "3",
])


def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)


with puzzle_input(10, example2, False) as f:
    data = [int(e) for e in f.read().split()]

    full = deque([0])  # start from dead battery
    builtin = max(data) + 3  # built in jotlage adapter
    full.extend(sorted(data))  # sorted? simplest way they can all be arranged
    builtin = max(data) + 3  # built in jotlage adapter
    full.append(builtin)

    jumps = [b - a for a, b in pairwise(full)]
    jolt_jumps = Counter(jumps)
    print(jolt_jumps[1] * jolt_jumps[3])  # Part 1

    # Part 2
    # DFS works for examples, and gives the paths... but for real inputs...
    # build adjacency, n^2? beurk but makes implementing the loop next much simpler
예제 #4
0
파일: day04.py 프로젝트: aah/advent
from utils import puzzle_input


def is_valid(passphrase: str, version: int = 1) -> bool:
    """Is a given `passphrase` valid?

    >>> is_valid('aa bb cc dd aa')
    False
    >>> is_valid('abcde xyz ecdab')
    True
    >>> is_valid('abcde xyz ecdab', version=2)
    False
    """
    passphrase = passphrase.split()

    if version == 2:
        passphrase = [''.join(sorted(word)) for word in passphrase]

    return len(passphrase) == len(set(passphrase))


if __name__ == '__main__':
    import doctest
    doctest.testmod()

    with puzzle_input(4) as f:
        passphrase_list = f.read().splitlines()

        for version in (1, 2):
            print(sum(is_valid(p, version) for p in passphrase_list))
예제 #5
0
파일: day01.py 프로젝트: aah/advent
    """Associate each item with its `n`th neighbor to the right (wrapping).

    >>> list(chunk('123', n=1))
    [('1', '2'), ('2', '3'), ('3', '1')]
    """
    c = len(l)
    return ((l[i], l[(i + n) % c]) for i in range(c))


def solve(digits: Iterable, places: int = 1) -> int:
    """Solve the CAPTCHA.

    >>> solve('1122')
    3
    >>> solve('1234')
    0
    >>> solve('123425', places=3)
    4
    """
    return sum(int(a) for a, b in chunk(digits, places) if a == b)


if __name__ == '__main__':
    import doctest
    doctest.testmod()

    with puzzle_input(1) as f:
        digits = f.read().strip()
        print(solve(digits))  # part 1
        print(solve(digits, len(digits) // 2))  # part 2
예제 #6
0
파일: day03.py 프로젝트: aah/advent
    return abs(x - a) + abs(y - b)


def spiral():
    """Generate the points of an infinite spiral.

    >>> s = spiral()
    >>> [next(s) for _ in range(5)]
    [(0, 0), (1, 0), (1, 1), (0, 1), (-1, 1)]
    """
    position = (0, 0)

    yield position

    for length, half in enumerate(cycle(HALVES), 1):
        for step in half:
            for _ in range(length):
                position = addv(position, step)
                yield position


if __name__ == '__main__':
    import doctest
    doctest.testmod()

    with puzzle_input(3) as f:
        N = int(f.read())

    print(carry_distance(N))  # part 1
    print(stress_test(N))  # part 2
예제 #7
0
range_ = seq(number, match_item("-") >> number).map(lambda x: range(x[0], x[1] + 1))
range_pair = seq(range_, whitespace >> string("or") >> whitespace >> range_)
rule = seq(rule_name, match_item(":") >> whitespace >> range_pair)
rules = rule.sep_by(match_item("\n")).map(dict)

fields = number.sep_by(match_item(","), min=1)
your_ticket = string("your ticket:\n") >> fields
nearby_tickets = string("nearby tickets:\n") >> fields.sep_by(match_item("\n"))

all_of_it = (
    seq(rules, string("\n\n") >> your_ticket, string("\n\n") >> nearby_tickets)
    << match_item("\n").optional()
)


with puzzle_input(16, example2, False) as field_values:
    data, remain = all_of_it.parse_partial(field_values.read())
    # print(data, repr(remain))
    print(repr(remain))

    all_ranges = list(chain.from_iterable(data[0].values()))
    # print(all_ranges)

    my_ticket = data[1]
    other_tickets = data[2]
    valid_tickets = []

    s = 0
    for ticket in other_tickets:
        valid = True
        for v in ticket:
예제 #8
0
    """Count the number of steps required to reach the exit.

    >>> count_steps([0, 3, 0, 1, -3])
    5
    """
    index, steps = 0, 0
    instructions = array('i', instructions[:])
    while True:
        try:
            index = jump(instructions, index, update)
            steps += 1
        except IndexError:
            return steps


def jump(instructions: list, index: int, update: Callable) -> int:
    """Execute and update a jump instruction."""
    next_index = index + instructions[index]
    instructions[index] = update(instructions[index])
    return next_index


if __name__ == '__main__':
    import doctest
    doctest.testmod()

    with puzzle_input(5) as f:
        instructions = [int(n) for n in f]
        print(count_steps(instructions))
        print(count_steps(instructions, update=lambda n: n + (n < 3 or -1)))
예제 #9
0
        "..##.......",
        "#...#...#..",
        ".#....#..#.",
        "..#.#...#.#",
        ".#...##..#.",
        "..#.##.....",
        ".#.#.#....#",
        ".#........#",
        "#.##...#...",
        "#...##....#",
        ".#..#...#.#",
    ]
)


with puzzle_input(3, example) as f:
    data = [list(l.strip()) for l in f.readlines()]


def slide(slope, direction, pos=(0, 0)):
    width = len(slope[0])
    trees = 0
    r, c = pos
    r_step, c_step = direction

    while r < len(slope):
        if slope[r][c] == "#":
            trees += 1

        r += r_step
        c = (c + c_step) % width