improve python algorithm on Day04
This commit is contained in:
parent
336d7fe657
commit
ead680fa94
@ -1,61 +1,64 @@
|
|||||||
def parse_card_data(line):
|
|
||||||
"""Parse a single line of card data into card number, winning numbers, and own numbers."""
|
|
||||||
try:
|
|
||||||
card_info, number_parts = line.split(":")
|
|
||||||
winning_part, own_part = number_parts.split("|")
|
|
||||||
card_number = "".join(filter(str.isdigit, card_info))
|
|
||||||
winning_numbers = set(map(int, winning_part.split()))
|
|
||||||
own_numbers = list(map(int, own_part.split()))
|
|
||||||
return int(card_number), winning_numbers, own_numbers
|
|
||||||
except ValueError as e:
|
|
||||||
raise ValueError(f"Error parsing line '{line}': {e}")
|
|
||||||
|
|
||||||
|
|
||||||
def calculate_matches(winning_numbers, own_numbers):
|
|
||||||
"""Calculate the number of matches for a single card."""
|
|
||||||
return sum(1 for number in own_numbers if number in winning_numbers)
|
|
||||||
|
|
||||||
|
|
||||||
def process_cards(file_path):
|
|
||||||
"""Process all cards in the given file and return the total number of cards."""
|
|
||||||
with open(file_path, "r") as file:
|
|
||||||
cards = [parse_card_data(line.strip()) for line in file]
|
|
||||||
|
|
||||||
i = 0
|
|
||||||
while i < len(cards):
|
|
||||||
card_number, winning_numbers, own_numbers = cards[i]
|
|
||||||
matches = calculate_matches(winning_numbers, own_numbers)
|
|
||||||
for _ in range(matches):
|
|
||||||
if card_number + 1 < len(cards):
|
|
||||||
cards.append(cards[card_number])
|
|
||||||
card_number += 1
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
return len(cards)
|
|
||||||
|
|
||||||
|
|
||||||
def test():
|
|
||||||
"""Run tests using the test.txt file."""
|
|
||||||
expected_result = 30 # Based on the given example
|
|
||||||
result = process_cards("../test.txt")
|
|
||||||
assert (
|
|
||||||
result == expected_result
|
|
||||||
), f"Test failed: Expected {expected_result}, got {result}"
|
|
||||||
print(f"Test passed: {result} cards")
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Main function to process the input file and display results."""
|
|
||||||
try:
|
try:
|
||||||
# Run tests first
|
# Run tests
|
||||||
test()
|
test_cards = parse_input("../test.txt")
|
||||||
|
assert part_a(test_cards) == 13, "Part A test failed"
|
||||||
|
assert part_b(test_cards) == 30, "Part B test failed"
|
||||||
|
print("All tests passed.")
|
||||||
|
|
||||||
# Process actual input
|
# Process main input
|
||||||
total_cards = process_cards("../input.txt")
|
main_cards = parse_input("../input.txt")
|
||||||
print(f"Total cards from input.txt: {total_cards}")
|
result = part_a(main_cards) + part_b(main_cards)
|
||||||
|
print(f"Puzzle result: {result}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"An error occurred: {e}")
|
print(f"Error: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
def part_a(cards):
|
||||||
|
"""Calculate the sum of scores for each card in part A"""
|
||||||
|
return sum(2 ** (card["wins"] - 1) for card in cards if card["wins"] > 0)
|
||||||
|
|
||||||
|
|
||||||
|
def part_b(cards):
|
||||||
|
"""Calculate the count for part B logic"""
|
||||||
|
queue = list(range(len(cards)))
|
||||||
|
visited = 0
|
||||||
|
|
||||||
|
while queue:
|
||||||
|
i = queue.pop()
|
||||||
|
visited += 1
|
||||||
|
|
||||||
|
card = cards[i]
|
||||||
|
if card["wins"] == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for j in range(card["wins"]):
|
||||||
|
queue.append(j + i + 1)
|
||||||
|
|
||||||
|
return visited
|
||||||
|
|
||||||
|
|
||||||
|
def parse_input(filename):
|
||||||
|
"""Read and parse input file into a list of card dictionaries"""
|
||||||
|
try:
|
||||||
|
with open(filename, "r") as file:
|
||||||
|
return [parse_card(line.strip()) for line in file]
|
||||||
|
except FileNotFoundError:
|
||||||
|
raise Exception(f"File not found: {filename}")
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception(f"Error reading file {filename}: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
def parse_card(line):
|
||||||
|
"""Parse a single line into a card dictionary"""
|
||||||
|
_, card_info = line.split(": ")
|
||||||
|
winning, scratch = card_info.split(" | ")
|
||||||
|
winning = set(map(int, winning.split()))
|
||||||
|
scratch = list(map(int, scratch.split()))
|
||||||
|
|
||||||
|
wins = sum(1 for num in scratch if num in winning)
|
||||||
|
return {"wins": wins}
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -22,13 +22,19 @@ fn main() {
|
|||||||
fn run_puzzle(file_path: &str) -> Result<usize, String> {
|
fn run_puzzle(file_path: &str) -> Result<usize, String> {
|
||||||
let input = fs::read_to_string(file_path).map_err(|e| e.to_string())?;
|
let input = fs::read_to_string(file_path).map_err(|e| e.to_string())?;
|
||||||
let springs = parse(&input);
|
let springs = parse(&input);
|
||||||
Ok(springs.iter().map(|s| s.clone().expand().arrangements()).sum())
|
Ok(springs
|
||||||
|
.iter()
|
||||||
|
.map(|s| s.clone().expand().arrangements())
|
||||||
|
.sum())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_puzzle(file_path: &str) -> Result<(), String> {
|
fn test_puzzle(file_path: &str) -> Result<(), String> {
|
||||||
let input = fs::read_to_string(file_path).map_err(|e| e.to_string())?;
|
let input = fs::read_to_string(file_path).map_err(|e| e.to_string())?;
|
||||||
let springs = parse(&input);
|
let springs = parse(&input);
|
||||||
let result = springs.iter().map(|s| s.clone().expand().arrangements()).sum::<usize>();
|
let result = springs
|
||||||
|
.iter()
|
||||||
|
.map(|s| s.clone().expand().arrangements())
|
||||||
|
.sum::<usize>();
|
||||||
assert_eq!(result, 525152, "Test failed!");
|
assert_eq!(result, 525152, "Test failed!");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -38,7 +44,10 @@ fn parse(input: &str) -> Vec<Spring> {
|
|||||||
.lines()
|
.lines()
|
||||||
.map(|line| {
|
.map(|line| {
|
||||||
let (field, springs) = line.split_once(' ').unwrap();
|
let (field, springs) = line.split_once(' ').unwrap();
|
||||||
let springs = springs.split(',').map(|s| s.parse().unwrap()).collect::<Vec<_>>();
|
let springs = springs
|
||||||
|
.split(',')
|
||||||
|
.map(|s| s.parse().unwrap())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
let mut field = field.chars().collect::<Vec<_>>();
|
let mut field = field.chars().collect::<Vec<_>>();
|
||||||
field.push('.');
|
field.push('.');
|
||||||
Spring { field, springs }
|
Spring { field, springs }
|
||||||
|
Loading…
Reference in New Issue
Block a user