main.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import os, sys
  2. task_dir = os.path.dirname(__file__)
  3. sys.path.append(f"{task_dir}/..")
  4. import numpy as np
  5. from get_tasks import get_input, generate_readme, check_example, bench
  6. from itertools import takewhile
  7. from scipy import ndimage
  8. from numpy.lib.stride_tricks import sliding_window_view
  9. def parse(input, test=False):
  10. if test:
  11. code = (
  12. "".join([line for line in takewhile(lambda l: len(l) > 0, input)])
  13. .replace("#", "1")
  14. .replace(".", "0")
  15. )
  16. code = np.array(list(code), dtype=int)
  17. image = np.array([list(line) for line in input[8:]])
  18. else:
  19. code = np.array(list(input[0].replace("#", "1").replace(".", "0")), dtype=int)
  20. image = np.array([list(line) for line in input[2:]])
  21. image[image == "."] = 0
  22. image[image == "#"] = 1
  23. return image.astype(int), code
  24. def naive_virgin_enhance_image(image, code, steps):
  25. for step in range(steps):
  26. match code[0]:
  27. case 0: pad = 0; val = 0
  28. case _: pad = step % 2; val = 1 - pad
  29. sp = 3 if step == 0 else 1
  30. enhance_image = np.pad(image, sp, constant_values=pad)
  31. enhanced_image = np.full_like(enhance_image, val, dtype=int)
  32. for i in range(enhance_image.shape[0] - 2):
  33. for j in range(enhance_image.shape[1] - 2):
  34. win = enhance_image[i : i + 3, j : j + 3]
  35. enhanced_image[i + 1, j + 1] = code[
  36. win.flatten()[0] * 256 + np.packbits(win.flatten()[1:])
  37. ]
  38. image = enhanced_image
  39. return image
  40. def true_vectorized_chad_enhance_image(image, code, steps, outside=0, pad_size=2):
  41. for _ in range(steps):
  42. image = np.pad(image, pad_size, constant_values=outside)
  43. windows = sliding_window_view(image, (3, 3))
  44. windows = windows.reshape(*windows.shape[:2], 9)
  45. codes = windows[:, :, 0] * 256 + np.packbits(windows[:, :, 1:]).reshape(
  46. windows.shape[:2]
  47. )
  48. image = code[codes]
  49. outside = code[outside * 511]
  50. return image
  51. @bench
  52. def part1(input, test=False, vec=True):
  53. image, code = parse(input, test)
  54. if vec:
  55. image = true_vectorized_chad_enhance_image(image, code, steps=2)
  56. else:
  57. image = naive_virgin_enhance_image(image, code, steps=2)
  58. print("The answer of part1 is:", image.sum())
  59. @bench
  60. def part2(input, test=False, vec=True):
  61. image, code = parse(input, test)
  62. if vec:
  63. image = true_vectorized_chad_enhance_image(image, code, steps=50)
  64. else:
  65. image = naive_virgin_enhance_image(image, code, steps=50)
  66. print("The answer of part2 is:", image.sum())
  67. if __name__ == "__main__":
  68. input, example = get_input(task_dir, 20)
  69. part1(example, True)
  70. part2(example, True)
  71. part1(input, vec=True)
  72. part2(input, vec=True)
  73. generate_readme(task_dir, 20)