1
0
Fork 0

formatting and cosmetic updates to 2020.

This commit is contained in:
Gabe Venberg 2026-04-17 16:21:34 +02:00
parent 84c4cf9991
commit cd75e58f77
28 changed files with 320 additions and 287 deletions

View file

@ -2,19 +2,19 @@
import pathlib import pathlib
import sys import sys
import re
from dataclasses import dataclass
def parse(puzzle_input): def parse(puzzle_input):
"""Parse input""" """Parse input"""
return [int(string) for string in puzzle_input.splitlines()] return [int(string) for string in puzzle_input.splitlines()]
def part1(data: list[int]): def part1(data: list[int]):
"""Solve part 1""" """Solve part 1"""
data.sort() data.sort()
while True: while True:
if len(data) < 2: if len(data) < 2:
raise ValueError('no match found') raise ValueError("no match found")
s = data[0] + data[-1] s = data[0] + data[-1]
if s > 2020: if s > 2020:
data.pop(-1) data.pop(-1)
@ -23,12 +23,13 @@ def part1(data:list[int]):
else: else:
return data[0] * data[-1] return data[0] * data[-1]
def part2(data): def part2(data):
"""Solve part 2""" """Solve part 2"""
data.sort() data.sort()
while True: while True:
if len(data) < 3: if len(data) < 3:
raise ValueError('no match found') raise ValueError("no match found")
if data[0] + data[1] + data[-1] > 2020: if data[0] + data[1] + data[-1] > 2020:
data.pop(-1) data.pop(-1)
elif data[0] + data[-1] + data[-2] < 2020: elif data[0] + data[-1] + data[-2] < 2020:
@ -38,6 +39,7 @@ def part2(data):
else: else:
return data[0] * data[-1] * data[-2] return data[0] * data[-1] * data[-2]
def solve(puzzle_input): def solve(puzzle_input):
"""Solve the puzzle for the given input""" """Solve the puzzle for the given input"""
data = parse(puzzle_input) data = parse(puzzle_input)
@ -46,6 +48,7 @@ def solve(puzzle_input):
return solution1, solution2 return solution1, solution2
if __name__ == "__main__": if __name__ == "__main__":
for path in sys.argv[1:]: for path in sys.argv[1:]:
print(f"{path}:") print(f"{path}:")

View file

@ -6,28 +6,24 @@ import day1 as aoc
PUZZLE_DIR = pathlib.Path(__file__).parent PUZZLE_DIR = pathlib.Path(__file__).parent
# these test fixtures setup the test, mainly by reading the filename into a string in this simple case. # these test fixtures setup the test, mainly by reading the filename into a string in this simple case.
@pytest.fixture @pytest.fixture
def example1(): def example():
puzzle_input = (PUZZLE_DIR / "example1").read_text().strip() puzzle_input = (PUZZLE_DIR / "example").read_text().strip()
return aoc.parse(puzzle_input) return aoc.parse(puzzle_input)
@pytest.fixture
def example2():
puzzle_input = (PUZZLE_DIR / "example2").read_text().strip()
return aoc.parse(puzzle_input)
# @pytest.mark.skip(reason="Not implemented") def test_parse(example):
def test_parse_example1(example1):
"""Test that input is parsed properly""" """Test that input is parsed properly"""
assert example1 == [1721, 979, 366, 299, 675, 1456] assert example == [1721, 979, 366, 299, 675, 1456]
# @pytest.mark.skip(reason="Not implemented")
def test_part1_example1(example1): def test_part1(example):
"""Test part 1 on example input""" """Test part 1 on example input"""
assert aoc.part1(example1) == 514579 assert aoc.part1(example) == 514579
# @pytest.mark.skip(reason="Not implemented")
def test_part2_example2(example1): def test_part2(example):
"""Test part 2 on example input""" """Test part 2 on example input"""
assert aoc.part2(example1) == 241861950 assert aoc.part2(example) == 241861950

View file

