Advertisement
DuckStrom

d17.py

Dec 17th, 2018
244
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.97 KB | None | 0 0
  1. inp = open("d17.txt").read()
  2.  
  3. import re, numpy as np
  4. from collections import deque
  5. from PIL import Image
  6.  
  7. def renderboard(board,loc="d17.png"):
  8.     palette = [0,0,0, 0xFF,0xA0,0x66, 0x14,0x66,0xFF, 0x38,0x7D,0xFF, 0,0xFF,0xDD]
  9.    
  10.     img = Image.fromarray(board, "P")
  11.     img.putpalette(palette)
  12.     #img.show()
  13.     img.save(loc)
  14.  
  15. def step(board):
  16.     for _ in range(len(activewater)):
  17.         w = activewater.popleft()
  18.         if (w[0]+1 > bounds[3]):
  19.             board[w[0]][w[1]] = 3
  20.             continue
  21.         down = board[w[0]+1][w[1]]
  22.         if down not in solid:
  23.             # falling
  24.             if (w[0]+1,w[1]) not in activewater:
  25.                 activewater.append((w[0]+1,w[1]))
  26.             board[w[0]][w[1]] = 3
  27.         else:
  28.             # hit something, so check if there's a basin to fill
  29.             flat = [0,0]
  30.             enclosed = True
  31.             while True:
  32.                 if (board[w[0]][w[1]+flat[0]-1] in solid):
  33.                     #print("left bound at",flat)
  34.                     break
  35.                 elif (board[w[0]+1][w[1]+flat[0]-1] not in solid):
  36.                     #print("found a hole on the left")
  37.                     activewater.append((w[0], w[1]+flat[0]-1))
  38.                     enclosed = False
  39.                     break
  40.                 else:
  41.                     #print("lb",flat)
  42.                     flat[0] -= 1
  43.             while True:
  44.                 if (board[w[0]][w[1]+flat[1]+1] in solid):
  45.                     #print("right bound at",flat)
  46.                     break
  47.                 elif (board[w[0]+1][w[1]+flat[1]+1] not in solid):
  48.                     activewater.append((w[0], w[1]+flat[1]+1))
  49.                     enclosed = False
  50.                     break
  51.                 else:
  52.                     #print("rb",flat)
  53.                     flat[1] += 1
  54.            
  55.             if enclosed:
  56.                 # the thing we hit is enclosed, so make this all standing water and reset our activewater 1 tick up the flow
  57.                 for i in range(w[1]+flat[0],w[1]+flat[1]+1):
  58.                     board[w[0]][i] = 2
  59.                 activewater.append((w[0]-1,w[1]))
  60.             else:
  61.                 # there's a hole, so make the range we found flowing water and let the new activewater entries tick
  62.                 for i in range(w[1]+flat[0],w[1]+flat[1]+1):
  63.                     board[w[0]][i] = 3
  64.  
  65. ud = sorted([[int(j) for j in i] for i in re.compile("x=(\d+), y=(\d+)\.\.(\d+)").findall(inp)]) # vertical ranges
  66. lr = sorted([[int(j) for j in i] for i in re.compile("y=(\d+), x=(\d+)\.\.(\d+)").findall(inp)]) # horiz ranges
  67.  
  68. bounds = (min(500,ud[0][0]), min(0, lr[0][0]), ud[-1][0], lr[-1][0])
  69. xoffset = bounds[0] - 1
  70. miny = 0x7FFFFFFF
  71.  
  72. boundsoffset = (bounds[0]-xoffset, bounds[1], bounds[2]-xoffset, bounds[3])
  73.  
  74. empty, clay, waters, waterf, spring = 0, 1, 2, 3, 4
  75. solid = [1,2]
  76.  
  77. board = np.zeros((bounds[3]-bounds[1]+1, bounds[2]-bounds[0]+3), dtype=np.uint8)
  78. #print(len(board), len(board[0]))
  79. #print(bounds)
  80.  
  81. for line in ud:
  82.     x = line[0]
  83.     for y in range(line[1],line[2]+1):
  84.         if (y < miny):
  85.             miny = y
  86.         board[y][x-xoffset] = 1
  87.  
  88. for line in lr:
  89.     y = line[0]
  90.     if (y < miny):
  91.         miny = y
  92.     for x in range(line[1],line[2]+1):
  93.         board[y][x-xoffset] = 1
  94.  
  95. board[0][500-xoffset] = 4
  96. activewater = deque([(1,500-xoffset)])
  97.  
  98. i = 0
  99. while activewater:
  100.     step(board)
  101.     renderboard(board,"d17\\frame" + str(i).zfill(4) + ".png")
  102.     i += 1
  103.  
  104. p2 = (board[miny:]==2).sum()
  105. p1 = (board[miny:]==3).sum()
  106.  
  107. print("P1", p1+p2)
  108. print("P2", p2)
  109.  
  110. renderboard(board)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement