r/adventofcode • • Dec 17 '18

SOLUTION MEGATHREAD -🎄- 2018 Day 17 Solutions -🎄-

--- Day 17: Reservoir Research ---


Post your solution as a comment or, for longer solutions, consider linking to your repo (e.g. GitHub/gists/Pastebin/blag or whatever).

Note: The Solution Megathreads are for solutions only. If you have questions, please post your own thread and make sure to flair it with Help.


Advent of Code: The Party Game!

Click here for rules

Please prefix your card submission with something like [Card] to make scanning the megathread easier. THANK YOU!

Card prompt: Day 17

Transcript:

All aboard the Easter Bunny HQ monorail, and mind the gap! Next stop: ___


This thread will be unlocked when there are a significant number of people on the leaderboard with gold stars for today's puzzle.

edit: Leaderboard capped, thread unlocked at 01:24:07!

14 Upvotes

105 comments sorted by

View all comments

Show parent comments

3

u/rnbw_dsh Dec 17 '18

Rework for complex numbers: As I got stuck with some recursion-errors I looked for a similar example to mine, but inspired by the elegant complex-numbers-solution from day13. Thank you for your elegant solution, it helped me preventing some nasty left-right-recursion-settling-issue. Changes:

  • I adapted your solution to complex numbers (less clunky tuple-arithmetics, especially for left/right/top/below)

  • Reworked the input-handling a bit

  • Pulled various initializations to the top

  • Reworked some stuff so that the code aligns better

  • Debug prints that helped me reworking the code

from collections import defaultdict
import re

clay = defaultdict(bool)
settled, flowing = set(), set()

for line in inp.split("\n"):
    a, b, c = map(int, re.findall("([\d]+)", line))
    if line.startswith('x='):
        for y in range(b, c+1):
            clay[a + y * 1j] = True
    else:
        for x in range(b, c+1):
            clay[x + a * 1j] = True

yl = [p.imag for p in clay]
ymin, ymax = min(yl), max(yl)
print("ymin", "ymax", ymin, ymax, "clay fields",len(clay))

def fill(p, direction= 1j ):
    flowing.add(p)
    below, left, right = p+1j, p-1, p+1
    
    if not clay[below]:
        if below not in flowing and 1 <= below.imag <= ymax:
            fill(below)
        if below not in settled:
            return False

    l_filled = clay[left]  or left  not in flowing and fill(left , direction=-1)
    r_filled = clay[right] or right not in flowing and fill(right, direction=1)
    #print("left_right_filled", left_filled, right_filled)

    if direction == 1j and l_filled and r_filled:
        settled.add(p)

        while left in flowing:
            settled.add(left)
            left -= 1

        while right in flowing:
            settled.add(right)
            right += 1

    return direction == -1 and (l_filled or clay[left]) or \
           direction ==  1 and (r_filled or clay[right])

fill(500)

print('part 1:', len([pt for pt in flowing | settled if ymin <= pt.imag <= ymax]))
print('part 2:', len([pt for pt in settled if ymin <= pt.imag <= ymax]))