@ -1,10 +1,11 @@
#! /usr/bin/env python3 #! /usr/bin/env python3
import pathlib import pathlib
import sys
import re import re
import sys
from dataclasses import dataclass from dataclasses import dataclass
@dataclass @dataclass
class PasswordSpec: class PasswordSpec:
first: int first: int
@ -12,29 +13,40 @@ class PasswordSpec:
letter: str letter: str
password: str password: str
def parse(puzzle_input: str): def parse(puzzle_input: str):
"""Parse input""" """Parse input"""
regex = re.compile(r'^(\d+)-(\d+) (\w): (\w+)$') regex = re.compile(r"^(\d+)-(\d+) (\w): (\w+)$")
toInt = lambda x: PasswordSpec(int(x[0]), int(x[1]), x[2], x[3])
def toInt(x):
return PasswordSpec(int(x[0]), int(x[1]), x[2], x[3])
return [toInt(regex.match(i).groups()) for i in puzzle_input.splitlines()] return [toInt(regex.match(i).groups()) for i in puzzle_input.splitlines()]
def part1(data): def part1(data):
"""Solve part 1""" """Solve part 1"""
test = lambda x: x.first<=x.password.count(x.letter)<=x.second
def test(x):
return x.first <= x.password.count(x.letter) <= x.second
# these two lines are equivilant. # these two lines are equivilant.
# return sum(1 for p in data if test(p)) # return sum(1 for p in data if test(p))
return len([1 for p in data if test(p)]) return len([1 for p in data if test(p)])
def test_password(passwordSpec: PasswordSpec): def test_password(passwordSpec: PasswordSpec):
if passwordSpec.password[passwordSpec.first - 1] == passwordSpec.letter: if passwordSpec.password[passwordSpec.first - 1] == passwordSpec.letter:
return passwordSpec.password[passwordSpec.second - 1] != passwordSpec.letter return passwordSpec.password[passwordSpec.second - 1] != passwordSpec.letter
else: else:
return passwordSpec.password[passwordSpec.second - 1] == passwordSpec.letter return passwordSpec.password[passwordSpec.second - 1] == passwordSpec.letter
def part2(data): def part2(data):
"""Solve part 2""" """Solve part 2"""
return sum(1 for p in data if test_password(p)) return sum(1 for p in data if test_password(p))
def solve(puzzle_input): def solve(puzzle_input):
"""Solve the puzzle for the given input""" """Solve the puzzle for the given input"""
data = parse(puzzle_input) data = parse(puzzle_input)
@ -43,6 +55,7 @@ def solve(puzzle_input):
return solution1, solution2 return solution1, solution2
if __name__ == "__main__": if __name__ == "__main__":
for path in sys.argv[1:]: for path in sys.argv[1:]:
print(f"{path}:") print(f"{path}:")

View file

@ -6,32 +6,28 @@ import day2 as aoc
PUZZLE_DIR = pathlib.Path(__file__).parent PUZZLE_DIR = pathlib.Path(__file__).parent
# these test fixtures setup the test, mainly by reading the filename into a string in this simple case. # these test fixtures setup the test, mainly by reading the filename into a string in this simple case.
@pytest.fixture @pytest.fixture
def example1(): def example():
puzzle_input = (PUZZLE_DIR / "example1").read_text().strip() puzzle_input = (PUZZLE_DIR / "example").read_text().strip()
return aoc.parse(puzzle_input) return aoc.parse(puzzle_input)
@pytest.fixture
def example2():
puzzle_input = (PUZZLE_DIR / "example2").read_text().strip()
return aoc.parse(puzzle_input)
# @pytest.mark.skip(reason="Not implemented") def test_parse(example):
def test_parse_example1(example1):
"""Test that input is parsed properly""" """Test that input is parsed properly"""
assert example1 == [ assert example == [
aoc.PasswordSpec(first=1, second=3, letter='a', password='abcde'), aoc.PasswordSpec(first=1, second=3, letter="a", password="abcde"),
aoc.PasswordSpec(first=1, second=3, letter='b', password='cdefg'), aoc.PasswordSpec(first=1, second=3, letter="b", password="cdefg"),
aoc.PasswordSpec(first=2, second=9, letter='c', password='ccccccccc') aoc.PasswordSpec(first=2, second=9, letter="c", password="ccccccccc"),
] ]
# @pytest.mark.skip(reason="Not implemented")
def test_part1_example1(example1):
"""Test part 1 on example input"""
assert aoc.part1(example1) == 2
# @pytest.mark.skip(reason="Not implemented") def test_part1(example):
def test_part2_example2(example1): """Test part 1 on example input"""
assert aoc.part1(example) == 2
def test_part2(example):
"""Test part 2 on example input""" """Test part 2 on example input"""
assert aoc.part2(example1) == 1 assert aoc.part2(example) == 1

View file

@ -2,25 +2,35 @@
import pathlib import pathlib
import sys import sys
import re
from dataclasses import dataclass
from pprint import pprint
def parse(puzzle_input: str): def parse(puzzle_input: str):
"""Parse input""" """Parse input"""
# returns a 2 dimentional array where true means there is a tree there. # returns a 2 dimentional array where true means there is a tree there.
return [[i=='#' for i in j] for j in puzzle_input.splitlines()] return [[i == "#" for i in j] for j in puzzle_input.splitlines()]
def part1(data): def part1(data):
"""Solve part 1""" """Solve part 1"""
return solveForSlope(data, 3, 1) return solveForSlope(data, 3, 1)
def solveForSlope(data, right: int, down: int): def solveForSlope(data, right: int, down: int):
return sum(1 for index, row in enumerate(data[::down]) if row[(right*index)%len(row)]) return sum(
1 for index, row in enumerate(data[::down]) if row[(right * index) % len(row)]
)
def part2(data): def part2(data):
"""Solve part 2""" """Solve part 2"""
return solveForSlope(data,1,1)*solveForSlope(data,3,1)*solveForSlope(data,5,1)*solveForSlope(data,7,1)*solveForSlope(data,1,2) return (
solveForSlope(data, 1, 1)
* solveForSlope(data, 3, 1)
* solveForSlope(data, 5, 1)
* solveForSlope(data, 7, 1)
* solveForSlope(data, 1, 2)
)
def solve(puzzle_input): def solve(puzzle_input):
"""Solve the puzzle for the given input""" """Solve the puzzle for the given input"""
@ -30,6 +40,7 @@ def solve(puzzle_input):
return solution1, solution2 return solution1, solution2
if __name__ == "__main__": if __name__ == "__main__":
for path in sys.argv[1:]: for path in sys.argv[1:]:
print(f"{path}:") print(f"{path}:")

View file

@ -6,21 +6,18 @@ import day3 as aoc
PUZZLE_DIR = pathlib.Path(__file__).parent PUZZLE_DIR = pathlib.Path(__file__).parent
# these test fixtures setup the test, mainly by reading the filename into a string in this simple case. # these test fixtures setup the test, mainly by reading the filename into a string in this simple case.
@pytest.fixture @pytest.fixture
def example1(): def example():
puzzle_input = (PUZZLE_DIR / "example1").read_text().strip() puzzle_input = (PUZZLE_DIR / "example.txt").read_text().strip()
return aoc.parse(puzzle_input) return aoc.parse(puzzle_input)
@pytest.fixture
def example2():
puzzle_input = (PUZZLE_DIR / "example1").read_text().strip()
return aoc.parse(puzzle_input)
# @pytest.mark.skip(reason="Not implemented") def test_parse(example):
def test_parse_example1(example1):
"""Test that input is parsed properly""" """Test that input is parsed properly"""
assert example1 == [[False, False, True, True, False, False, False, False, False, False, False], assert example == [
[False, False, True, True, False, False, False, False, False, False, False],
[True, False, False, False, True, False, False, False, True, False, False], [True, False, False, False, True, False, False, False, True, False, False],
[False, True, False, False, False, False, True, False, False, True, False], [False, True, False, False, False, False, True, False, False, True, False],
[False, False, True, False, True, False, False, False, True, False, True], [False, False, True, False, True, False, False, False, True, False, True],
@ -30,14 +27,17 @@ def test_parse_example1(example1):
[False, True, False, False, False, False, False, False, False, False, True], [False, True, False, False, False, False, False, False, False, False, True],
[True, False, True, True, False, False, False, True, False, False, False], [True, False, True, True, False, False, False, True, False, False, False],
[True, False, False, False, True, True, False, False, False, False, True], [True, False, False, False, True, True, False, False, False, False, True],
[False, True, False, False, True, False, False, False, True, False, True]] [False, True, False, False, True, False, False, False, True, False, True],
]
# @pytest.mark.skip(reason="Not implemented") # @pytest.mark.skip(reason="Not implemented")
def test_part1_example1(example1): def test_part1(example):
"""Test part 1 on example input""" """Test part 1 on example input"""
assert aoc.part1(example1) == 7 assert aoc.part1(example) == 7
# @pytest.mark.skip(reason="Not implemented") # @pytest.mark.skip(reason="Not implemented")
def test_part2_example2(example2): def test_part2(example):
"""Test part 2 on example input""" """Test part 2 on example input"""
assert aoc.part2(example2) == 336 assert aoc.part2(example) == 336

