Files
AdventOfCode2025/src/solutions/day03.rs
T
luke-else d03f97e641
Continuous integration / Check (push) Successful in 39s
Continuous integration / Test Suite (push) Failing after 42s
Continuous integration / Rustfmt (push) Successful in 27s
Continuous integration / Clippy (push) Successful in 39s
Continuous integration / build (push) Successful in 41s
feat: Ready for day 4, clippy has been satisfied :)
2025-12-07 21:31:33 +00:00

146 lines
3.8 KiB
Rust

use super::Solution;
pub struct Day03 {}
impl Solution for Day03 {
fn part1(
&self,
input: &mut Vec<String>,
) -> Result<Box<dyn std::fmt::Display>, Box<dyn std::error::Error>> {
let battery_banks: Vec<Vec<u8>> = self.collect_banks(input);
let batteries = 2;
let mut total: u64 = 0;
for bank in battery_banks {
total += self.calculate_joltage(batteries, &bank);
}
Ok(Box::new(total))
}
fn part2(
&self,
input: &mut Vec<String>,
) -> Result<Box<dyn std::fmt::Display>, Box<dyn std::error::Error>> {
let battery_banks: Vec<Vec<u8>> = self.collect_banks(input);
let batteries = 12;
let mut total: u64 = 0;
for bank in battery_banks {
total += self.calculate_joltage(batteries, &bank);
}
Ok(Box::new(total))
}
fn get_day(&self) -> u8 {
3
}
}
impl Day03 {
/// Collect battery banks from input
///
/// # Arguments
/// * `arr` - Vec of strings representing battery banks
///
/// # Returns
/// * `Vec<Vec<u8>>` - Vector of battery banks as vectors of u8s
fn collect_banks(&self, arr: &Vec<String>) -> Vec<Vec<u8>> {
let mut battery_banks: Vec<Vec<u8>> = vec![];
// Maps Battery banks into vec of u8s
for bank in arr {
let n = bank
.as_str()
.chars()
.filter_map(|c| c.to_digit(10))
.map(|d| d as u8)
.collect();
battery_banks.push(n);
}
battery_banks
}
/// Scan a slice of u8s to find the max int,
/// (including its location) within the slice
fn get_max(&self, arr: &[u8]) -> (u8, usize) {
let mut max: u8 = 0;
let mut max_idx: usize = 0;
for (idx, i) in arr.iter().enumerate() {
if *i > max {
max = *i;
max_idx = idx;
}
}
(max, max_idx)
}
/// Calculate the joltage given a number of batteries and a bank
///
/// # Arguments
/// * `num_batteries` - Number of batteries to consider
/// * `bank` - Slice of u8s representing the battery bank
///
/// # Returns
/// * `u64` - The calculated joltage
fn calculate_joltage(&self, num_batteries: u8, bank: &[u8]) -> u64 {
// Find the highest val in the avilable bank slice
// leaving enough room for the remaining batteries
let (max_val, max_idx) = self.get_max(&bank[0..=(bank.len() - (num_batteries as usize))]);
// Base case: only one battery left to place
if num_batteries == 1 {
return max_val as u64;
}
// Otherwise, place the battery and recurse
(max_val as u64) * 10u64.pow((num_batteries - 1) as u32)
+ self.calculate_joltage(num_batteries - 1, &bank[max_idx + 1..bank.len()])
}
}
/// Test from puzzle input
#[cfg(test)]
mod test {
use super::*;
use crate::*;
#[test]
fn part1() {
let challenge = day03::Day03 {};
//Complete the Challenge
let answer = challenge
.part1(
utils::get_input(challenge.get_day(), utils::InputType::Test1)
.unwrap()
.as_mut(),
)
.unwrap()
.to_string();
assert_eq!(answer, "357");
}
#[test]
fn part2() {
let challenge = day03::Day03 {};
//Complete the Challenge
let answer = challenge
.part2(
utils::get_input(challenge.get_day(), utils::InputType::Test2)
.unwrap()
.as_mut(),
)
.unwrap()
.to_string();
assert_eq!(answer, "3121910778619");
}
}