From 8c73824980fdcafc6989a82a9a891bcdd7c38a5c Mon Sep 17 00:00:00 2001
From: Christopher Bohn <bohn@unl.edu>
Date: Mon, 4 Dec 2023 09:09:00 -0600
Subject: [PATCH] Completed 2023 Day 04

---
 2023/python/Day04.py | 61 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)
 create mode 100644 2023/python/Day04.py

diff --git a/2023/python/Day04.py b/2023/python/Day04.py
new file mode 100644
index 0000000..3451099
--- /dev/null
+++ b/2023/python/Day04.py
@@ -0,0 +1,61 @@
+from math import log2
+from typing import List, Tuple
+
+from ImportData import import_data
+
+day: int = 4
+
+sample_data: List[str] = '''
+Card 1: 41 48 83 86 17 | 83 86  6 31 17  9 48 53
+Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
+Card 3:  1 21 53 59 44 | 69 82 63 72 16 21 14  1
+Card 4: 41 92 73 84 69 | 59 84 76 51 58  5 54 83
+Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
+Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
+'''.split('\n')[1:-1]
+
+data_structure: type = List[Tuple[List[int], List[int]]]
+
+
+def parse_data(data: List[str]) -> data_structure:
+    cards: List[Tuple[List[int], List[int]]] = []
+    for card in data:
+        numbers: List[str] = card.split(':')[1].split('|')
+        winning_numbers: List[int] = [int(number_string) for number_string in numbers[0].strip().split()]
+        your_numbers: List[int] = [int(number_string) for number_string in numbers[1].strip().split()]
+        cards.append((winning_numbers, your_numbers))
+    return cards
+
+
+def get_score(card: Tuple[List[int], List[int]]) -> int:
+    score: int = 0
+    winning_numbers: List[int] = card[0]
+    your_numbers: List[int] = card[1]
+    for number in your_numbers:
+        if number in winning_numbers:
+            score = 1 if score == 0 else 2 * score
+    return score
+
+
+def part1(data: data_structure) -> int:
+    return sum([get_score(card) for card in data])
+
+
+def part2(data: data_structure) -> int:
+    copy_count: List[int] = [1 for _ in data]
+    number_of_cards = len(data)
+    for i in range(number_of_cards):
+        card: Tuple[List[int], List[int]] = data[i]
+        score: int = get_score(card)
+        if score > 0:
+            count: int = int(log2(score)) + 1  # kludgey
+            for j in range(i + 1, min(number_of_cards, i + count + 1)):
+                copy_count[j] += copy_count[i]
+    return sum(copy_count)
+
+
+if __name__ == '__main__':
+    production_ready = True
+    raw_data = import_data(day) if production_ready else sample_data
+    print(part1(parse_data(raw_data)))
+    print(part2(parse_data(raw_data)))
-- 
GitLab