View file

@ -1,10 +1,10 @@
#! /usr/bin/env python3 #! /usr/bin/env python3
import pathlib import pathlib
import sys
import re import re
import sys
from dataclasses import dataclass from dataclasses import dataclass
from pprint import pprint
@dataclass @dataclass
class Passport: class Passport:
@ -17,23 +17,26 @@ class Passport:
passportId: str | None passportId: str | None
countryId: str | None countryId: str | None
def regexUnwrap(match, group: int) -> str | None: def regexUnwrap(match, group: int) -> str | None:
return match[group] if match is not None else None return match[group] if match is not None else None
def parse(puzzle_input: str) -> list[Passport]: def parse(puzzle_input: str) -> list[Passport]:
"""Parse input""" """Parse input"""
rawRecords = [i.replace('\n', ' ') for i in puzzle_input.split('\n\n')] rawRecords = [i.replace("\n", " ") for i in puzzle_input.split("\n\n")]
records = [] records = []
for rawRecord in rawRecords: for rawRecord in rawRecords:
birthYear=re.search(r'byr:(\S+)', rawRecord) birthYear = re.search(r"byr:(\S+)", rawRecord)
issueYear=re.search(r'iyr:(\S+)', rawRecord) issueYear = re.search(r"iyr:(\S+)", rawRecord)
expirationYear=re.search(r'eyr:(\S+)', rawRecord) expirationYear = re.search(r"eyr:(\S+)", rawRecord)
height=re.search(r'hgt:(\S+)', rawRecord) height = re.search(r"hgt:(\S+)", rawRecord)
hairColor=re.search(r'hcl:(\S+)', rawRecord) hairColor = re.search(r"hcl:(\S+)", rawRecord)
eyeColor=re.search(r'ecl:(\S+)', rawRecord) eyeColor = re.search(r"ecl:(\S+)", rawRecord)
passportId=re.search(r'pid:(\S+)', rawRecord) passportId = re.search(r"pid:(\S+)", rawRecord)
countryId=re.search(r'cid:(\S+)', rawRecord) countryId = re.search(r"cid:(\S+)", rawRecord)
records.append(Passport( records.append(
Passport(
int(birthYear[1]) if birthYear is not None else None, int(birthYear[1]) if birthYear is not None else None,
int(issueYear[1]) if issueYear is not None else None, int(issueYear[1]) if issueYear is not None else None,
int(expirationYear[1]) if expirationYear is not None else None, int(expirationYear[1]) if expirationYear is not None else None,
@ -42,9 +45,11 @@ def parse(puzzle_input: str)->list[Passport]:
regexUnwrap(eyeColor, 1), regexUnwrap(eyeColor, 1),
regexUnwrap(passportId, 1), regexUnwrap(passportId, 1),
regexUnwrap(countryId, 1), regexUnwrap(countryId, 1),
)) )
)
return records return records
def lazyCheckPassport(passport: Passport) -> bool: def lazyCheckPassport(passport: Passport) -> bool:
return ( return (
passport.birthYear is not None passport.birthYear is not None
@ -56,54 +61,73 @@ def lazyCheckPassport(passport: Passport)->bool:
and passport.passportId is not None and passport.passportId is not None
) )
def part1(data): def part1(data):
"""Solve part 1""" """Solve part 1"""
return sum(1 for record in data if lazyCheckPassport(record)) return sum(1 for record in data if lazyCheckPassport(record))
def checkBirthYear(passport: Passport) -> bool: def checkBirthYear(passport: Passport) -> bool:
if passport.birthYear is None: return False if passport.birthYear is None:
return (1920<=passport.birthYear<=2002) return False
return 1920 <= passport.birthYear <= 2002
def checkIssueYear(passport: Passport) -> bool: def checkIssueYear(passport: Passport) -> bool:
if passport.issueYear is None: return False if passport.issueYear is None:
return (2010<=passport.issueYear<=2020) return False
return 2010 <= passport.issueYear <= 2020
def checkExpirationYear(passport: Passport) -> bool: def checkExpirationYear(passport: Passport) -> bool:
if passport.expirationYear is None: return False if passport.expirationYear is None:
return (2020<=passport.expirationYear<=2030) return False
return 2020 <= passport.expirationYear <= 2030
def checkHeight(passport: Passport) -> bool: def checkHeight(passport: Passport) -> bool:
if passport.height is None: return False if passport.height is None:
rematch = re.match(r'(\d+)((?:in)|(?:cm))', passport.height) return False
if rematch is None: return False rematch = re.match(r"(\d+)((?:in)|(?:cm))", passport.height)
if rematch is None:
return False
number = int(rematch.group(1)) number = int(rematch.group(1))
unit = rematch.group(2) unit = rematch.group(2)
if unit == 'in': if unit == "in":
return (59<=number<=76) return 59 <= number <= 76
else: else:
return (150<=number<=193) return 150 <= number <= 193
def checkHairColour(passport: Passport) -> bool: def checkHairColour(passport: Passport) -> bool:
if passport.hairColor is None: return False if passport.hairColor is None:
return (re.match(r'#[0123456789abcdef]{6}$', passport.hairColor) is not None) return False
return re.match(r"#[0123456789abcdef]{6}$", passport.hairColor) is not None
def checkEyeColour(passport: Passport) -> bool: def checkEyeColour(passport: Passport) -> bool:
if passport.eyeColor is None: return False if passport.eyeColor is None:
return (passport.eyeColor == 'amb' return False
or passport.eyeColor == 'blu' return (
or passport.eyeColor == 'brn' passport.eyeColor == "amb"
or passport.eyeColor == 'gry' or passport.eyeColor == "blu"
or passport.eyeColor == 'grn' or passport.eyeColor == "brn"
or passport.eyeColor == 'hzl' or passport.eyeColor == "gry"
or passport.eyeColor == 'oth' or passport.eyeColor == "grn"
or passport.eyeColor == "hzl"
or passport.eyeColor == "oth"
) )
def checkPassportId(passport: Passport) -> bool: def checkPassportId(passport: Passport) -> bool:
if passport.passportId is None: return False if passport.passportId is None:
return (re.match(r'[0-9]{9}$', passport.passportId) is not None) return False
return re.match(r"[0-9]{9}$", passport.passportId) is not None
def checkPassport(passport: Passport) -> bool: def checkPassport(passport: Passport) -> bool:
return (checkBirthYear(passport) return (
checkBirthYear(passport)
and checkIssueYear(passport) and checkIssueYear(passport)
and checkExpirationYear(passport) and checkExpirationYear(passport)
and checkHeight(passport) and checkHeight(passport)
@ -112,10 +136,12 @@ def checkPassport(passport: Passport)->bool:
and checkPassportId(passport) and checkPassportId(passport)
) )
def part2(data): def part2(data):
"""Solve part 2""" """Solve part 2"""
return sum(1 for record in data if checkPassport(record)) return sum(1 for record in data if checkPassport(record))
def solve(puzzle_input): def solve(puzzle_input):
"""Solve the puzzle for the given input""" """Solve the puzzle for the given input"""
data = parse(puzzle_input) data = parse(puzzle_input)
@ -124,6 +150,7 @@ def solve(puzzle_input):
return solution1, solution2 return solution1, solution2
if __name__ == "__main__": if __name__ == "__main__":
for path in sys.argv[1:]: for path in sys.argv[1:]:
print(f"{path}:") print(f"{path}:")

