def part_2():
    instructions = get_strings_by_lines('8.txt')
    for idx in range(len(instructions)):
        # Copy the instructions
        copy = [] + instructions
        log(f'trying flipping instruction {idx}')
        if instructions[idx][:3] == 'jmp':
            copy[idx] = 'nop' + instructions[idx][3:]
        elif instructions[idx][:3] == 'nop':
            copy[idx] = 'jmp' + instructions[idx][3:]
        else:
            log('skipping instr: ' + instructions[idx])

        acc, pointer = 0, 0
        already_run = set()

        while pointer not in already_run:
            instr = copy[pointer]
            already_run.add(pointer)
            acc, pointer = run_instr(instr, acc, pointer)

            if pointer == len(instructions):
                log(f'found it flipping idx {idx}')
                return acc

        log('Failed idx {idx}')

    return None
def parse_tree():
    rules = get_strings_by_lines('7.txt')
    for rule in rules:
        specifier, contain_string = rule.split(' bags contain ')
        # Add this object to the tree if we don't know anything about it
        if specifier not in tree:
            curr_bag = Bag(specifier)
            tree[specifier] = curr_bag
        else:
            curr_bag = tree[specifier]

        for spec in contain_string.strip('.').split(', '):
            spec = spec.strip('s')
            if spec == 'no other bag':
                continue
            else:
                number, bag = parse('{:d} {} bag', spec)
                if bag in tree:
                    target_bag = tree[bag]
                else:
                    target_bag = Bag(bag)
                    tree[bag] = target_bag

                curr_bag.children[bag] = number
                curr_bag.contains.add(bag)
                target_bag.parents.add(curr_bag.name)
Example #3
0
def part_2():
    earliest, bus_list = get_strings_by_lines('13.txt')
    busses = [ bus for bus in bus_list.split(',') if bus ]

    # Fulfill the constraints one at a time - Once you find a number satisfying
    # Two divisors, future values must be a multiple of that value.
    # AKA for divisors w,x,y,z the minimum value satisfying y must be
    #   <the minimum value satisfying w,x> + (w * x)
    # And then the minimum value satisfying z must be
    #   <the minimum value satisfying w,x,y> + (w * x * y)
    # ETC.
    current_time = 0
    inc = 1
    for idx in range(len(busses)):
        if busses[idx] == 'x':
            log(f'Skipping idx {idx}')
            continue
        curr_bus = int(busses[idx])

        while (current_time + idx) % curr_bus != 0:
            current_time += inc

        log(f'constraint fulfilled! {curr_bus}')
        inc *= curr_bus
        log(f'New Inc: {inc}')

    return current_time
def part_1():
    x, y, dir = 0, 0, 'E'
    log(f"({x}, {y}, {dir})")
    for instr_str in get_strings_by_lines('12.txt'):
        x, y, dir = handle_instruction(x, y, dir, instr_str)
        log(f"({x}, {y}, {dir})")

    return abs(x) + abs(y)
def part_2():
    x, y, wx, wy = 0, 0, 10, 1
    log(f"({x}, {y}), ({wx}, {wy})")
    for instr_str in get_strings_by_lines('12.txt'):
        x, y, wx, wy = handle_instruction_with_waypoint(
            x, y, wx, wy, instr_str)
        log(f"({x}, {y}), ({wx}, {wy})")

    return abs(x) + abs(y)
def part_1():
    instructions = get_strings_by_lines('8.txt')
    acc, pointer = 0, 0
    already_run = set()

    while pointer not in already_run:
        instr = instructions[pointer]
        already_run.add(pointer)
        acc, pointer = run_instr(instr, acc, pointer)

    return acc
Example #7
0
def part_1():
    earliest, bus_list = get_strings_by_lines('13.txt')
    current_time = int(earliest)
    busses = [ int(bus) for bus in bus_list.split(',') if bus and bus != 'x']
    while True:
        log(f'Testing: {current_time}')
        for bus in busses:
            if current_time % bus == 0:
                log('FOUND IT')
                return (current_time - int(earliest)) * bus
        current_time += 1
Example #8
0
def part_1():
    boarding_passes = get_strings_by_lines('5.txt')
    max = 0
    for bp in boarding_passes:
        row = bin_search(127, bp[:7])
        col = bin_search(8, bp[7:])
        id = (row * 8) + col
        if id > max:
            max = id

    return max
