diff --git a/2023/day07.nim b/2023/day07.nim new file mode 100644 index 0000000..1270ca4 --- /dev/null +++ b/2023/day07.nim @@ -0,0 +1,82 @@ +import std/algorithm +import std/enumerate +import std/math +import std/sequtils +import std/sets +import std/strscans +import std/strutils +import std/sugar +import std/tables + +type Hand = tuple + cards: seq[int] + bid: int + +func parseCard(c: char): int = + case c: + of 'A': 14 + of 'K': 13 + of 'Q': 12 + of 'J': 11 + of 'T': 10 + of '9': 9 + of '8': 8 + of '7': 7 + of '6': 6 + of '5': 5 + of '4': 4 + of '3': 3 + of '2': 2 + else: 0 + +func parseHand(text: string): Hand = + let parts = text.strip.splitWhitespace + (parts[0].map(parseCard), parts[1].parseInt) + +func parseHands(text: string): seq[Hand] = + text.strip.splitLines.map(parseHand) + +func strength(hand: Hand): int = + let count = newCountTable(hand.cards) + + var counts: CountTable[int] + for v in values(count): + counts.inc v + + if counts[5] > 0: + return 7 + if counts[4] > 0: + return 6 + if counts[3] > 0: + if counts[2] > 0: + return 5 + else: + return 4 + if counts[2] == 2: + return 3 + if counts[2] == 1: + return 2 + return 1 + +func cmpHand(a: Hand, b: Hand): int = + let strength = cmp(a.strength, b.strength) + if strength != 0: + return strength + + for (aa, bb) in zip(a.cards, b.cards): + let card = cmp(aa, bb) + if card != 0: + return card + +proc dbg[T](v: T): T = (echo(v); v) + +proc part1(): int = + let text = readFile("input/day07.txt") + var hands = parseHands(text) + + hands.sort(cmpHand) + + for (rank, hand) in enumerate(hands): + result += (rank + 1) * hand.bid + +echo part1()