2023.04
This commit is contained in:
parent
59019040ce
commit
639cca6ac3
4 changed files with 104 additions and 2 deletions
1
challenges/2023/04-scratchcards/README.md
Normal file
1
challenges/2023/04-scratchcards/README.md
Normal file
|
@ -0,0 +1 @@
|
|||
# [Day 4: Scratchcards](https://adventofcode.com/2023/day/4)
|
92
challenges/2023/04-scratchcards/main.py
Normal file
92
challenges/2023/04-scratchcards/main.py
Normal file
|
@ -0,0 +1,92 @@
|
|||
import sys
|
||||
from dataclasses import dataclass
|
||||
import functools
|
||||
from typing import Callable
|
||||
|
||||
|
||||
@dataclass()
|
||||
class Card:
|
||||
id: int
|
||||
winning: set[int]
|
||||
present: set[int]
|
||||
|
||||
def __init__(self, id: int):
|
||||
self.id = id
|
||||
self.winning = set()
|
||||
self.present = set()
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(self.id)
|
||||
|
||||
def get_winning_numbers(self) -> set[int]:
|
||||
return self.winning & self.present
|
||||
|
||||
def calculate_score(self) -> int:
|
||||
n = len(self.get_winning_numbers())
|
||||
score = 0 if n == 0 else 2**(n-1)
|
||||
return score
|
||||
|
||||
def get_prize_copies(self) -> set[int]:
|
||||
return set(map(lambda x: self.id + x + 1, range(len(self.get_winning_numbers()))))
|
||||
|
||||
|
||||
def make_card_counter(all_cards: list[Card]) -> Callable[[Card], int]:
|
||||
@functools.cache
|
||||
def fn(c: Card) -> int:
|
||||
acc = 1
|
||||
won = c.get_prize_copies()
|
||||
|
||||
for won_card in won:
|
||||
acc += fn(all_cards[won_card-1])
|
||||
|
||||
return acc
|
||||
return fn
|
||||
|
||||
|
||||
def parse(instr: str) -> list[Card]:
|
||||
res = []
|
||||
|
||||
for line in instr.splitlines():
|
||||
card_decl, numbers_sect = line.split(": ")
|
||||
|
||||
card = Card(int(card_decl.lstrip("Card ")))
|
||||
|
||||
winning, present = numbers_sect.split("|")
|
||||
card.winning = set([int(x) for x in winning.split(" ") if x != ""])
|
||||
card.present = set([int(x) for x in present.split(" ") if x != ""])
|
||||
|
||||
res.append(card)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def one(instr: str) -> int:
|
||||
cards = parse(instr)
|
||||
return sum(x.calculate_score() for x in cards)
|
||||
|
||||
|
||||
def two(instr: str) -> int:
|
||||
cards = parse(instr)
|
||||
acc = 0
|
||||
|
||||
count_fn = make_card_counter(cards)
|
||||
|
||||
for card in cards:
|
||||
acc += count_fn(card)
|
||||
return acc
|
||||
|
||||
|
||||
def _debug(*args, **kwargs):
|
||||
kwargs["file"] = sys.stderr
|
||||
print(*args, **kwargs)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2 or sys.argv[1] not in ["1", "2"]:
|
||||
print("Missing day argument", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
inp = sys.stdin.read().strip()
|
||||
if sys.argv[1] == "1":
|
||||
print(one(inp))
|
||||
else:
|
||||
print(two(inp))
|
8
challenges/2023/04-scratchcards/tests.json
Normal file
8
challenges/2023/04-scratchcards/tests.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"1": [
|
||||
{"is": "13", "input": "Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53\nCard 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19\nCard 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1\nCard 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83\nCard 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36\nCard 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11\n"}
|
||||
],
|
||||
"2": [
|
||||
{"is": "30", "input": "Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53\nCard 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19\nCard 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1\nCard 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83\nCard 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36\nCard 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11\n"}
|
||||
]
|
||||
}
|
|
@ -11,5 +11,6 @@ Solutions to the [2023 Advent of Code](https://adventofcode.com/2023).
|
|||
| Day | Status | Solutions | Notes |
|
||||
|-----|--------|-----------|-------|
|
||||
| 01 - Trebuchet?! | ★ ★ | Python | I never knew detecting numbers could be so confusingly tricky |
|
||||
| 01 - Cube Conundrum | ★ ★ | Python | Pleasingly straightforwards, though seems like it would be well suited to Haskell |
|
||||
| 01 - Gear Ratios | ★ ★ | Python | First coordinate grid of the year! |
|
||||
| 02 - Cube Conundrum | ★ ★ | Python | Pleasingly straightforwards, though seems like it would be well suited to Haskell |
|
||||
| 03 - Gear Ratios | ★ ★ | Python | First coordinate grid of the year! |
|
||||
| 04 - Scratchcards | ★ ★ | Python | First flawed initial grok of the year |
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue