day 3 (help)

This commit is contained in:
2025-12-03 21:59:41 +04:00
parent 78664852d3
commit ccd8b3556c
5 changed files with 345 additions and 0 deletions

12
src/bin/day03.rs Normal file
View File

@@ -0,0 +1,12 @@
use aoc_2025::day03;
use color_eyre::Report;
fn main() -> Result<(), Report> {
color_eyre::install()?;
let data = day03::data("inputs/day03.txt")?;
let code1 = day03::part1(&data)?;
let code2 = day03::part2(&data)?;
println!("code1: {code1}");
println!("code2: {code2}");
Ok(())
}

128
src/day03.rs Normal file
View File

@@ -0,0 +1,128 @@
use color_eyre::{Report, eyre::ContextCompat};
use std::{
fs::File,
io::{self, BufRead, BufReader},
};
const BATTERIES: usize = 12;
pub struct BatteryBank {
biggest_sorted: Vec<u8>,
batteries: Vec<u8>,
}
impl TryFrom<String> for BatteryBank {
type Error = Report;
fn try_from(value: String) -> Result<Self, Self::Error> {
let digits = value
.chars()
.map(|v| v.to_string().parse::<u8>())
.collect::<Result<Vec<u8>, std::num::ParseIntError>>()?;
let mut sorted_list = digits.clone();
sorted_list.sort();
sorted_list.reverse();
sorted_list.dedup();
Ok(Self {
batteries: digits,
biggest_sorted: sorted_list,
})
}
}
impl BatteryBank {
fn try_value_part1(&self, index: usize) -> Result<Option<u64>, Report> {
let value = self.biggest_sorted.get(index).context("out of bounds")?;
let index = self.batteries.iter().position(|x| x == value).unwrap();
let (_, split) = self.batteries.split_at(index + 1);
if split.is_empty() {
return Ok(None);
}
let mut split = split.to_vec();
split.sort();
let biggest = split.last().unwrap();
Ok(Some((value * 10) as u64 + *biggest as u64))
}
fn part1(&self) -> Result<u64, Report> {
let len = self.biggest_sorted.len();
for i in 0..len {
if let Some(v) = self.try_value_part1(i)? {
return Ok(v);
}
}
Ok(0)
}
fn part2(&self) -> Result<u64, Report> {
let mut progress = vec![];
let len = self.batteries.len();
for (i, value) in self.batteries.iter().enumerate() {
while let Some(last) = progress.last()
&& *last < value
&& progress.len() + (len - i) > BATTERIES
{
progress.pop();
}
if progress.len() < BATTERIES {
progress.push(value);
}
}
println!("value: {progress:?} {}", progress.len());
let mut num = 0;
for (i, v) in progress.iter().enumerate() {
num += **v as u64 * 10_u64.pow(progress.len() as u32 - i as u32 - 1);
}
// println!("{num}");
Ok(num)
}
}
pub fn part1(data: &[BatteryBank]) -> Result<u64, Report> {
Ok(data
.iter()
.map(|v| v.part1())
.collect::<Result<Vec<u64>, Report>>()?
.iter()
.sum::<u64>())
}
pub fn part2(data: &[BatteryBank]) -> Result<u64, Report> {
// let first = BatteryBank::try_from(String::from("818181911112111"))?.part2()?;
Ok(data
.iter()
.map(|v| v.part2())
.collect::<Result<Vec<u64>, Report>>()?
.iter()
.sum::<u64>())
}
pub fn data(filepath: &str) -> Result<Vec<BatteryBank>, Report> {
let file = File::open(filepath)?;
let bufreader = BufReader::new(file);
let banks = bufreader
.lines()
.collect::<Result<Vec<String>, io::Error>>()?
.into_iter()
.map(BatteryBank::try_from)
.collect::<Result<Vec<BatteryBank>, Report>>()?;
Ok(banks)
}
#[cfg(test)]
mod tests {
use super::*;
use criterion::Criterion;
use criterion_macro::criterion;
#[criterion]
fn bench_part1(b: &mut Criterion) {
let data = data("inputs/day03.txt").unwrap();
b.bench_function("day03-part1", |b| b.iter(|| part1(&data).unwrap()));
}
#[criterion]
fn bench_part2(b: &mut Criterion) {
let data = data("inputs/day03.txt").unwrap();
b.bench_function("day03-part2", |b| b.iter(|| part2(&data).unwrap()));
}
}

View File

@@ -4,3 +4,4 @@
extern crate test;
pub mod day01;
pub mod day02;
pub mod day03;