|
| 1 | +# -------------------------------- Input data ---------------------------------------- # |
| 2 | +importos,grid,graph,dot,assembly,re,itertools |
| 3 | +fromcollectionsimportCounter,deque,defaultdict |
| 4 | + |
| 5 | +fromcompassimport* |
| 6 | +fromdoubly_linked_listimport* |
| 7 | + |
| 8 | + |
| 9 | +# This functions come from https://github.com/mcpower/adventofcode - Thanks! |
| 10 | +deflmap(func,*iterables): |
| 11 | +returnlist(map(func,*iterables)) |
| 12 | + |
| 13 | + |
| 14 | +defints(s:str): |
| 15 | +returnlmap(int,re.findall(r"-?\d+",s))# thanks mserrano! |
| 16 | + |
| 17 | + |
| 18 | +defpositive_ints(s:str): |
| 19 | +returnlmap(int,re.findall(r"\d+",s))# thanks mserrano! |
| 20 | + |
| 21 | + |
| 22 | +deffloats(s:str): |
| 23 | +returnlmap(float,re.findall(r"-?\d+(?:\.\d+)?",s)) |
| 24 | + |
| 25 | + |
| 26 | +defpositive_floats(s:str): |
| 27 | +returnlmap(float,re.findall(r"\d+(?:\.\d+)?",s)) |
| 28 | + |
| 29 | + |
| 30 | +defwords(s:str): |
| 31 | +returnre.findall(r"[a-zA-Z]+",s) |
| 32 | + |
| 33 | + |
| 34 | +test_data= {} |
| 35 | + |
| 36 | +test=1 |
| 37 | +test_data[test]= { |
| 38 | +"input":"""389125467""", |
| 39 | +"expected": ["92658374 after 10 moves, 67384529 after 100 moves","149245887792"], |
| 40 | +} |
| 41 | + |
| 42 | +test="real" |
| 43 | +input_file=os.path.join( |
| 44 | +os.path.dirname(__file__), |
| 45 | +"Inputs", |
| 46 | +os.path.basename(__file__).replace(".py",".txt"), |
| 47 | +) |
| 48 | +test_data[test]= { |
| 49 | +"input":open(input_file,"r+").read(), |
| 50 | +"expected": ["45286397","836763710"], |
| 51 | +} |
| 52 | + |
| 53 | + |
| 54 | +# -------------------------------- Control program execution ------------------------- # |
| 55 | + |
| 56 | +case_to_test="real" |
| 57 | +part_to_test=2 |
| 58 | + |
| 59 | +# -------------------------------- Initialize some variables ------------------------- # |
| 60 | + |
| 61 | +puzzle_input=test_data[case_to_test]["input"] |
| 62 | +puzzle_expected_result=test_data[case_to_test]["expected"][part_to_test-1] |
| 63 | +puzzle_actual_result="Unknown" |
| 64 | + |
| 65 | + |
| 66 | +# -------------------------------- Actual code execution ----------------------------- # |
| 67 | + |
| 68 | + |
| 69 | +ifpart_to_test==1: |
| 70 | +moves=100 |
| 71 | +forstringinpuzzle_input.split("\n"): |
| 72 | +cups= [int(x)forxinstring] |
| 73 | + |
| 74 | +foriinrange(moves): |
| 75 | +cur_cup=cups[0] |
| 76 | +pickup=cups[1:4] |
| 77 | +delcups[0:4] |
| 78 | + |
| 79 | +try: |
| 80 | +dest_cup=max([xforxincupsifx<cur_cup]) |
| 81 | +except: |
| 82 | +dest_cup=max([xforxincups]) |
| 83 | +cups[cups.index(dest_cup)+1 :cups.index(dest_cup)+1]=pickup |
| 84 | +cups.append(cur_cup) |
| 85 | + |
| 86 | +print(cups) |
| 87 | + |
| 88 | +pos1=cups.index(1) |
| 89 | +puzzle_actual_result="".join(map(str,cups[pos1+1 :]+cups[:pos1])) |
| 90 | + |
| 91 | +else: |
| 92 | +moves=10**7 |
| 93 | +nb_cups=10**6 |
| 94 | +cups=DoublyLinkedList(True) |
| 95 | + |
| 96 | +forstringinpuzzle_input.split("\n"): |
| 97 | +forcupinstring: |
| 98 | +cups.append(cup) |
| 99 | + |
| 100 | +new_cups= { |
| 101 | +str(i):DoublyLinkedListElement(str(i),None,None) |
| 102 | +foriinrange(10,nb_cups+1) |
| 103 | + } |
| 104 | +forkey,cupinnew_cups.items(): |
| 105 | +ifkey!="10": |
| 106 | +cup.prev_element=new_cups[str(int(key)-1)] |
| 107 | +ifkey!=str(nb_cups): |
| 108 | +cup.next_element=new_cups[str(int(key)+1)] |
| 109 | +new_cups["10"].prev_element=cups.elements[string[-1]] |
| 110 | +new_cups[str(nb_cups)].next_element=cups.elements[string[0]] |
| 111 | + |
| 112 | +cups.elements.update(new_cups) |
| 113 | +cups.elements[string[-1]].next_element=new_cups["10"] |
| 114 | +cups.elements[string[0]].prev_element=new_cups[str(nb_cups)] |
| 115 | + |
| 116 | +delnew_cups |
| 117 | + |
| 118 | +print([(i,cups.elements[str(i)])foriinmap(str,range(1,15))]) |
| 119 | + |
| 120 | +cur_cup=cups.start_element |
| 121 | +# #print (cups.elements) |
| 122 | +foriinrange(1,moves+1): |
| 123 | +print("----- Move",i) |
| 124 | +# #print (','.join([x.item for x in cups.traverse(cups.start_element)]), cur_cup.item) |
| 125 | + |
| 126 | +cups_moved= [ |
| 127 | +cur_cup.next_element, |
| 128 | +cur_cup.next_element.next_element, |
| 129 | +cur_cup.next_element.next_element.next_element, |
| 130 | + ] |
| 131 | +cups_moved_int=list(map(lambdai:int(i.item),cups_moved)) |
| 132 | +# #print ('Moved cups', [x.item for x in cups_moved]) |
| 133 | + |
| 134 | +cups.delete_by_value(cur_cup.next_element) |
| 135 | +cups.delete_by_value(cur_cup.next_element) |
| 136 | +cups.delete_by_value(cur_cup.next_element) |
| 137 | + |
| 138 | +dest_cup_nr=int(cur_cup.item)-1 |
| 139 | +whiledest_cup_nrincups_moved_intordest_cup_nr<=0: |
| 140 | +dest_cup_nr-=1 |
| 141 | +ifdest_cup_nr<=0: |
| 142 | +dest_cup_nr=nb_cups |
| 143 | +dest_cup=cups.find(str(dest_cup_nr)) |
| 144 | + |
| 145 | +# #print ("Destination", dest_cup_nr) |
| 146 | + |
| 147 | +cups.insert(dest_cup,cups_moved) |
| 148 | +cur_cup=cur_cup.next_element |
| 149 | + |
| 150 | +pos1=cups.find("1") |
| 151 | +puzzle_actual_result=int(pos1.next_element.item)*int( |
| 152 | +pos1.next_element.next_element.item |
| 153 | + ) |
| 154 | +# #puzzle_actual_result = cups[(pos1+1)%len(cups)] * cups[(pos1+2)%len(cups)] |
| 155 | + |
| 156 | +# -------------------------------- Outputs / results --------------------------------- # |
| 157 | + |
| 158 | +print("Case :",case_to_test,"- Part",part_to_test) |
| 159 | +print("Expected result : "+str(puzzle_expected_result)) |
| 160 | +print("Actual result : "+str(puzzle_actual_result)) |
| 161 | +# Date created: 2020-12-23 06:25:17.546310 |