#advent of code 2018 #day 18 #part 1 and part 2 #at first I thought I can find the loop by simply registering when a value "part2" is repeated once #(kind of like in an earlier puzzle for that year) #then I had a correct idea how to find the pattern, #but didn't really know how to implement it efficently #pattern recognition is an implementation of solution provided by Michael Fogleman #adjusted to my current code #another issue I had was that I resumed the calculations for part 2 from the state after 10 minutes (part1) #I needed to save the initial state and then start over #could probably reduce the code to single loop instead of two separate loops for each part f = open("input.txt",'r'); Testing = False; #Testing = True; if Testing: f.close(); f = open("testinput.txt",'r'); size = 50; if Testing: size = 10; #part 1 CurrentState = {}; for r,l in enumerate(f): #print(len(l)); for c,a in enumerate(l): CurrentState.update({(r,c):a}); InitialState = CurrentState.copy(); f.close(); for x in range(size): for y in range(size): print(CurrentState[(x,y)],end=""); print(); #check if each adjacent position is still within grid range def GetAdjacent(Cords): Adjacent = []; if (Cords[0] -1 >= 0 and Cords[1]-1 >=0): Adjacent.append( (Cords[0] -1,Cords[1]-1) ); if (Cords[0] -1 >= 0): Adjacent.append( (Cords[0] -1,Cords[1]) ); if (Cords[0] -1 >= 0 and Cords[1]+1 < size): Adjacent.append( (Cords[0] -1,Cords[1]+1) ); if (Cords[1]+1 < size): Adjacent.append( (Cords[0],Cords[1]+1) ); if (Cords[1]-1 >= 0): Adjacent.append( (Cords[0],Cords[1]-1) ); if (Cords[0] +1 < size and Cords[1]-1 >=0): Adjacent.append( (Cords[0] +1,Cords[1]-1) ); if (Cords[0] +1 < size): Adjacent.append( (Cords[0] +1,Cords[1]) ); if (Cords[0] +1 < size and Cords[1]+1 < size): Adjacent.append( (Cords[0] +1,Cords[1]+1) ); return Adjacent; def GetAcres(area, adj): acres = []; for c in adj: acres.append(area[c]); return acres; def ChangeState(area, Cords): s = area[Cords]; adj = GetAdjacent(Cords); Acres = GetAcres(area, adj); if (s == "." and Acres.count("|")>=3): s = "|"; elif (s == "|" and Acres.count("#")>=3): s = "#"; elif (s == "#" and Acres.count("#")>=1 and Acres.count("|")>=1): s = "#"; elif (s == "#"): s = "."; return s; SimTime = 10; #minutes InitialState = CurrentState.copy(); for t in range(SimTime): NextState = {}; for x in range(size): for y in range(size): NextState.update({(x,y):ChangeState(CurrentState,(x,y))}); CurrentState = NextState.copy(); ''' print("MINUTE ",t); for x in range(size): for y in range(size): print(CurrentState[(x,y)],end=""); print(); print(); ''' summary = list(CurrentState.values()); woods = summary.count("|"); lumbs = summary.count("#"); part1 = woods*lumbs; print("part 1 = ", part1); #part 2 SimTime2 = 1000000000; #minutes for part2 values = {}; prev = 0; CurrentState = InitialState.copy(); for t in range(1,SimTime2): NextState = {}; for x in range(size): for y in range(size): NextState.update({(x,y):ChangeState(CurrentState,(x,y))}); CurrentState = NextState.copy(); summary = list(CurrentState.values()); woods = summary.count("|"); lumbs = summary.count("#"); part2 = woods*lumbs; loop = t - values.get(part2,0); if (loop == prev): if SimTime2%loop == t%loop: break; values[part2]=t; prev = loop; print("part 2 = ", part2);