Skip to content

Commit

Permalink
AoC 2023 Day 7 Part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
pareronia committed Dec 7, 2023
1 parent c1f7263 commit fe29fb6
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 28 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<!-- @BEGIN:ImplementationsTable:2023@ -->
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| ---| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| python3 | [](src/main/python/AoC2023_01.py) | [](src/main/python/AoC2023_02.py) | [](src/main/python/AoC2023_03.py) | [](src/main/python/AoC2023_04.py) | [](src/main/python/AoC2023_05.py) | [](src/main/python/AoC2023_06.py) | | | | | | | | | | | | | | | | | | | |
| python3 | [](src/main/python/AoC2023_01.py) | [](src/main/python/AoC2023_02.py) | [](src/main/python/AoC2023_03.py) | [](src/main/python/AoC2023_04.py) | [](src/main/python/AoC2023_05.py) | [](src/main/python/AoC2023_06.py) | [](src/main/python/AoC2023_07.py) | | | | | | | | | | | | | | | | | | |
| java | [](src/main/java/AoC2023_01.java) | [](src/main/java/AoC2023_02.java) | [](src/main/java/AoC2023_03.java) | [](src/main/java/AoC2023_04.java) | | [](src/main/java/AoC2023_06.java) | | | | | | | | | | | | | | | | | | | |
| bash | | | | | | | | | | | | | | | | | | | | | | | | | |
| c++ | | | | | | | | | | | | | | | | | | | | | | | | | |
Expand Down
141 changes: 114 additions & 27 deletions src/main/python/AoC2023_07.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from aoc.common import InputData
from aoc.common import SolutionBase
from aoc.common import aoc_samples
from aoc.common import log

TEST = """\
32T3K 765
Expand All @@ -24,6 +23,16 @@
"""

VALUES = {
"5_KIND": 1000,
"4_KIND": 900,
"FULL_HOUSE": 800,
"3_KIND": 700,
"2_PAIR": 600,
"1_PAIR": 500,
"HIGH_CARD": 400,
}

STRENGTH = {
"2": 2,
"3": 3,
"4": 4,
Expand All @@ -40,6 +49,29 @@
}


def _value(s: str) -> str:
c = Counter(s)
if 5 in c.values():
type = "5_KIND"
elif 4 in c.values():
type = "4_KIND"
elif sorted(c.values()) == [2, 3]:
type = "FULL_HOUSE"
elif 3 in c.values():
type = "3_KIND"
elif sorted(c.values()) == [1, 2, 2]:
type = "2_PAIR"
elif 2 in c.values():
type = "1_PAIR"
else:
type = "HIGH_CARD"
return type


def _strength(s: str) -> list[int]:
return [STRENGTH[s[i]] if s[i] != "J" else 1 for i in range(5)]


@total_ordering
class Hand(NamedTuple):
cards: str
Expand All @@ -50,40 +82,79 @@ def from_input(cls, line: str) -> Hand:
c, b = line.split()
return Hand(c, int(b))

def value(self) -> int:
c = Counter(self.cards)
if 5 in c.values():
type = 1000
elif 4 in c.values():
type = 900
elif sorted(c.values()) == [2, 3]:
type = 800
elif 3 in c.values():
type = 700
elif sorted(c.values()) == [1, 2, 2]:
type = 600
elif 2 in c.values():
type = 500
else:
type = 400
return type
def value(self) -> str:
return _value(self.cards)

# def value(self) -> str:
# c = Counter(self.cards)
# if 5 in c.values():
# type = "5_KIND"
# elif 4 in c.values():
# if c.get("J") == 1:
# type = "5_KIND"
# else:
# type = "4_KIND"
# elif sorted(c.values()) == [2, 3]:
# if c.get("J") == 2 or c.get("J") == 3:
# type = "5_KIND"
# else:
# type = "FULL_HOUSE"
# elif 3 in c.values():
# if c.get("J") == 1:
# type = "4_KIND"
# elif c.get("J") == 2:
# type = "5_KIND"
# else:
# type = "3_KIND"
# elif sorted(c.values()) == [1, 2, 2]:
# if c.get("J") == 1:
# type = "FULL_HOUSE"
# elif c.get("J") == 2:
# type = "4_KIND"
# else:
# type = "2_PAIR"
# elif 2 in c.values():
# if c.get("J") == 1:
# type = "3_KIND"
# elif c.get("J") == 2:
# type = "4_KIND"
# else:
# type = "1_PAIR"
# else:
# if c.get("J") == 1:
# type = "1_PAIR"
# else:
# type = "HIGH_CARD"
# return type

def strength(self) -> list[int]:
return [VALUES[self.cards[i]] for i in range(5)]
return [STRENGTH[self.cards[i]] for i in range(5)]

def __eq__(self, other: Hand) -> bool:
if self.value() == other.value():
if VALUES[self.value()] == VALUES[other.value()]:
return self.strength() == other.strength()
else:
return False

def __lt__(self, other: Hand) -> bool:
if self.value() < other.value():
if VALUES[self.value()] < VALUES[other.value()]:
return True
elif self.value() == other.value():
elif VALUES[self.value()] == VALUES[other.value()]:
return self.strength() < other.strength()
return False

def all_possible(self) -> list[str]:
if "J" not in self.cards:
return [self.cards]
ans = []
for i, c in enumerate(self.cards):
if c == "J":
for x in "23456789TQKA":
ans.append(
"".join(x if _ == "J" else _ for _ in self.cards)
)
return ans


Input = list[Hand]
Output1 = int
Expand All @@ -96,18 +167,34 @@ def parse_input(self, input_data: InputData) -> Input:

def part_1(self, hands: Input) -> Output1:
hands = sorted(hands)
log(hands)
ans = sum((i + 1) * hands[i].bid for i in range(len(hands)))
log(ans)
return ans

def part_2(self, input: Input) -> Output2:
return 0
def part_2(self, hands: Input) -> Output2:
# for hand in hands:
# assert not (hand.value() == "HIGH_CARD" and "J" in hand.cards)
# assert not (hand.value() == "1_PAIR" and hand.cards.count("J") > 1)
# assert not (hand.value() == "2_PAIR" and "J" in hand.cards)
new_hands = []
for h in hands:
p = h.all_possible()
new_hands.append(
(
max(p, key=lambda x: (VALUES[_value(x)])),
h.cards,
h.bid,
)
)
new_hands.sort(
key=lambda hand: (VALUES[_value(hand[0])], _strength(hand[1]))
)
ans = sum((i + 1) * new_hands[i][2] for i in range(len(new_hands)))
return ans

@aoc_samples(
(
("part_1", TEST, 6440),
# ("part_2", TEST, "TODO"),
("part_2", TEST, 5905),
)
)
def samples(self) -> None:
Expand Down

0 comments on commit fe29fb6

Please sign in to comment.