View file

@ -7,59 +7,67 @@ from day4 import Passport
PUZZLE_DIR = pathlib.Path(__file__).parent PUZZLE_DIR = pathlib.Path(__file__).parent
# these test fixtures setup the test, mainly by reading the filename into a string in this simple case. # these test fixtures setup the test, mainly by reading the filename into a string in this simple case.
@pytest.fixture @pytest.fixture
def example1(): def example():
puzzle_input = (PUZZLE_DIR / "example1").read_text().strip() puzzle_input = (PUZZLE_DIR / "example.txt").read_text().strip()
return aoc.parse(puzzle_input) return aoc.parse(puzzle_input)
@pytest.fixture
def example2():
puzzle_input = (PUZZLE_DIR / "example2").read_text().strip()
return aoc.parse(puzzle_input)
# @pytest.mark.skip(reason="Not implemented") def test_parse(example):
def test_parse_example1(example1):
"""Test that input is parsed properly""" """Test that input is parsed properly"""
assert example1 == [Passport(birthYear=1937, assert example == [
Passport(
birthYear=1937,
issueYear=2017, issueYear=2017,
expirationYear=2020, expirationYear=2020,
height='183cm', height="183cm",
hairColor='#fffffd', hairColor="#fffffd",
eyeColor='gry', eyeColor="gry",
passportId='860033327', passportId="860033327",
countryId='147'), countryId="147",
Passport(birthYear=1929, ),
Passport(
birthYear=1929,
issueYear=2013, issueYear=2013,
expirationYear=2023, expirationYear=2023,
height=None, height=None,
hairColor='#cfa07d', hairColor="#cfa07d",
eyeColor='amb', eyeColor="amb",
passportId='028048884', passportId="028048884",
countryId='350'), countryId="350",
Passport(birthYear=1931, ),
Passport(
birthYear=1931,
issueYear=2013, issueYear=2013,
expirationYear=2024, expirationYear=2024,
height='179cm', height="179cm",
hairColor='#ae17e1', hairColor="#ae17e1",
eyeColor='brn', eyeColor="brn",
passportId='760753108', passportId="760753108",
countryId=None), countryId=None,
Passport(birthYear=None, ),
Passport(
birthYear=None,
issueYear=2011, issueYear=2011,
expirationYear=2025, expirationYear=2025,
height='59in', height="59in",
hairColor='#cfa07d', hairColor="#cfa07d",
eyeColor='brn', eyeColor="brn",
passportId='166559648', passportId="166559648",
countryId=None)] countryId=None,
),
]
# @pytest.mark.skip(reason="Not implemented") # @pytest.mark.skip(reason="Not implemented")
def test_part1_example1(example1): def test_part1(example):
"""Test part 1 on example input""" """Test part 1 on example input"""
assert aoc.part1(example1) == 2 assert aoc.part1(example) == 2
# @pytest.mark.skip(reason="Not implemented") # @pytest.mark.skip(reason="Not implemented")
def test_part2_example2(example1): def test_part2(example):
"""Test part 2 on example input""" """Test part 2 on example input"""
assert aoc.part2(example1) == 2 assert aoc.part2(example) == 2

