Skip to content

Commit

Permalink
Use heuristic-selected parsers for 9 more puzzles
Browse files Browse the repository at this point in the history
  • Loading branch information
IsaacG committed Dec 15, 2024
1 parent cb67a4e commit 365f4bc
Show file tree
Hide file tree
Showing 11 changed files with 20 additions and 27 deletions.
1 change: 0 additions & 1 deletion 2019/d01.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ class Day01(aoc.Challenge):
aoc.TestCase(inputs="1969", part=2, want=966),
aoc.TestCase(inputs="100756", part=2, want=50346),
]
INPUT_PARSER = aoc.parse_one_int_per_line

def fuel(self, mass):
"""Sum fuel needed for some mass and all its fuel."""
Expand Down
2 changes: 0 additions & 2 deletions 2019/d08.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
class Day08(aoc.Challenge):
"""Day 8."""

INPUT_PARSER = aoc.parse_one_str

def part1(self, puzzle_input: str) -> int:
"""Find the min layer."""
layers = chunked(puzzle_input, WIDTH * HEIGHT)
Expand Down
1 change: 0 additions & 1 deletion 2019/d09.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ class Day09(aoc.Challenge):
aoc.TestCase(inputs=SAMPLE[2], part=1, want="1125899906842624"),
aoc.TestCase(inputs="", part=2, want=aoc.TEST_SKIP),
)
INPUT_PARSER = aoc.parse_one_str

def part1(self, puzzle_input: str) -> int:
computer = intcode.Computer(puzzle_input, debug=self.DEBUG)
Expand Down
1 change: 0 additions & 1 deletion 2020/d13.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ class Day13(aoc.Challenge):
aoc.TestCase(inputs=SAMPLE[0], part=1, want=295),
aoc.TestCase(inputs=SAMPLE[0], part=2, want=1068781),
)
INPUT_PARSER = aoc.parse_one_str_per_line

def part1(self, puzzle_input: List[str]) -> int:
"""Find which bus will first arrive once we are at the bus terminal."""
Expand Down
1 change: 0 additions & 1 deletion 2022/d25.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ class Day25(aoc.Challenge):
aoc.TestCase(inputs=SAMPLE[0], part=1, want="2=-1=0"),
aoc.TestCase(inputs=SAMPLE[0], part=2, want=aoc.TEST_SKIP),
]
INPUT_PARSER = aoc.parse_one_str_per_line

def encode(self, dec: int) -> str:
"""Return the SNAFU encoding of a number."""
Expand Down
1 change: 0 additions & 1 deletion 2023/d01.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ class Day01(aoc.Challenge):
aoc.TestCase(inputs="eightwo", part=2, want=82),
aoc.TestCase(inputs="hczrldvxffninemzbhsv2two5eightwozfh", part=2, want=92),
]
INPUT_PARSER = aoc.parse_one_str_per_line

def solver(self, puzzle_input: list[str], part_one: bool) -> int:
"""Walk a string and extract numbers."""
Expand Down
7 changes: 2 additions & 5 deletions 2023/d06.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,13 @@ class Day06(aoc.Challenge):
aoc.TestCase(inputs=SAMPLE[0], part=1, want=288),
aoc.TestCase(inputs=SAMPLE[0], part=2, want=71503),
]
INPUT_PARSER = aoc.parse_one_str_per_line

def solver(self, puzzle_input: InputType, part_one: bool) -> int:
"""Compute how long to charge the car in order to win the race."""
lines = [line.split(":")[1].strip() for line in puzzle_input]

if part_one:
times, distances = ([int(i) for i in line.split()] for line in lines)
times, distances = ([int(i) for i in line[1:]] for line in puzzle_input)
else:
times, distances = ([int(line.replace(" ", ""))] for line in lines)
times, distances = ([int("".join(line[1:]))] for line in puzzle_input)

# See notes for explanation.
result = 1
Expand Down
4 changes: 1 addition & 3 deletions 2023/d12.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
class Day12(aoc.Challenge):
"""Day 12: Hot Springs."""

