solution.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #!/usr/bin/python3
  2. import sys
  3. # part 1
  4. def get_bounds(tiles):
  5. min_x = sys.maxsize
  6. min_y = sys.maxsize
  7. max_x = 0
  8. max_y = 0
  9. for x in tiles:
  10. for y in tiles[x]:
  11. if x < min_x: min_x = x
  12. if x > max_x: max_x = x
  13. if y < min_y: min_y = y
  14. if y > max_y: max_y = y
  15. return (min_x, min_y, max_x, max_y)
  16. def print_grid(tiles, bounds):
  17. min_x, min_y, max_x, max_y = bounds
  18. for y in range(min_y, max_y + 1):
  19. for x in range(min_x, max_x + 1):
  20. if x in tiles and y in tiles[x]:
  21. print(tiles[x][y], end='')
  22. else:
  23. print(' ', end='')
  24. print()
  25. def try_add(tiles, x, y, tile):
  26. if x not in tiles:
  27. tiles[x] = {y: tile}
  28. else:
  29. tiles[x][y] = tile
  30. def collides_with(tiles, sand, pos):
  31. if px in tiles and py in tiles[px]:
  32. return True
  33. def comes_to_rest(tiles, origin, bounds):
  34. min_x, min_y, max_x, max_y = bounds
  35. sx, sy = origin
  36. # lol
  37. if sx not in tiles:
  38. return False
  39. while sy <= max_y:
  40. if not (sx in tiles and sy + 1 in tiles[sx]):
  41. sy += 1
  42. continue
  43. elif not (sx - 1 in tiles and sy + 1 in tiles[sx - 1]):
  44. sx -= 1
  45. sy += 1
  46. elif not (sx + 1 in tiles and sy + 1 in tiles[sx + 1]):
  47. sx += 1
  48. sy += 1
  49. else:
  50. try_add(tiles, sx, sy, 'o')
  51. return True
  52. return False
  53. def part1():
  54. tiles = {}
  55. for line in sys.stdin:
  56. new_rocks = [[int(pos) for pos in coord.split(',')] for coord in line.strip().split(' -> ')]
  57. print(new_rocks)
  58. for i, (rx1, ry1) in enumerate(new_rocks[1:]):
  59. rx2, ry2 = new_rocks[i]
  60. if rx1 - rx2 != 0:
  61. for x in range(min(rx1, rx2), max(rx1, rx2) + 1):
  62. try_add(tiles, x, ry1, '#')
  63. elif ry1 - ry2 != 0:
  64. for y in range(min(ry1, ry2), max(ry1, ry2) + 1):
  65. try_add(tiles, rx1, y, '#')
  66. print(tiles)
  67. bounds = get_bounds(tiles)
  68. rest = 0
  69. while comes_to_rest(tiles, (500, 0), bounds):
  70. rest += 1
  71. print_grid(tiles, bounds)
  72. print(f'{rest} units come to rest')
  73. # part 2
  74. def part2():
  75. tiles = {}
  76. for line in sys.stdin:
  77. new_rocks = [[int(pos) for pos in coord.split(',')] for coord in line.strip().split(' -> ')]
  78. print(new_rocks)
  79. for i, (rx1, ry1) in enumerate(new_rocks[1:]):
  80. rx2, ry2 = new_rocks[i]
  81. if rx1 - rx2 != 0:
  82. for x in range(min(rx1, rx2), max(rx1, rx2) + 1):
  83. try_add(tiles, x, ry1, '#')
  84. elif ry1 - ry2 != 0:
  85. for y in range(min(ry1, ry2), max(ry1, ry2) + 1):
  86. try_add(tiles, rx1, y, '#')
  87. print(tiles)
  88. min_x, min_y, max_x, max_y = get_bounds(tiles)
  89. least_x = 500 - (2 * (max_y - min_y))
  90. most_x = 500 + 2 * (max_y - min_y)
  91. for x in range(least_x, most_x + 1):
  92. try_add(tiles, x, max_y + 2, '#')
  93. bounds = get_bounds(tiles)
  94. print_grid(tiles, (min_x, min_y, max_x, max_y))
  95. rest = 0
  96. while not (500 in tiles and 0 in tiles[500]):
  97. comes_to_rest(tiles, (500, 0), bounds)
  98. rest += 1
  99. print()
  100. print_grid(tiles, (min_x, min_y, max_x, max_y))
  101. print(f'{rest} units come to rest')
  102. if sys.argv[1] in '1':
  103. part1()
  104. else:
  105. part2()