112 lines
3 KiB
Python
112 lines
3 KiB
Python
|
#!/usr/bin/env python
|
||
|
# -*- encoding: utf-8; py-indent-offset: 4 -*-
|
||
|
|
||
|
# Author: Sebastian Mark
|
||
|
# CC-BY-SA (https://creativecommons.org/licenses/by-sa/4.0/deed.de)
|
||
|
|
||
|
# pylint: disable=missing-module-docstring,missing-function-docstring,consider-using-f-string
|
||
|
|
||
|
# Strength:
|
||
|
# Five of a kind: 6
|
||
|
# Four of a kind: 5
|
||
|
# Full house: 4
|
||
|
# Three of a kind: 3
|
||
|
# Two pair: 2
|
||
|
# One Pair: 1
|
||
|
# High Card: 0
|
||
|
|
||
|
|
||
|
import copy
|
||
|
from collections import Counter
|
||
|
|
||
|
|
||
|
def readinput():
|
||
|
with open("input", "r", encoding="utf-8") as file:
|
||
|
games = []
|
||
|
for line in file:
|
||
|
hand, bid = line.strip().split()
|
||
|
games.append({"hand": hand, "bid": int(bid), "strength": 0})
|
||
|
|
||
|
return games
|
||
|
|
||
|
|
||
|
# pylint: disable=inconsistent-return-statements,too-many-return-statements
|
||
|
def calc_strength(hand: str) -> int:
|
||
|
counter = Counter(hand)
|
||
|
highes_count = max(Counter(hand).values())
|
||
|
|
||
|
if highes_count == 5:
|
||
|
return 6 # Five of a kind
|
||
|
if highes_count == 4:
|
||
|
return 5 # Four of a kind
|
||
|
if highes_count == 3:
|
||
|
if len(counter) == 3:
|
||
|
return 3 # Three of a kind
|
||
|
return 4 # Full House
|
||
|
if highes_count == 2:
|
||
|
if len(set(hand)) == 3:
|
||
|
return 2 # Two Pair
|
||
|
return 1 # One Pair
|
||
|
if highes_count == 1:
|
||
|
return 0 # High Card
|
||
|
|
||
|
|
||
|
def bubblesort_reverse(games: dict) -> dict:
|
||
|
sorted_games = copy.deepcopy(games)
|
||
|
cards = "23456789TJQKA"
|
||
|
|
||
|
for n in range(len(sorted_games) - 1, 0, -1):
|
||
|
swapped = False
|
||
|
|
||
|
for i in range(n):
|
||
|
this_game = sorted_games[i]
|
||
|
next_game = sorted_games[i + 1]
|
||
|
|
||
|
# first sort key: strength (descending)
|
||
|
if this_game["strength"] > next_game["strength"]:
|
||
|
swapped = True
|
||
|
sorted_games[i], sorted_games[i + 1] = (
|
||
|
sorted_games[i + 1],
|
||
|
sorted_games[i],
|
||
|
)
|
||
|
|
||
|
if this_game["strength"] == next_game["strength"]:
|
||
|
# second sort key: cards (descending)
|
||
|
# compare each card,
|
||
|
# if first card is lower, take this order,
|
||
|
# otherwise swap games
|
||
|
for card_a, card_b in zip(this_game["hand"], next_game["hand"]):
|
||
|
if cards.index(card_a) < cards.index(card_b):
|
||
|
break
|
||
|
if cards.index(card_a) > cards.index(card_b):
|
||
|
swapped = True
|
||
|
sorted_games[i], sorted_games[i + 1] = (
|
||
|
sorted_games[i + 1],
|
||
|
sorted_games[i],
|
||
|
)
|
||
|
break
|
||
|
|
||
|
if not swapped:
|
||
|
break
|
||
|
|
||
|
return sorted_games
|
||
|
|
||
|
|
||
|
def main():
|
||
|
games = readinput()
|
||
|
|
||
|
# part 1
|
||
|
for game in games:
|
||
|
game["strength"] = calc_strength(game["hand"])
|
||
|
|
||
|
ranked_games = bubblesort_reverse(games)
|
||
|
|
||
|
winnings = 0
|
||
|
for i, game in enumerate(ranked_games):
|
||
|
winnings += game["bid"] * (i + 1)
|
||
|
print("Total winnings: %d" % winnings)
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
main()
|