Let's see how far I get this year.
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

day03-1.py 3.7KB

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