From c4c013c3eadc89b5365c0d7b58e7fe4650f387bc Mon Sep 17 00:00:00 2001 From: Pat Thoyts Date: Sun, 3 Dec 2023 08:33:40 +0000 Subject: [PATCH] day3: completed part 1 --- day3/data/test_input2 | 10 +++++++++ day3/run.py | 21 +++++++++++++++++ day3/schematic.py | 51 ++++++++++++++++++++++++++++++++++++++++++ day3/test_schematic.py | 25 +++++++++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 day3/data/test_input2 create mode 100755 day3/run.py create mode 100644 day3/schematic.py create mode 100644 day3/test_schematic.py diff --git a/day3/data/test_input2 b/day3/data/test_input2 new file mode 100644 index 0000000..395c419 --- /dev/null +++ b/day3/data/test_input2 @@ -0,0 +1,10 @@ +467....114 +...*...... +..35..633. +......#... +617*...... +.....+.58. +..592..... +......755. +...$.*.... +.664.598.. diff --git a/day3/run.py b/day3/run.py new file mode 100755 index 0000000..fb2d64e --- /dev/null +++ b/day3/run.py @@ -0,0 +1,21 @@ +#!/bin/env python3 + +import sys +import argparse +from schematic import Schematic + + +def main(args=None): + parser = argparse.ArgumentParser(description="AoC 2023 day 2") + parser.add_argument('filename', type=str, help="input path") + parser.add_argument('-d', '--debug', action='store_true') + options = parser.parse_args(args) + + with open(options.filename, 'r') as input: + schematic = Schematic.fromstream(input) + print(f"part1: {sum(schematic.parts)}") + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/day3/schematic.py b/day3/schematic.py new file mode 100644 index 0000000..ef060b6 --- /dev/null +++ b/day3/schematic.py @@ -0,0 +1,51 @@ +from typing import List + + +class Schematic: + def __init__(self, rows: List[str]): + self.rows = rows + self.span = len(rows[0]) + self.parts = [] + self.debug = True + self.update() + + def update(self): + """Parse the input data and generate the list of parts""" + self.parts = [] + for row in range(len(self.rows)): + part = {'digits': [], 'symbols':[]} + for col in range(self.span): + c = self.rows[row][col] + if c.isdigit(): + part['digits'].append(c) + part['symbols'].append(self.get_neighbours(row, col)) + else: + if part['digits']: + self._complete_part(part) + part = {'digits': [], 'symbols':[]} + if part['digits']: + self._complete_part(part) + part = {'digits': [], 'symbols':[]} + + def _complete_part(self, part:dict): + value = int(''.join(part['digits'])) + valid = bool(''.join(part['symbols'])) + if self.debug: + print(value, valid, ''.join(part['symbols'])) + if valid: + self.parts.append(value) + + def get_neighbours(self, row: int, col: int) -> bool: + result = '' + for r in [row - 1, row, row + 1]: + if r >= 0 and r < len(self.rows): + for c in [col - 1, col, col + 1]: + if c >= 0 and c < self.span: + t = self.rows[r][c] + if not (t.isdigit() or t == '.'): + result = result + t + return result + + @staticmethod + def fromstream(stream) -> 'Schematic': + return Schematic([x.strip() for x in stream.readlines() if x.strip()]) diff --git a/day3/test_schematic.py b/day3/test_schematic.py new file mode 100644 index 0000000..f07335f --- /dev/null +++ b/day3/test_schematic.py @@ -0,0 +1,25 @@ +import unittest +import os +import sys +from io import StringIO +from schematic import Schematic + + +class TestPart1(unittest.TestCase): + def test_schematic_sum(self): + with open('data/test_input') as input: + schematic = Schematic.fromstream(input) + self.assertSequenceEqual( + [467, 35, 633, 617, 592, 755, 664, 598], + schematic.parts) + self.assertEqual(4361, sum(schematic.parts)) + + def test_schematic_from_file2(self): + with open('data/test_input2') as input: + schematic = Schematic.fromstream(input) + self.assertSequenceEqual( + [467, 35, 633, 617, 592, 755, 664, 598], + schematic.parts) + +if __name__ == '__main__': + unittest.main() -- 2.23.0