INPUT_PARSER = aoc.parse_one_str_per_line
TESTS = [
aoc.TestCase(inputs=SAMPLE, part=1, want=21),
aoc.TestCase(inputs=SAMPLE, part=2, want=525152),
Expand Down Expand Up @@ -62,8 +61,7 @@ def ways_to_fit(self, springs: tuple[str, ...], numbers: tuple[int, ...]) -> int
def solver(self, puzzle_input: str, part_one: bool) -> int:
"""Return the total number of possible fits."""
count = 0
for line in puzzle_input:
springs_str, numbers_str = line.split()
for springs_str, numbers_str in puzzle_input:
if not part_one:
springs_str = "?".join([springs_str] * 5)
numbers_str = ",".join([numbers_str] * 5)
Expand Down
1 change: 0 additions & 1 deletion 2023/d15.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ class Day15(aoc.Challenge):
aoc.TestCase(inputs=SAMPLE, part=1, want=1320),
aoc.TestCase(inputs=SAMPLE, part=2, want=145),
]
INPUT_PARSER = aoc.parse_one_str

def hash(self, word: str) -> int:
"""Compute the HASH of a word."""
Expand Down
24 changes: 14 additions & 10 deletions pylib/aoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,28 +626,32 @@ def _parser(self) -> parsers.BaseParser:
# Use heuristics to guess at an input parser.
data = self.raw_data(None)
lines = data.splitlines()
multi_lines = len(lines) > 1
multi_line = len(lines) > 1
one_line = lines[0]

if len(lines) > 5 and len(lines[0]) > 5 and len(lines) == len(lines[0]):
return CoordinatesParser()
if ParseIntergers().matches(data):
return ParseIntergers()

if len(RE_INT.findall(one_line)) > 1 and multi_lines:
lines = [re.sub(" +", " ", line) for line in lines[:4]]
pi = ParseIntergers(multi_line=multi_line)
if pi.matches(data):
return pi

if len(RE_INT.findall(one_line)) > 1 and multi_line:
lines = lines[:4]
for char in "?()+*":
lines = [l.replace(char, "\\" + char) for l in lines]
lines = [re.sub(" +", " ", line) for line in lines]
one_line = lines[0]
template = re.compile(RE_INT.sub(lambda x: RE_INT.pattern, one_line))
print(template)
# print(template)
if all(template.fullmatch(line) for line in lines):
return parse_ints_per_line
elif not multi_lines and all(RE_INT.fullmatch(i) for i in one_line.split()):
elif not multi_line and all(RE_INT.fullmatch(i) for i in one_line.split()):
return parse_ints_one_line

word_count = max(len(line.split()) for line in data.splitlines())
if word_count == 1:
return parse_one_str_per_line if multi_lines else parse_one_str
return parse_multi_str_per_line if multi_lines else parse_one_str
return parse_one_str_per_line if multi_line else parse_one_str
return parse_multi_str_per_line if multi_line else parse_one_str

def input_parser(self, puzzle_input: str) -> Any:
"""Parse input data. Block of text -> output."""
Expand Down
4 changes: 3 additions & 1 deletion pylib/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,11 @@ def parse(self, puzzle_input: str) -> Any:
raise NotImplementedError


@dataclasses.dataclass
class ParseIntergers(BaseParser):
"""Get integers from input."""

multi_line: bool | None = None
NUMBER_LINE = re.compile(r"^[+-]?\d{1,1000}( +[+-]?\d{1,1000})*$")

def matches(self, puzzle_input) -> bool:
Expand All @@ -72,7 +74,7 @@ def matches(self, puzzle_input) -> bool:
def parse(self, puzzle_input: str) -> int | list[int] | list[list[int]]:
"""Parse a puzzle input."""
lines = puzzle_input.splitlines()
multi_line = len(lines) > 1
multi_line = len(lines) > 1 if self.multi_line is None else self.multi_line
multi_word = any(len(line.split()) > 1 for line in lines)
numbers = [[int(word) for word in line.split()] for line in lines]
if multi_line:
Expand Down

0 comments on commit 365f4bc

Please sign in to comment.