#!/usr/bin/env python from copy import deepcopy my_raw_input = """0: 3 1: 2 2: 4 4: 6 6: 5 8: 6 10: 6 12: 4 14: 8 16: 8 18: 9 20: 8 22: 6 24: 14 26: 12 28: 10 30: 12 32: 8 34: 10 36: 8 38: 8 40: 12 42: 12 44: 12 46: 12 48: 14 52: 14 54: 12 56: 12 58: 12 60: 12 62: 14 64: 14 66: 14 68: 14 70: 14 72: 14 80: 18 82: 14 84: 20 86: 14 90: 17 96: 20 98: 24 """ my_raw_input2 = [item.split(": ") for item in my_raw_input.splitlines()] my_input = {int(item[0]): {'layer_range': int(item[1]), 'scanner_position': 1, 'scanner_velocity_sign': -1} for item in my_raw_input2} layers_in_which_caught = [] for packet_position in range(0,my_input.keys()[-1]+1): if packet_position in my_input and my_input[packet_position]['scanner_position']==1: layers_in_which_caught.append(packet_position) for layer_depth,layer_dict in my_input.iteritems(): if layer_dict['scanner_position'] == 1 or layer_dict['scanner_position'] == layer_dict['layer_range']: my_input[layer_depth]['scanner_velocity_sign'] *= -1 layer_dict['scanner_position'] += my_input[layer_depth]['scanner_velocity_sign']*1 ##print((packet_position,my_input[packet_position] if packet_position in my_input else "no layer")) answer1 = sum(map(lambda x: x*my_input[x]['layer_range'], layers_in_which_caught)) print("Part 1: " + str(answer1)) ## To interactively see the sieve in action, ## uncomment the below line (and lines ## indicated in other places below). ###print(" ") ## Resetting input and scanner positions ## to initial positions for Part 2 my_raw_input2 = [item.split(": ") for item in my_raw_input.splitlines()] my_input = {int(item[0]): {'layer_range': int(item[1]), 'scanner_position': 1, 'scanner_velocity_sign': -1} for item in my_raw_input2} max_penetration = 0 ### Not used, just def am_i_caught(my_unchanged_input, delay): global max_penetration my_input = deepcopy(my_unchanged_input) range_of_iteration = [] if delay > 0: range_of_iteration = [-1] * (delay) range_of_iteration.extend(range(0,my_input.keys()[-1]+1)) else: range_of_iteration = range(0,my_input.keys()[-1]+1) for packet_position in range_of_iteration: if packet_position in my_input and my_input[packet_position]['scanner_position']==1: if packet_position > max_penetration: max_penetration = packet_position-1 print("Max penetration: " + str(max_penetration)) return True for layer_depth,layer_dict in my_input.iteritems(): if layer_dict['scanner_position'] == 1 or layer_dict['scanner_position'] == layer_dict['layer_range']: my_input[layer_depth]['scanner_velocity_sign'] *= -1 layer_dict['scanner_position'] += my_input[layer_depth]['scanner_velocity_sign']*1 return False ## keep increasing this till you get the right delay limit = 10000000 my_delay = 0 my_sieved_list = {i: True for i in range(0,limit)} flag = True ## To interactively see the sieve in action, ## uncomment the below line (and lines ## indicated in other places below). ###firewall_dict = {} while flag: ## To interactively see the sieve in action, ## uncomment the below line (and lines ## indicated in other places below). ###firewall_dict.clear() flag = False if len(my_sieved_list) == 0: print("Limit was too low. Please increase `limit` in the program. The answer below is *WRONG*.") break if my_delay > max(my_sieved_list.keys()): break elif my_delay not in my_sieved_list: flag = True for key in my_sieved_list: if key > my_delay: my_delay = key break continue for layer_depth,layer_dict in my_input.iteritems(): if (my_delay+layer_depth)%(2*(layer_dict['layer_range']-1))==0: ## To interactively see the sieve in action, ## uncomment the below line (and lines ## indicated in other places below). ###firewall_dict[layer_depth] = (my_delay, layer_depth, layer_dict['layer_range'], my_delay+layer_depth, 2*(layer_dict['layer_range']-1), (my_delay+layer_depth)%(2*(layer_dict['layer_range']-1))) factor = 2*(layer_dict['layer_range']-1) for i in range(0,limit//factor+1): key = my_delay+i*factor if key in my_sieved_list: del my_sieved_list[key] flag = True ## To interactively see the sieve in action, ## uncomment the below lines (and lines ## indicated in other places above). ###info_list = map(list, zip(*[(key,)+value for key,value in firewall_dict.iteritems()])) ###print("my_delay: " + str(my_delay)) ###print("len(my_sieved_list): " + str(len(my_sieved_list))) ###print("firewall_dict: ") ###print(" { ") ###print(" layer_depth: " + str(info_list[0])) ###print(" 1-> my_delay: " + str(info_list[1])) ###print(" 2-> layer_depth: " + str(info_list[2])) ###print(" 3-> layer_range: " + str(info_list[3])) ###print(" 4-> $1 + $2: " + str(info_list[4])) ###print(" 5-> 2 * ($3 - 1): " + str(info_list[5])) ###print(" 6-> $4 % $5: " + str(info_list[6])) ###print(" 7-> $6==0 i.e. WillBlock: " + str([item==0 for item in info_list[6]])) ###print(" } ") ###raw_input("\nPress return to continue...\n") if flag == True: my_delay+=1 answer2 = my_delay print("Part 2: " + str(answer2)) ## Optionally, uncomment the below line to ## simulate the packet transmission through ## the firewall to confirm answer ###print("Am I caught? " + str(am_i_caught(my_input, answer2)))