Let's see how far I get this year.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

day03-1.py 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. from helpers import Helper
  2. helper = Helper(debug=True)
  3. debug = helper.debug
  4. load_input = helper.load_input
  5. class InputNumber:
  6. def __init__(self, number, start_pos, end_pos, line):
  7. self.number = number
  8. self.start_pos = start_pos
  9. self.end_pos = end_pos
  10. self.line = line
  11. def _is_symbol(self, char):
  12. return (char != "." and not char.isdigit())
  13. def _check_up(self, input):
  14. if self.line == 0:
  15. return False
  16. cur_line = input[self.line - 1]
  17. for i in range(max(0, self.start_pos-1), min(len(cur_line)-1, self.end_pos+2)):
  18. char = cur_line[i]
  19. if self._is_symbol(char):
  20. debug(f"Found symbol next to {self.number} at line {self.line-1}: {i}")
  21. return True
  22. return False
  23. def _check_down(self, input):
  24. if self.line == len(input)-1:
  25. return False
  26. cur_line = input[self.line + 1]
  27. for i in range(max(0, self.start_pos-1), min(len(cur_line)-1, self.end_pos+2)):
  28. char = cur_line[i]
  29. if self._is_symbol(char):
  30. debug(f"Found symbol next to {self.number} at line {self.line+1}: {i}")
  31. return True
  32. return False
  33. def _check_left(self, input):
  34. if self.start_pos == 0:
  35. debug("Already at the left-hand side of the line")
  36. return False
  37. if self._is_symbol(input[self.line][self.start_pos-1]):
  38. debug(f"Found symbol next to {self.number} at line {self.line}: {self.start_pos-1}")
  39. return True
  40. return False
  41. def _check_right(self, input):
  42. if self.end_pos == len(input[0]) - 1:
  43. debug("Already at the right-hand side of the line")
  44. return False
  45. if self._is_symbol(input[self.line][self.end_pos+1]):
  46. debug(f"Found symbol next to {self.number} at line {self.line}: {self.end_pos+1}")
  47. return True
  48. return False
  49. def is_part_number(self, input):
  50. return (
  51. self._check_up(input)
  52. or self._check_down(input)
  53. or self._check_left(input)
  54. or self._check_right(input)
  55. )
  56. def main():
  57. lines = load_input(3)
  58. # Input is lines of periods (.), numbers (0-9), and symbols
  59. # (anything that isn't a period or number)
  60. # Any number adjacent (horizontally, vertically, diagonally)
  61. # to a symbol is a part number. Get the sum of the part numbers.
  62. max_len = len(lines[0]) # all lines are the same length
  63. positions = []
  64. for j, line in enumerate(lines):
  65. i = 0
  66. while i < max_len:
  67. if line[i].isdigit():
  68. current_number = ""
  69. start_pos = i
  70. while i < max_len and line[i].isdigit():
  71. current_number += f"{line[i]}"
  72. i += 1
  73. end_pos = i
  74. input_number = InputNumber(
  75. number = int(current_number),
  76. start_pos = start_pos,
  77. end_pos = end_pos-1, # i is one greater than the end of the number
  78. line = j
  79. )
  80. positions.append(input_number)
  81. debug(f"Found {input_number.number} at line {input_number.line} ({input_number.start_pos}, {input_number.end_pos})")
  82. i += 1
  83. # Now I have a list of the positions of all the numbers in the input.
  84. part_numbers = []
  85. for p in positions:
  86. if p.is_part_number(lines):
  87. part_numbers.append(p.number)
  88. print(sum(part_numbers))
  89. if __name__ == "__main__":
  90. main()