From ead680fa9435cbe97b4368f1ec15e7a9f450cf77 Mon Sep 17 00:00:00 2001 From: wieerwill Date: Tue, 12 Dec 2023 21:13:27 +0100 Subject: [PATCH] improve python algorithm on Day04 --- Day04/python/solution2.py | 109 ++++++++++++++++++++------------------ Day04/rust/src/main.rs | 2 +- Day12/rust/src/main.rs | 15 ++++-- 3 files changed, 69 insertions(+), 57 deletions(-) diff --git a/Day04/python/solution2.py b/Day04/python/solution2.py index 7e0e50b..038dffd 100644 --- a/Day04/python/solution2.py +++ b/Day04/python/solution2.py @@ -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(): - """Main function to process the input file and display results.""" try: - # Run tests first - test() + # Run tests + 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 - total_cards = process_cards("../input.txt") - print(f"Total cards from input.txt: {total_cards}") + # Process main input + main_cards = parse_input("../input.txt") + result = part_a(main_cards) + part_b(main_cards) + print(f"Puzzle result: {result}") 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__": diff --git a/Day04/rust/src/main.rs b/Day04/rust/src/main.rs index 3e6f39e..a72cf4b 100644 --- a/Day04/rust/src/main.rs +++ b/Day04/rust/src/main.rs @@ -88,7 +88,7 @@ fn parse(input: &str) -> Vec { let winning = parse(winning); let scratch = parse(scratch); - + Card { wins: scratch.iter().filter(|x| winning.contains(x)).count() as u8, } diff --git a/Day12/rust/src/main.rs b/Day12/rust/src/main.rs index de6a772..49d3bc2 100644 --- a/Day12/rust/src/main.rs +++ b/Day12/rust/src/main.rs @@ -22,13 +22,19 @@ fn main() { fn run_puzzle(file_path: &str) -> Result { let input = fs::read_to_string(file_path).map_err(|e| e.to_string())?; 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> { let input = fs::read_to_string(file_path).map_err(|e| e.to_string())?; let springs = parse(&input); - let result = springs.iter().map(|s| s.clone().expand().arrangements()).sum::(); + let result = springs + .iter() + .map(|s| s.clone().expand().arrangements()) + .sum::(); assert_eq!(result, 525152, "Test failed!"); Ok(()) } @@ -38,7 +44,10 @@ fn parse(input: &str) -> Vec { .lines() .map(|line| { let (field, springs) = line.split_once(' ').unwrap(); - let springs = springs.split(',').map(|s| s.parse().unwrap()).collect::>(); + let springs = springs + .split(',') + .map(|s| s.parse().unwrap()) + .collect::>(); let mut field = field.chars().collect::>(); field.push('.'); Spring { field, springs }