import itertools rocks = [ 0b00011110, 0b00001000_00011100_00001000, 0b00000100_00000100_00011100, 0b00010000_00010000_00010000_00010000, 0b00011000_00011000, ] jets = ">>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>" jets = open("input").read().strip() rocki = itertools.cycle(rocks) a = 0b11111111 wall = 0b10000000_10000000_10000000_10000000_10000000 stopped = 0 r = 0 def drop(a, r, jets): # start falling h = a.bit_length() + 8*3 if h % 8 != 0: h += 8 - h%8 numjets = 0 while True: j = next(jets) if j == '<': x = (r<<1) if x & wall == 0: if x & (a>>h) == 0: r = x elif j == '>': x = (r<<7) if x & wall == 0: x >>= 8 if x & (a>>h) == 0: r = x numjets += 1 # continue falling? if r & (a>>(h-8)) == 0: h -= 8 assert h > 0 else: # stop a |= (r<>h)&0xff while h >= 8 and x != 0x7f: h -= 8 x |= (a>>h)&0xff if x == 0x7f: return a>>h return 0 import math def height(a): return math.ceil(a.bit_length()/8) try: while True: r = next(rocki) a, n = drop(a,r,jeti) stopped += 1 i = (i+1) % len(rocks) j = (j+n) % len(jets) if (i,j,head(a)) in seen: break seen[(i,j,head(a))] = (a,stopped) #for i in reversed(range(0,a.bit_length(),8)): # print("{:08b}".format((a>>i)&0xff)) #print() b, old = seen[(i,j,head(a))] sdiff = stopped - old hdiff = height(a) - height(b) goal = 1000000000000 rounds, extra = divmod(goal - stopped, sdiff) h = rounds*hdiff for _ in range(extra): r = next(rocki) a, n = drop(a,r,jeti) print(rounds*hdiff + height(a)-1) finally: print(i, j, stopped) print(math.ceil((a>>8).bit_length()/8))