View file

@ -2,25 +2,29 @@
import pathlib import pathlib
import sys import sys
import re
from dataclasses import dataclass
from pprint import pprint
def row_to_int(string: str) -> int: def row_to_int(string: str) -> int:
return int(string.replace('F','0').replace('B','1'),2) return int(string.replace("F", "0").replace("B", "1"), 2)
def col_to_int(string: str) -> int: def col_to_int(string: str) -> int:
return int(string.replace('L','0').replace('R','1'),2) return int(string.replace("L", "0").replace("R", "1"), 2)
def parse(puzzle_input: str): def parse(puzzle_input: str):
"""Parse input""" """Parse input"""
rows_and_cols = [(row_to_int(x[:7]),col_to_int(x[7:])) for x in puzzle_input.splitlines()] rows_and_cols = [
(row_to_int(x[:7]), col_to_int(x[7:])) for x in puzzle_input.splitlines()
]
return set([x[0] * 8 + x[1] for x in rows_and_cols]) return set([x[0] * 8 + x[1] for x in rows_and_cols])
def part1(data): def part1(data):
"""Solve part 1""" """Solve part 1"""
return max(data) return max(data)
def part2(data): def part2(data):
"""Solve part 2""" """Solve part 2"""
for row in range(128): for row in range(128):
@ -30,6 +34,7 @@ def part2(data):
if (potentialID + 1 in data) and (potentialID - 1 in data): if (potentialID + 1 in data) and (potentialID - 1 in data):
return potentialID return potentialID
def solve(puzzle_input): def solve(puzzle_input):
"""Solve the puzzle for the given input""" """Solve the puzzle for the given input"""
data = parse(puzzle_input) data = parse(puzzle_input)
@ -38,6 +43,7 @@ def solve(puzzle_input):
return solution1, solution2 return solution1, solution2
if __name__ == "__main__": if __name__ == "__main__":
for path in sys.argv[1:]: for path in sys.argv[1:]:
print(f"{path}:") print(f"{path}:")