def part_2():
    grid = [[char for char in line] for line in get_strings_by_lines('11.txt')]
    changed = True
    iterations = 0
    print_grid(grid)

    while changed:
        grid, changed = iterate(grid, False)
        iterations += 1
        log(f"iterated {iterations} times")

    print_grid(grid)
    return count_grid(grid)
Example #10
0
def part_2():
    instructions = get_strings_by_lines('14.txt')
    memory = {}
    mask = ''

    for inst in instructions:
        if inst[:4] == 'mask':
            (mask, ) = parse('mask = {}', inst)
            log(f"set mask to {mask}")

        else:
            address, value = parse('mem[{:d}] = {:d}', inst)
            memory = write_value_to_decoded_registers(memory, address, mask, value)

    log(memory)
    return sum(memory.values())
Example #11
0
def part_1():
    instructions = get_strings_by_lines('14.txt')
    memory = {}
    and_mask, or_mask = 0, 0

    for inst in instructions:
        if inst[:4] == 'mask':
            (new_mask, ) = parse('mask = {}', inst)
            and_mask, or_mask = set_bitmask(new_mask)

        else:
            address, value = parse('mem[{:d}] = {:d}', inst)
            memory = set_register(memory, address, value, and_mask, or_mask)

    log(memory)
    return sum(memory.values())
def part_2():
    rows = get_strings_by_lines('3.txt')
    x = 0

    tree_counts = [
        count_trees(rows, slope)
        for slope in [(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)]
    ]
    log(tree_counts)

    # return functools.reduce(lambda x, y: x*y, tree_counts)
    # Yeah, Robin, I know how to reduce stuff too

    product = 1
    for count in tree_counts:
        product *= count
    return product
def part_1():
    input_arr = get_strings_by_lines('2.txt')
    valid_count = 0

    # Loop through every pair in the array
    for input in input_arr:
        min, max, char, password = parse('{:d}-{:d} {:l}: {:w}', input)
        count = password.count(char)
        log(f"Testing {password} for {min} to {max} {char}'s")

        if min <= count <= max:
            log(f"\tYES")
            valid_count += 1
        else:
            log(f"\tNO")

    return valid_count
Example #14
0
def part_2():
    boarding_passes = get_strings_by_lines('5.txt')
    ids = []
    for bp in boarding_passes:
        row = bin_search(127, bp[:7])
        col = bin_search(8, bp[7:])
        ids += [(row * 8) + col]

    ids.sort()
    log(ids)

    for idx in range(1, len(ids)):
        # Did we skip a number?
        if ids[idx] - ids[idx - 1] != 1:
            return ids[idx] - 1  # Return the skipped number

    return None
def part_2():
    input_arr = get_strings_by_lines('2.txt')
    valid_count = 0

    # Loop through every pair in the array
    for input in input_arr:
        idx_a, idx_b, char, password = parse('{:d}-{:d} {:l}: {:w}', input)
        count = password.count(char)
        log(f"Testing {password} for {char} at indexes {idx_a} and {idx_b}")

        # convert from indexing at 0 to indexing at 1
        # And cast to bools to use the exclusive or operator
        if bool(password[idx_a - 1] == char) ^ bool(password[idx_b -
                                                             1] == char):
            log(f"\tYES")
            valid_count += 1
        else:
            log(f"\tNO")

    return valid_count
def part_1():
    rows = get_strings_by_lines('3.txt')
    x = 0
    tree_count = 0
    return count_trees(rows, (3, 1))
lib.config.DAY_NUMBER = args.day

# Import helper functions
from lib.helpers import log, get_strings_by_lines

if __name__ == "__main__":
    # import the library dynamically
    lib_name = f"problems.day_{args.day}"
    solver = importlib.import_module(lib_name)

    # Choose day 1 or day 2
    if args.test:
        if args.part != 2:
            log('\nTesting part 1...')
            computed = solver.part_1()
            all_answers = get_strings_by_lines('answers-part-1.txt')
            answer = all_answers[args.day - 1]
            if str(computed) == answer:
                print(f"Part 1: PASSED ({computed})")
            else:
                print(f"Part 1: FAILED")
                print(f"\tcomputed: {computed}")
                print(f"\tintended: {answer}")
        if args.part != 1:
            log('\nTesting part 2...')
            computed = solver.part_2()
            all_answers = get_strings_by_lines('answers-part-2.txt')
            answer = all_answers[args.day - 1]
            if str(computed) == answer:
                print(f"Part 2: PASSED ({computed})")
            else: