Advent of Code 2023 - Day 04
I'ts that time of year again, the Advent of Code! I'm completing the challenges this year using Rust 🦀 Day 4 was really interesting!
I'll be posting them here, just to document how I'm solving each challenge, and I highly encourage you to check them out before reading my solutions!
Here's the Day 4 Challenge
BTW: Complete Part 1 to have access to Part 2 😉
Solution for Part 1
use std::fs::File;
use std::io::{BufRead, BufReader, Lines, Result};
use std::path::Path;
use std::str::FromStr;
fn main() {
let input_file_path = "path_to_input_file";
let mut curr_sum = 0;
let iterator = for_each_line(input_file_path)
.unwrap_or_else(|_| panic!("Could not find input file {}", input_file_path));
for line in iterator.flatten() {
if let Some((_, remainder)) = line.split_once(':') {
if let Some((winning_numbers, elf_numbers)) = remainder.trim().split_once('|') {
let mut score = 0;
let winning_numbers: Vec<i32> = parse_list(winning_numbers.trim());
let elf_numbers: Vec<i32> = parse_list(elf_numbers.trim());
for winning_number in winning_numbers {
if elf_numbers.contains(&winning_number) {
if score == 0 {
score = 1;
} else {
score = score * 2;
}
}
}
curr_sum += score;
}
}
}
println!("Score of entire pile: {}", curr_sum);
}
fn parse_list(list_as_str: &str) -> Vec<i32> {
return list_as_str.split(' ').filter(|str| !str.is_empty()).map(|str| {
i32::from_str(str.trim()).unwrap_or_else(|_| panic!("{} is not a valid i32.", str))
}).collect();
}
fn for_each_line<P: AsRef<Path>>(filename: P) -> Result<Lines<BufReader<File>>> {
let file = File::open(filename)?;
Ok(BufReader::new(file).lines())
}
Solution for Part 2
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufRead, BufReader, Lines, Result};
use std::path::Path;
use std::str::FromStr;
fn main() {
let input_file_path = "path_to_your_input_file";
let mut curr_sum = 0;
let iterator = for_each_line(input_file_path)
.unwrap_or_else(|_| panic!("Could not find input file {}", input_file_path));
let mut map_of_scratchcards: HashMap<i32, i32> = HashMap::new();
for line in iterator.flatten() {
let (card_id, remainder) = line.split_once(':').unwrap();
let (_, card_id) = card_id.split_once(' ').unwrap();
let card_id = i32::from_str(card_id.trim())
.unwrap_or_else(|_| panic!("{} is not a valid i32 for card name", card_id));
map_of_scratchcards.entry(card_id).or_insert(1);
let (winning_numbers, elf_numbers) = remainder.trim()
.split_once('|').unwrap();
let mut matching_numbers = 0;
let winning_numbers: Vec<i32> = parse_list(winning_numbers.trim());
let elf_numbers: Vec<i32> = parse_list(elf_numbers.trim());
for winning_number in winning_numbers {
if elf_numbers.contains(&winning_number) {
matching_numbers += 1;
}
}
let current_cards = *map_of_scratchcards.entry(card_id).or_insert(1);
for _ in (0..current_cards).rev() {
for future_card in card_id+1..=card_id+matching_numbers {
map_of_scratchcards.entry(future_card).or_insert(1);
let curr_card_amount = map_of_scratchcards.get(&future_card).unwrap();
map_of_scratchcards.insert(future_card, curr_card_amount + 1);
}
curr_sum += 1;
}
}
println!("Sum of all winning cards: {}", curr_sum);
}
fn parse_list(list_as_str: &str) -> Vec<i32> {
return list_as_str.split(' ').filter(|str| !str.is_empty()).map(|str| {
i32::from_str(str.trim()).unwrap_or_else(|_| panic!("{} is not a valid i32.", str))
}).collect();
}
fn for_each_line<P: AsRef<Path>>(filename: P) -> Result<Lines<BufReader<File>>> {
let file = File::open(filename)?;
Ok(BufReader::new(file).lines())
}