View file

@ -6,28 +6,24 @@ import day5 as aoc
PUZZLE_DIR = pathlib.Path(__file__).parent PUZZLE_DIR = pathlib.Path(__file__).parent
# these test fixtures setup the test, mainly by reading the filename into a string in this simple case. # these test fixtures setup the test, mainly by reading the filename into a string in this simple case.
@pytest.fixture @pytest.fixture
def example1(): def example():
puzzle_input = (PUZZLE_DIR / "example1").read_text().strip() puzzle_input = (PUZZLE_DIR / "example.txt").read_text().strip()
return aoc.parse(puzzle_input) return aoc.parse(puzzle_input)
@pytest.fixture
def example2():
puzzle_input = (PUZZLE_DIR / "input").read_text().strip()
return aoc.parse(puzzle_input)
# @pytest.mark.skip(reason="Not implemented") def test_parse(example):
def test_parse_example1(example1):
"""Test that input is parsed properly""" """Test that input is parsed properly"""
assert example1 == {119, 357, 567, 820} assert example == {119, 357, 567, 820}
# @pytest.mark.skip(reason="Not implemented")
def test_part1_example1(example1): def test_part1(example):
"""Test part 1 on example input""" """Test part 1 on example input"""
assert aoc.part1(example1) == 820 assert aoc.part1(example) == 820
# @pytest.mark.skip(reason="Not implemented")
def test_part2_example2(example2): def test_part2(example):
"""Test part 2 on example input""" """Test part 2 on example input"""
assert aoc.part2(example2) == 640 assert aoc.part2(example) == 640

View file

@ -2,15 +2,14 @@
import pathlib import pathlib
import sys import sys
import re
from dataclasses import dataclass
from pprint import pprint
def parse(puzzle_input: str): def parse(puzzle_input: str):
"""Parse input""" """Parse input"""
records = [[list(y) for y in x.splitlines()] for x in puzzle_input.split('\n\n')] records = [[list(y) for y in x.splitlines()] for x in puzzle_input.split("\n\n")]
return records return records
def part1(data): def part1(data):
"""Solve part 1""" """Solve part 1"""
results = [] results = []
@ -21,6 +20,7 @@ def part1(data):
results.append(len(result)) results.append(len(result))
return sum(results) return sum(results)
def part2(data): def part2(data):
"""Solve part 2""" """Solve part 2"""
results = [] results = []
@ -31,6 +31,7 @@ def part2(data):
results.append(len(result)) results.append(len(result))
return sum(results) return sum(results)
def solve(puzzle_input): def solve(puzzle_input):
"""Solve the puzzle for the given input""" """Solve the puzzle for the given input"""
data = parse(puzzle_input) data = parse(puzzle_input)
@ -39,6 +40,7 @@ def solve(puzzle_input):
return solution1, solution2 return solution1, solution2
if __name__ == "__main__": if __name__ == "__main__":
for path in sys.argv[1:]: for path in sys.argv[1:]:
print(f"{path}:") print(f"{path}:")

View file

