#/usr/bin/env python # Remove all instances of #"1"# and #"2"# # (without quotes) from the code to view # Part 1 interactively (without quotes) # Remove all instances of #"1"# and #"3"# # (without quotes) from the code to view # Part 2 interactively # Remove all instances of #"4"# (without quotes) # from the code to test Part 1 and 2 with # with map_centre_grid = ["..#", "#..", "..."] # "." means clean # "#" means infected map_centre_grid = [] with open("/home/login/bin/advent17/input22.txt") as f: for line in f: map_centre_grid.append(line[:-1]) #4#map_centre_grid = ["..#", "#..", "..."] map_width = len(map_centre_grid[0]) map_height = len(map_centre_grid) origin = ((map_width-1)//2, (map_height-1)//2) # 0 means clean # 1 means infected map_dict = {} for j in range(map_height): for i in range(map_width): map_dict[(i-origin[0],origin[1]-j)] = 1 if map_centre_grid[j][i] == "#" else 0 infected_nodes = {key:None for key,value in map_dict.items() if value==1} infected_nodes = {} def is_infected(x,y): global map_dict global map_width, map_height if (x,y) not in map_dict: map_dict[(x,y)] = 0 return_value = True if map_dict[(x,y)]==1 else False return return_value def clean(x,y): global map_dict if (x,y) not in map_dict: map_dict[(x,y)] = 0 else: map_dict[(x,y)] = 0 def infect(x,y): global map_dict if (x,y) not in map_dict: map_dict[(x,y)] = 0 map_dict[(x,y)] = 1 #1#def bound_map(x,y): #1# global map_width, map_height #1# if abs(x) > (map_width-1)//2: #1# map_width = (2*abs(x)+1) #1# if abs(y) > (map_height-1)//2: #1# map_height = (2*abs(y)+1) # RULES # # There is one virus carrier that moves across the grid, infecting # or cleaning machines it encounters on its path. It carries out # these movements in bursts. The virus carrier starts in the middle # of the grid in the "up" direction. # # For every burst of activity, the virus carrier does the following # in order: # 1. If the current node is infected, its direction becomes "right" # else "left". # # 2. If the current node is clean, is infected, else cleaned. # # 3. The virus carrier moves forward one node in the direction it # is facing. # RULES (PART 2): # # Node progression: # # Clean -> Weakened # Weakened -> Infected # Infected -> Flagged # Flagged -> Clean # # Burst logic: # # 1. If current node is: # - clean: turn left # - weakened: no turn # - infected: turn right # - flagged: reverse (left-left or right-right) # # 2. If current node is: # - clean: weaken # - weakened: infect # - infected: flag # - flagged: clean # Legend: # clean: 0 # infected: 1 # weakened: 2 # flagged : 3 def weaken(x,y): global map_dict if (x,y) not in map_dict: map_dict[(x,y)] = 0 map_dict[(x,y)] = 2 def flag(x,y): global map_dict if (x,y) not in map_dict: map_dict[(x,y)] = 0 map_dict[(x,y)] = 3 def is_weakened(x,y): global map_dict global map_width, map_height if (x,y) not in map_dict: map_dict[(x,y)] = 0 return_value = True if map_dict[(x,y)]==2 else False return return_value def is_flagged(x,y): global map_dict global map_width, map_height if (x,y) not in map_dict: map_dict[(x,y)] = 0 return_value = True if map_dict[(x,y)]==3 else False return return_value #1#def print_map(x=0,y=0): #1# global map_dict, map_width, map_height #1# bound_map(x,y) # to update map_width, map_height #1# max_j = (map_height-1)//2 #1# min_j = -max_j #1# max_i = (map_width-1)//2 #1# min_i = -max_i #1# #1# begin_char = "" #1# mid_char = "." #1# end_char = " " #1# print(" ", end="") #1# for j in range(max_j,min_j-1,-1): #1# for i in range(min_i,max_i+1): #1# if (i,j)==(x,y): #1# begin_char = "\b[" #1# end_char = "]" #1# else: #1# begin_char = "" #1# end_char = " " #1# if is_infected(i,j): #1# mid_char = "#" #1# elif is_weakened(i,j): #1# mid_char = "W" #1# elif is_flagged(i,j): #1# mid_char = "F" #1# else: #is clean #1# mid_char = "." #1# #1# print(begin_char, end="") #1# print(mid_char, end=end_char) #1# print("\n ", end="") #2#print_map() #vc = virus carrier vc_position = [0,0] vc_direction = [0,1] vc_caused_infection_counter = 0 # direction=0 means "turn left" # direction=`anything else` means "turn right" def turn(direction): global vc_direction factor_complex_number = 1j if direction == 0 else (-1j if direction == 1 else -1) vc_direction_complex_number = complex(vc_direction[0], vc_direction[1]) new_vc_direction_complex_number = vc_direction_complex_number * factor_complex_number vc_direction[0] = int(new_vc_direction_complex_number.real) vc_direction[1] = int(new_vc_direction_complex_number.imag) def move(): global vc_direction, vc_position vc_position[0] += vc_direction[0] vc_position[1] += vc_direction[1] def burst(): global vc_position, vc_caused_infection_counter, infected_nodes left = 0 right = 1 if is_infected(*vc_position): turn(right) clean(*vc_position) else: #is clean turn(left) infect(*vc_position) if tuple(vc_position) not in infected_nodes: vc_caused_infection_counter += 1 move() num_of_bursts = 10000 for i in [None]*num_of_bursts: burst() #2# print(" ") #2# print_map(*vc_position) #2# print("") #2# input() print("Part 1: " + str(vc_caused_infection_counter)) def evolved_burst(): global vc_position, vc_caused_infection_counter, infected_nodes left = 0 right = 1 around = 2 if is_infected(*vc_position): turn(right) flag(*vc_position) elif is_weakened(*vc_position): #don't turn infect(*vc_position) if tuple(vc_position) not in infected_nodes: vc_caused_infection_counter += 1 elif is_flagged(*vc_position): turn(around) clean(*vc_position) else: #is clean turn(left) weaken(*vc_position) move() # Resetting map, counter, position and direction map_width = len(map_centre_grid[0]) map_height = len(map_centre_grid) origin = ((map_width-1)//2, (map_height-1)//2) map_dict = {} for j in range(map_height): for i in range(map_width): map_dict[(i-origin[0],origin[1]-j)] = 1 if map_centre_grid[j][i] == "#" else 0 vc_position = [0,0] vc_direction = [0,1] vc_caused_infection_counter = 0 #3#print_map() num_of_bursts = 10000000 for i in [None]*num_of_bursts: evolved_burst() #3# print(" ") #3# print_map(*vc_position) #3# print("") #3# input() print("Part 2: " + str(vc_caused_infection_counter))