Advertisement
Guest User

Untitled

a guest
Dec 19th, 2021
365
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.24 KB | None | 0 0
  1. import numpy as np
  2. from scipy.signal import convolve2d
  3.  
  4. def part_1():
  5.   handle = open('20a.txt','r')
  6.   #read in the dictionary, convert it to binary
  7.   ref = handle.readline().strip()
  8.   handle.readline() #skip the blank
  9.   vals = {'.':0,'#':1}
  10.   ref = [vals[x] for x in ref]
  11.  
  12.   #now read in the initial image, conver to binary
  13.   lines = []
  14.   for line in handle:
  15.     row = [vals[x] for x in line.strip()]
  16.     lines.append(row)
  17.  
  18.   image = np.array(lines)
  19.  
  20.   #this is the key to the puzzle - you not only have to keep track of what
  21.   #is happening in the image boundary, but also what happens to the infinite background
  22.   #the infinite background will start at all zero, but will potentially change
  23.   #if the first value in the dictionary is not zero (changing to all ones)
  24.   #and then will change back again on the next step (assuming the last entry is a 0)
  25.   pad_val = 0
  26.  
  27.   #enhance 50 times
  28.   for i in range(50):
  29.     image = enhance(image,ref,pad_val)
  30.     if i == 1 or i == 49: #really 2 and 50
  31.       print(np.sum(image)) #count the ones.
  32.    
  33.     #update the padding value, if it's currently 0, it goes to ref[0],
  34.     #if it's currently 1, it goes to ref[-1] (which is what you get from all 1s)
  35.     if pad_val == 0:
  36.       pad_val = ref[0]
  37.     else:
  38.       pad_val = ref[-1]
  39.  
  40. #use the magic of convolution!  
  41. def enhance(img,ref,pad_val):
  42.     result = np.zeros_like(img)
  43.     img = np.pad(img,(2,2),constant_values=pad_val)
  44.  
  45.     kernel = np.array([[1,2,4],[8,16,32],[64,128,256]])
  46.     indices = convolve2d(img,kernel,mode='full',fillvalue=pad_val)
  47.    
  48.     result = np.array(ref)[indices]
  49.     return result
  50.    
  51.  
  52. def enhance_slow(img,ref,pad_val):
  53.  
  54.   result = np.zeros_like(img)
  55.   #first we need to pad out the image with the current pad value
  56.   #note that we pad by TWO per edge, because we need to specially handle any cell
  57.   #which depends on a cell in the image (so the image itself plus a border of 1)
  58.   #the second layer of padding lets us figure out the new values of that first
  59.   #layer of external cells.
  60.   img = np.pad(img,(2,2),constant_values=pad_val)
  61.   #we also need to figure out what the padded values in the result will be
  62.   #this is a little hacky, but basically we want the result to be the same size
  63.   #as the input image, so that it's easy to match coordinates, and so have some
  64.   #extra values along the edges
  65.   #this could be optimized away, I think
  66.   if pad_val == 0:
  67.     pad_val = ref[0]
  68.   else:
  69.     pad_val = ref[-1]
  70.   result = np.pad(result,(2,2),constant_values=pad_val)
  71.  
  72.   #now we just loop over the range of cells which need to be calculated
  73.   #this extends one pixel past the original image boundaries (which have
  74.   #been padded by TWO, thus the 1 and -1)
  75.  
  76.   #if we wanted to go FAST we could convolve with a specially crafted filter:
  77.   # [1,2,4]
  78.   # [8,16,32]
  79.   # [64,128,256]
  80.   #to get each code, and then just batch update
  81.   #but this was faster to code at 12AM.
  82.   for x in range(1,len(img)-1):
  83.     for y in range(1,len(img)-1):
  84.       vals = img[x-1:x+2,y-1:y+2]
  85.       vals = vals.reshape(-1) #luckily np reshape does the thing we want
  86.       code = int(''.join([str(x) for x in list(vals)]),2) #lookup the code
  87.       result[x,y] = ref[code] #fill in the result cell
  88.   return result
  89.  
  90.  
  91. part_1()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement