aboutsummaryrefslogtreecommitdiffstats
path: root/src/17/solve.py
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2023-04-07 17:18:18 -0400
committerLouis Burda <quent.burda@gmail.com>2023-04-07 17:19:39 -0400
commit87ab487d59fa85dbe2afa55cc841b02805ae42ca (patch)
treecd90ab715e1b5b5803674045dbafd6d51d27ac90 /src/17/solve.py
parent1bcc82c5bfbde87edd03c01ffdf9ee5934681592 (diff)
downloadaoc2018-python-87ab487d59fa85dbe2afa55cc841b02805ae42ca.tar.gz
aoc2018-python-87ab487d59fa85dbe2afa55cc841b02805ae42ca.zip
Reorder days into src
Diffstat (limited to 'src/17/solve.py')
-rw-r--r--src/17/solve.py183
1 files changed, 183 insertions, 0 deletions
diff --git a/src/17/solve.py b/src/17/solve.py
new file mode 100644
index 0000000..c6454f3
--- /dev/null
+++ b/src/17/solve.py
@@ -0,0 +1,183 @@
+import sys
+sys.path.append("../common")
+import aoc
+
+def parse_line(l):
+ s = l.split(", ")
+ if s[0].startswith("y="):
+ s = s[::-1]
+
+ res = [[int(x) for x in v.split("=")[1].split("..")] for v in s]
+ return res
+
+constraints = [parse_line(l) for l in aoc.data.split("\n")]
+
+xmin = min(c[0][0] for c in constraints)-1
+xmax = max(c[0][-1] for c in constraints)+1
+ymin = min(c[1][0] for c in constraints)
+ymax = max(c[1][-1] for c in constraints)
+xdif = xmax - xmin + 1
+ydif = ymax - ymin + 1
+
+vmap = [[0 for x in range(xdif)] for y in range(ydif)]
+
+def set_map(x, y, v):
+ global vmap
+ if y < ymin or y > ymax or x < xmin or x > xmax:
+ return
+ vmap[y-ymin][x-xmin] = v
+
+def get_map(x, y):
+ global vmap
+ if x > xmax or x < xmin:
+ return 1
+ elif y > ymax:
+ return 0
+ return vmap[y-ymin][x-xmin]
+
+def drawWall(c):
+ if len(c[0]) == 1:
+ for y in range(c[1][0], c[1][1] + 1):
+ set_map(c[0][0], y, 1)
+ else:
+ for x in range(c[0][0], c[0][1] + 1):
+ set_map(x, c[1][0], 1)
+
+for c in constraints:
+ drawWall(c)
+
+spring = (500, 0)
+
+
+### SETUP END
+
+
+def interpretChar(v):
+ chars = [".", "#", "|", "~"]
+ return chars[v]
+
+def drawMap():
+ for y in range(ydif):
+ aoc.debug("".join([interpretChar(v) for v in vmap[y]]))
+
+def fwriteMap():
+ f = open("output","w+")
+ for y in range(ydif):
+ f.write("".join([interpretChar(v) for v in vmap[y]])+"\n")
+ f.close()
+
+def isstatic(p):
+ return get_map(p[0], p[1]) in (1, 3)
+
+def isfree(p):
+ return get_map(p[0], p[1]) == 0
+
+def move(p):
+ x = p[0]
+ y = p[1]
+ if isfree((x, y+1)):
+ return (x, y+1)
+ onblock = isstatic((x, y+1))
+ if not onblock:
+ return (x,y)
+ npos = [(x + dir, y) for dir in [-1, 1]]
+ npos = [np for np in npos if isfree(np) and onblock]
+ if len(npos) > 1:
+ return npos
+ elif len(npos) == 1:
+ return npos[0]
+ return (x, y)
+
+def fillfloor(p):
+ onblock = True
+ isblock = False
+ x = p[0]
+ while onblock and not isblock and x >= xmin:
+ x -= 1
+ isblock = isstatic((x, p[1]))
+ onblock = isstatic((x, p[1]+1))
+ if not isblock:
+ return None # edge
+ lx = x+1
+
+ onblock = True
+ isblock = False
+ x = p[0]
+ while onblock and not isblock and x <= xmax:
+ x += 1
+ isblock = isstatic((x, p[1]))
+ onblock = isstatic((x, p[1]+1))
+ if not isblock:
+ return None
+ rx = x-1
+
+ return [(i, p[1]) for i in range(lx, rx+1)]
+
+def count_w_flowing():
+ water = 0
+ for y in range(ymin, ymax+1):
+ for x in range(xmin, xmax+1):
+ if get_map(x,y) == 2:
+ water += 1
+ return water
+
+def count_w_static():
+ water = 0
+ for y in range(ymin, ymax+1):
+ for x in range(xmin, xmax+1):
+ if get_map(x,y) == 3:
+ water += 1
+ return water
+
+def simulate():
+ heads = [spring]
+ while len(heads) > 0:
+ cp = heads[-1]
+ if isstatic((cp[0], cp[1]+1)):
+ # solid below => expand
+ res = fillfloor(cp)
+ if res:
+ for p in res:
+ set_map(p[0], p[1], 3)
+ nhead = None
+ for x in range(res[0][0], res[-1][0]+1):
+ np = (x, res[0][1]-1)
+ if get_map(np[0], np[1]) == 2:
+ nhead = np
+ break
+ if nhead == None: # head got trapped
+ heads.pop()
+ else:
+ heads[-1] = nhead
+ continue
+
+ res = move(cp)
+ if type(res[0]) == tuple:
+ heads.pop()
+ heads += res
+ for p in res:
+ set_map(p[0], p[1], 2)
+ else:
+ if res != cp:
+ if res[1] <= ymax:
+ set_map(res[0], res[1], 2)
+ heads[-1] = res
+ else:
+ heads.pop()
+ else:
+ heads.pop()
+
+ if aoc.debug_lvl:
+ aoc.debug(heads)
+ input()
+ fwriteMap()
+
+def solve1(args):
+ simulate()
+ return count_w_flowing() + count_w_static()
+
+def solve2(args):
+ simulate()
+ return count_w_static()
+
+aoc.run(solve1, solve2, sols=[39557, 32984])