@ -6,50 +6,33 @@ import day6 as aoc
PUZZLE_DIR = pathlib.Path(__file__).parent PUZZLE_DIR = pathlib.Path(__file__).parent
# these test fixtures setup the test, mainly by reading the filename into a string in this simple case. # these test fixtures setup the test, mainly by reading the filename into a string in this simple case.
@pytest.fixture @pytest.fixture
def example1(): def example():
puzzle_input = (PUZZLE_DIR / "example1").read_text().strip() puzzle_input = (PUZZLE_DIR / "example.txt").read_text().strip()
return aoc.parse(puzzle_input) return aoc.parse(puzzle_input)
@pytest.fixture
def example2():
puzzle_input = (PUZZLE_DIR / "example2").read_text().strip()
return aoc.parse(puzzle_input)
# @pytest.mark.skip(reason="Not implemented") # @pytest.mark.skip(reason="Not implemented")
def test_parse_example1(example1): def test_parse(example):
"""Test that input is parsed properly""" """Test that input is parsed properly"""
assert example1 == [ assert example == [
[ [["a", "b", "c"]],
['a', 'b', 'c'] [["a"], ["b"], ["c"]],
], [["a", "b"], ["a", "c"]],
[ [["a"], ["a"], ["a"], ["a"]],
['a'], [["b"]],
['b'],
['c']
],
[
['a', 'b'],
['a', 'c']
],
[
['a'],
['a'],
['a'],
['a']
],
[
['b']
]
] ]
# @pytest.mark.skip(reason="Not implemented") # @pytest.mark.skip(reason="Not implemented")
def test_part1_example1(example1): def test_part1(example):
"""Test part 1 on example input""" """Test part 1 on example input"""
assert aoc.part1(example1) == 11 assert aoc.part1(example) == 11
# @pytest.mark.skip(reason="Not implemented") # @pytest.mark.skip(reason="Not implemented")
def test_part2_example2(example1): def test_part2(example):
"""Test part 2 on example input""" """Test part 2 on example input"""
assert aoc.part2(example1) == 6 assert aoc.part2(example) == 6

View file

0
2020/template/input.txt Normal file
View file

View file

@ -2,9 +2,6 @@
import pathlib import pathlib
import sys import sys
import re
from dataclasses import dataclass
from pprint import pprint
def parse(puzzle_input: str): def parse(puzzle_input: str):
"""Parse input""" """Parse input"""

View file

@ -2,32 +2,27 @@
import pathlib import pathlib
import pytest import pytest
import template as aoc import temp as aoc
PUZZLE_DIR = pathlib.Path(__file__).parent PUZZLE_DIR = pathlib.Path(__file__).parent
#these test fixtures setup the test, mainly by reading the filename into a string in this simple case. #these test fixtures setup the test, mainly by reading the filename into a string in this simple case.
@pytest.fixture @pytest.fixture
def example1(): def example():
puzzle_input = (PUZZLE_DIR / "example1").read_text().strip() puzzle_input = (PUZZLE_DIR / "example.txt").read_text().strip()
return aoc.parse(puzzle_input)
@pytest.fixture
def example2():
puzzle_input = (PUZZLE_DIR / "example2").read_text().strip()
return aoc.parse(puzzle_input) return aoc.parse(puzzle_input)
@pytest.mark.skip(reason="Not implemented") @pytest.mark.skip(reason="Not implemented")
def test_parse_example1(example1): def test_parse_example(example):
"""Test that input is parsed properly""" """Test that input is parsed properly"""
assert example1 == ... assert example == ...
@pytest.mark.skip(reason="Not implemented") @pytest.mark.skip(reason="Not implemented")
def test_part1_example1(example1): def test_part1_example(example):
"""Test part 1 on example input""" """Test part 1 on example input"""
assert aoc.part1(example1) == ... assert aoc.part1(example) == ...
@pytest.mark.skip(reason="Not implemented") @pytest.mark.skip(reason="Not implemented")
def test_part2_example2(example2): def test_part2_example(example):
"""Test part 2 on example input""" """Test part 2 on example input"""
assert aoc.part2(example2) == ... assert aoc.part2(example) == ...