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

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