You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
253 lines
7.6 KiB
253 lines
7.6 KiB
#rock grid |
|
class Chamber(): |
|
def __init__(self): |
|
self.grid = [['#', '#', '#', '#', '#', '#', '#']] |
|
|
|
def addEmpty(self, x): |
|
for i in range(x): |
|
self.grid.append(['.', '.', '.', '.', '.', '.', '.']) |
|
|
|
def removeEmpty(self): |
|
self.grid = [i for i in self.grid if i != ['.']*7] |
|
|
|
def topEdge(self): |
|
return len(self.grid) |
|
|
|
def addRock(self, rock): |
|
for add in rock: |
|
y, x = add |
|
self.grid[y][x] = '#' |
|
|
|
def testPrint(self): |
|
for gridLine in reversed(self.grid): |
|
line = '' |
|
for point in gridLine: |
|
line += point |
|
print(line) |
|
|
|
|
|
#Defining Rock Shapes |
|
def line(): |
|
relativeX = 0 |
|
relativeY = 0 |
|
settled = False |
|
chamber.addEmpty(3) |
|
NY = chamber.topEdge() |
|
NX = 2 |
|
chamber.addEmpty(1) |
|
while not settled: |
|
if jetstream[jetPosition] == '<': |
|
if NX != 0 and chamber.grid[NY][NX - 1] == '.': |
|
NX -= 1 |
|
relativeX -= 1 |
|
else: |
|
if NX != 3 and chamber.grid[NY][NX + 4] == '.': |
|
NX += 1 |
|
relativeX += 1 |
|
jet() |
|
if chamber.grid[NY - 1][NX:NX+4] == ['.', '.', '.', '.',]: |
|
NY -= 1 |
|
relativeY -= 1 |
|
else: |
|
settled = True |
|
rock = [(NY, NX), (NY, NX + 1), (NY, NX + 2), (NY, NX + 3)] |
|
chamber.addRock(rock) |
|
chamber.removeEmpty() |
|
rockSequence.append(((relativeY, relativeX), 1, chamber.topEdge() - 1)) |
|
|
|
def cross(): |
|
relativeX = 0 |
|
relativeY = 0 |
|
settled = False |
|
chamber.addEmpty(3) |
|
NY = chamber.topEdge() |
|
NX = 3 |
|
chamber.addEmpty(3) |
|
while not settled: |
|
if jetstream[jetPosition] == '<': |
|
if NX != 1 and all(x == '.' for x in (chamber.grid[NY][NX - 1], chamber.grid[NY + 1][NX - 2], chamber.grid[NY + 2][NX - 1])): |
|
NX -= 1 |
|
relativeX -= 1 |
|
else: |
|
if NX != 5 and all(x == '.' for x in (chamber.grid[NY][NX + 1], chamber.grid[NY + 1][NX + 2], chamber.grid[NY + 2][NX + 1])): |
|
NX += 1 |
|
relativeX += 1 |
|
jet() |
|
if all(x == '.' for x in (chamber.grid[NY - 1][NX], chamber.grid[NY][NX - 1], chamber.grid[NY][NX + 1])): |
|
NY -= 1 |
|
relativeY -= 1 |
|
else: |
|
settled = True |
|
rock = [(NY, NX), (NY + 1, NX - 1), (NY + 1, NX), (NY + 1, NX + 1), (NY + 2, NX)] |
|
chamber.addRock(rock) |
|
chamber.removeEmpty() |
|
rockSequence.append(((relativeY, relativeX), 2, chamber.topEdge() - 1)) |
|
|
|
def l(): |
|
relativeX = 0 |
|
relativeY = 0 |
|
settled = False |
|
chamber.addEmpty(3) |
|
NY = chamber.topEdge() |
|
NX = 2 |
|
chamber.addEmpty(3) |
|
while not settled: |
|
if jetstream[jetPosition] == '<': |
|
if NX != 0 and all(x == '.' for x in (chamber.grid[NY][NX - 1], chamber.grid[NY + 1][NX + 1], chamber.grid[NY + 2][NX + 1])): |
|
NX -= 1 |
|
relativeX -= 1 |
|
else: |
|
if NX != 4 and all(x == '.' for x in (chamber.grid[NY][NX + 3], chamber.grid[NY + 1][NX + 3], chamber.grid[NY + 2][NX + 3])): |
|
NX += 1 |
|
relativeX += 1 |
|
jet() |
|
if chamber.grid[NY - 1][NX:NX+3] == ['.', '.', '.']: |
|
NY -= 1 |
|
relativeY -= 1 |
|
else: |
|
settled = True |
|
rock = [(NY, NX), (NY, NX + 1), (NY, NX + 2), (NY + 1, NX + 2), (NY + 2, NX + 2)] |
|
chamber.addRock(rock) |
|
chamber.removeEmpty() |
|
rockSequence.append(((relativeY, relativeX), 3, chamber.topEdge() - 1)) |
|
|
|
def staff(): |
|
relativeX = 0 |
|
relativeY = 0 |
|
settled = False |
|
chamber.addEmpty(3) |
|
NY = chamber.topEdge() |
|
NX = 2 |
|
chamber.addEmpty(4) |
|
while not settled: |
|
if jetstream[jetPosition] == '<': |
|
if NX != 0 and all(x == '.' for x in (chamber.grid[NY][NX - 1], chamber.grid[NY + 1][NX - 1], chamber.grid[NY + 2][NX - 1], chamber.grid[NY + 3][NX - 1])): |
|
NX -= 1 |
|
relativeX -= 1 |
|
else: |
|
if NX != 6 and all(x == '.' for x in (chamber.grid[NY][NX + 1], chamber.grid[NY + 1][NX + 1], chamber.grid[NY + 2][NX + 1], chamber.grid[NY + 3][NX + 1])): |
|
NX += 1 |
|
relativeX += 1 |
|
jet() |
|
if chamber.grid[NY -1][NX] == '.': |
|
NY -= 1 |
|
relativeY -= 1 |
|
else: |
|
settled = True |
|
rock = [(NY, NX), (NY + 1, NX), (NY + 2, NX), (NY + 3, NX)] |
|
chamber.addRock(rock) |
|
chamber.removeEmpty() |
|
rockSequence.append(((relativeY, relativeX), 4, chamber.topEdge() - 1)) |
|
|
|
def square(): |
|
relativeX = 0 |
|
relativeY = 0 |
|
settled = False |
|
chamber.addEmpty(3) |
|
NY = chamber.topEdge() |
|
NX = 2 |
|
chamber.addEmpty(2) |
|
while not settled: |
|
if jetstream[jetPosition] == '<': |
|
if NX != 0 and (chamber.grid[NY][NX -1] == '.' and chamber.grid[NY + 1][NX -1] == '.'): |
|
NX -= 1 |
|
relativeX -= 1 |
|
else: |
|
if NX != 5 and (chamber.grid[NY][NX + 2] == '.' and chamber.grid[NY + 1][NX + 2] == '.'): |
|
NX += 1 |
|
relativeX += 1 |
|
jet() |
|
if chamber.grid[NY - 1][NX] == '.' and chamber.grid[NY - 1][NX + 1] == '.': |
|
NY -= 1 |
|
relativeY -= 1 |
|
else: |
|
settled = True |
|
rock = [(NY, NX), (NY + 1, NX), (NY + 1, NX + 1), (NY, NX + 1)] |
|
chamber.addRock(rock) |
|
chamber.removeEmpty() |
|
rockSequence.append(((relativeY, relativeX), 5, chamber.topEdge() - 1)) |
|
|
|
|
|
#miscelanious |
|
def jet(): |
|
global jetPosition |
|
jetPosition += 1 |
|
if jetPosition == jetWrap: |
|
jetPosition = 0 |
|
|
|
|
|
def _counter(): |
|
global counter |
|
counter += 1 |
|
if counter == end: |
|
return True |
|
return False |
|
|
|
|
|
def cycleFinder(): |
|
global cycleFound |
|
global counter |
|
global skippedValue |
|
if cycleFound: |
|
return |
|
position1, _, _ = rockSequence[-1] |
|
position2, _, _ = rockSequence[-2] |
|
position3, _, _ = rockSequence[-3] |
|
position4, _, _ = rockSequence[-4] |
|
position5, _, _ = rockSequence[-5] |
|
position6, _, _ = rockSequence[-6] |
|
position7, _, _ = rockSequence[-7] |
|
cycle[(position1, position2, position3, position4, position5, position6, position7)] = cycle.get((position1, position2, position3, position4, position5, position6, position7), 0) + len(rockSequence) |
|
if cycle[(position1, position2, position3, position4, position5, position6, position7)] > len(rockSequence): |
|
endOfCycle = rockSequence[-5] |
|
index = cycle[(position1, position2, position3, position4, position5, position6, position7)] - len(rockSequence) |
|
startOfCycle = rockSequence[index - 5] |
|
cycleFound = True |
|
cycleLength = len(rockSequence) - index |
|
cycleValue = endOfCycle[2] - startOfCycle[2] |
|
print('found cycle') |
|
n, rest = divmod(end - len(rockSequence), cycleLength) |
|
counter = len(rockSequence) + cycleLength * n |
|
skippedValue = cycleValue * n |
|
|
|
|
|
#Building Input, defioning variables |
|
with open('input17.txt','r') as f: |
|
inp = f.read().splitlines(keepends=False) |
|
|
|
jetstream = list(inp[0]) |
|
jetWrap = len(jetstream) |
|
chamber = Chamber() |
|
jetPosition = 0 |
|
counter = 0 |
|
end = 1000000000000 |
|
rockSequence = [] |
|
cycle = {} |
|
cycleFound = False |
|
|
|
|
|
# Main function |
|
while True: |
|
line() |
|
if _counter(): |
|
break |
|
cross() |
|
if _counter(): |
|
break |
|
l() |
|
if _counter(): |
|
break |
|
staff() |
|
if _counter(): |
|
break |
|
square() |
|
if _counter(): |
|
break |
|
if counter == 5: |
|
pass |
|
else: |
|
cycleFinder() |
|
if counter % 10000 == 0: |
|
print(counter, 'of', end) |
|
|
|
print(chamber.topEdge() - 1 + skippedValue) |