#advent of code 2018 #day 13 #part 1 and part 2 #I got it working the first time, but I was getting a wrong answer for actual input #turns out I made a mistake in calculations for the crossroads for turn-left and turn-right #i hastily scrambled a set of 2 equations for X and Y coordinates #and it costed me time wasted on debugging #for each round I was drawing the current layout of the map with a single cart #I noticed that at crossroads it was doing a turn-left, straight, turn-left #(instead of right for 3rd crossroads) #I followed my equations by *slowly* calculating them on paper #and found out that I had wrong signs for Y coordinate #fun puzzle nonetheless #comment for part2 #i had a bit of an issue with getting it working properly #at this moment, the part2 is calculated correctly, but part1 was off #I cleaned up the code a bit and managed to solve this, so both parts are in the same file f = open("input.txt",'r'); Testing = False; #Testing = True; if Testing: f.close(); f = open("testinput.txt",'r'); class trackpoint: def __init__(self, sign, x, y): self.sign = sign; self.positionX = x; self.positionY = y; def __str__(self): return self.sign; class hline(trackpoint): def __init__(self, sign, x, y): trackpoint.__init__(self, sign, x, y); def GiveSteps(self, cart_x, cart_y, cartid): #left or right x_next = self.positionX + (self.positionX - cart_x); y_next = self.positionY + (self.positionY - cart_y); return [x_next, y_next]; class vline(trackpoint): def __init__(self, sign, x, y): trackpoint.__init__(self, sign, x, y); def GiveSteps(self, cart_x, cart_y, cartid): #up or down x_next = self.positionX + (self.positionX - cart_x); y_next = self.positionY + (self.positionY - cart_y); return [x_next, y_next]; class turnleft(trackpoint): def __init__(self, sign, x, y): trackpoint.__init__(self, sign, x, y); def GiveSteps(self, cart_x, cart_y, cartid): x_next = self.positionX - (cart_y - self.positionY); y_next = self.positionY - (cart_x - self.positionX); return [x_next, y_next]; class turnright(trackpoint): def __init__(self, sign, x, y): trackpoint.__init__(self, sign, x, y); def GiveSteps(self, cart_x, cart_y, cartid): x_next = self.positionX + (cart_y - self.positionY); y_next = self.positionY + (cart_x - self.positionX); return [x_next, y_next]; class crossroads(trackpoint): def __init__(self, sign, x, y): trackpoint.__init__(self, sign, x, y); self.CartRegistry = {}; def GiveSteps(self, cart_x, cart_y, cartid): #number of crossroads is updated before this function is called, thats why it starts from 1 if (cartid%3 == 1): #turn left x_next = self.positionX - (cart_y - self.positionY); y_next = self.positionY + (cart_x - self.positionX); elif (cartid%3 == 2): #go straight x_next = self.positionX + (self.positionX - cart_x); y_next = self.positionY + (self.positionY - cart_y); elif (cartid%3 == 0): #turn right x_next = self.positionX + (cart_y - self.positionY); y_next = self.positionY - (cart_x - self.positionX); return [x_next, y_next]; class minecart: def __init__(self, sign, x, y, cart_id): self.posX = x; self.posY = y; self.XroadsEncountered = 0; self.nextstepX = x; self.nextstepY = y; self.Cart_ID = cart_id; self.notHit = True; if (sign == '>'): self.prevX = x-1; self.prevY = y; if (sign == '<'): self.prevX = x+1; self.prevY = y; if (sign == 'v'): self.prevX = x; self.prevY = y-1; if (sign == '^'): self.prevX = x; self.prevY = y+1; def cartmove(self, nextX, nextY): self.nextstepX = nextX; self.nextstepY = nextY; self.prevX = self.posX; self.prevY = self.posY; self.posX = self.nextstepX; self.posY = self.nextstepY; def ReadCoords(self): return [self.posX, self.posY]; def CheckMatch(self, OtherCoords): return (self.posX == OtherCoords[0] and self.posY == OtherCoords[1]); def IsXroads(self, currentsign): if (currentsign == "+"): self.XroadsEncountered += 1; trackmap = []; for l in f: subline = []; l.replace("\n", ""); for c in l: subline.append(c); trackmap.append(subline.copy()); cartlist = []; cartid_counter = 10; TMSize_C = len(trackmap); TMSize_R = len(trackmap[0]) -1; #RETREIVING MINECARTS AND REPLACING SIGNS ON THE MAP for c in range(TMSize_C): for r in range(TMSize_R): if (trackmap[c][r] == '^' or trackmap[c][r] == 'v' or trackmap[c][r] == '>' or trackmap[c][r] == '<'): cartlist.append( minecart(trackmap[c][r], r, c, cartid_counter) ); cartid_counter += 1; if (trackmap[c][r] == '^' or trackmap[c][r] == 'v'): trackmap[c][r] = '|'; if (trackmap[c][r] == '>' or trackmap[c][r] == '<'): trackmap[c][r] = '-'; cartlist = sorted(cartlist, key=lambda x: (x.posY, x.posX)); newmap = []; for c in range(TMSize_C): templine = []; for r in range(TMSize_R): if (trackmap[c][r] == ' '): templine.append( trackpoint(trackmap[c][r], r, c) ); elif (trackmap[c][r] == '-'): templine.append( hline(trackmap[c][r], r, c) ); elif (trackmap[c][r] == '|'): templine.append( vline(trackmap[c][r], r, c) ); elif (trackmap[c][r] == '/'): templine.append( turnright(trackmap[c][r], r, c) ); elif (trackmap[c][r] == '\\'): templine.append( turnleft(trackmap[c][r], r, c) ); elif (trackmap[c][r] == '+'): templine.append( crossroads(trackmap[c][r], r, c) ); newmap.append( templine.copy() ); roundcounter = 0; part1 = None; p1round = 0; while (len(cartlist) > 1): roundcounter += 1; cartlist = sorted(cartlist, key=lambda x: (x.posY, x.posX)); for mc in cartlist: NextSteps = []; mc.IsXroads(newmap[mc.posY][mc.posX].sign); NextSteps = newmap[mc.posY][mc.posX].GiveSteps(mc.prevX, mc.prevY, mc.XroadsEncountered); mc.cartmove(NextSteps[0],NextSteps[1]); MatchCounter = 0; for mc2 in cartlist: if mc.Cart_ID != mc2.Cart_ID: mc.notHit = not mc.CheckMatch( mc2.ReadCoords() ); mc2.notHit = not mc2.CheckMatch( mc.ReadCoords() ); if part1 == None and mc.notHit == False: part1 = mc.ReadCoords(); p1round = int(roundcounter); #print("part 1 = ",part1, "\t after", roundcounter, "rounds"); cartlist = [c for c in cartlist if c.notHit]; part2 = cartlist[0].ReadCoords(); print("part 1 = ",part1, "\t after", p1round, "rounds"); print("part 2 = ",part2, "\t after", roundcounter, "rounds");