Sean McLemon | Advent of Code

Home | Czech | Blog | GitHub | Advent Of Code | Notes


2017-12-22 - Sporifica Virus

(original .ipynb)
puzzle_input_str = open("puzzle_input/day22.txt").read()
test_input_str = """..#
#..
..."""

clean = "."
infected = "#"


def parse_input(input_str):
    return [list(line) for line in input_str.split("\n")]


def left(dr, dc):
    return (-dc, dr)


def right(dr, dc):
    return (dc, -dr)


def maybe_grow(grid, r, c):
    if r < 0:
        grid.insert(0, [clean] * len(grid[0]))
        r += 1

    if r >= len(grid):
        grid.append([clean] * len(grid[0]))

    if c < 0:
        for i in range(len(grid)):
            grid[i].insert(0, clean)
        c += 1    

    if c >= len(grid[0]):
        for i in range(len(grid)):
            grid[i].append(clean)

    return r, c


def solve(input_str, bursts, next_state, next_direction):
    grid = parse_input(input_str)
    centre = len(grid) // 2
    r, c = centre, centre
    dr, dc = (-1, 0)
    infections_caused = 0
    
    while bursts > 0:
        node_state = grid[r][c]
        dr, dc = next_direction[node_state](dr, dc)
        next_node_state = next_state[node_state]
        if next_node_state == infected:
            infections_caused += 1
        
        grid[r][c] = next_node_state
        
        r, c = r+dr, c+dc
        r, c = maybe_grow(grid, r, c)
        
        bursts -= 1

    return infections_caused


def part_one(input_str, bursts):
    next_state = {
        clean: infected,
        infected: clean
    }
    
    next_direction = {
        clean: left,
        infected: right
    }
    
    return solve(input_str, bursts, next_state, next_direction)

assert    5 == part_one(test_input_str, 7)
assert   41 == part_one(test_input_str, 70)
assert 5587 == part_one(test_input_str, 10000)

print("part one:", part_one(puzzle_input_str, 10000))
part one: 5280
weakened = "W"
flagged = "F"

def reverse(dr, dc):
    return (-dr, -dc)


def same_direction(dr, dc):
    return (dr, dc)


def part_two(input_str, bursts):
    next_state = {
        clean: weakened,
        weakened: infected,
        infected: flagged,
        flagged: clean
    }
    
    next_direction = {
        clean: left,
        weakened: same_direction,
        infected: right,
        flagged: reverse
    }
    
    return solve(input_str, bursts, next_state, next_direction)


assert      26 == part_two(test_input_str, 100)
assert 2511944 == part_two(test_input_str, 10_000_000)

print("part two:", part_two(puzzle_input_str, 10_000_000))
part two: 2512261