Add solution for "Day 2: Gift Shop", part 1
This commit is contained in:
+1
-1
@@ -3,7 +3,7 @@ use advent_of_code_2025::solvers;
|
|||||||
fn main() {
|
fn main() {
|
||||||
println!("### Advent of Code 2025 ###\n");
|
println!("### Advent of Code 2025 ###\n");
|
||||||
solvers::run(solvers::secret_entrance::SecretEntrance {});
|
solvers::run(solvers::secret_entrance::SecretEntrance {});
|
||||||
// GiftShop
|
solvers::run(solvers::gift_shop::GiftShop {});
|
||||||
// Lobby
|
// Lobby
|
||||||
solvers::run(solvers::printing_department::PrintingDepartment {});
|
solvers::run(solvers::printing_department::PrintingDepartment {});
|
||||||
solvers::run(solvers::cafeteria::Cafeteria {});
|
solvers::run(solvers::cafeteria::Cafeteria {});
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use std::path;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
pub mod cafeteria;
|
pub mod cafeteria;
|
||||||
|
pub mod gift_shop;
|
||||||
pub mod movie_theater;
|
pub mod movie_theater;
|
||||||
pub mod playground;
|
pub mod playground;
|
||||||
pub mod printing_department;
|
pub mod printing_department;
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
use crate::solvers::Solver;
|
||||||
|
use std::io::BufRead;
|
||||||
|
|
||||||
|
pub struct GiftShop {}
|
||||||
|
|
||||||
|
impl GiftShop {
|
||||||
|
const RANGES_SPLIT_CHAR: char = ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Solver for GiftShop {
|
||||||
|
const PUZZLE_INDEX: u8 = 2;
|
||||||
|
const PUZZLE_NAME: &'static str = "Gift Shop";
|
||||||
|
|
||||||
|
fn process_data<R: BufRead>(&self, reader: R) -> (u64, u64) {
|
||||||
|
let mut invalid_ids_sum = 0;
|
||||||
|
for line in reader.lines().map_while(Result::ok) {
|
||||||
|
let ranges = line.split(Self::RANGES_SPLIT_CHAR);
|
||||||
|
for range in ranges {
|
||||||
|
if let Some(range) = Range::try_from_str(range) {
|
||||||
|
invalid_ids_sum += range.sum_invalid_ids();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(invalid_ids_sum, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Range {
|
||||||
|
first: u64,
|
||||||
|
last: u64,
|
||||||
|
digits: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Range {
|
||||||
|
const SPLIT_CHAR: char = '-';
|
||||||
|
|
||||||
|
fn try_from_str(s: &str) -> Option<Self> {
|
||||||
|
// Parses first and last IDs from range string.
|
||||||
|
let ids: Vec<u64> = s
|
||||||
|
.split(Self::SPLIT_CHAR)
|
||||||
|
.map(|s| {
|
||||||
|
s.parse()
|
||||||
|
.expect("could not parse id range, must be integers")
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
assert_eq!(ids.len(), 2, "could not parse id range, must be two values");
|
||||||
|
|
||||||
|
// Calculates the logs of first and last IDs and checks the size of the range.
|
||||||
|
let (a_log, b_log) = (ids[0].ilog10(), ids[1].ilog10());
|
||||||
|
assert!(b_log < a_log + 2, "id range is unexpectedly large");
|
||||||
|
|
||||||
|
if a_log == b_log {
|
||||||
|
if a_log % 2 == 0 {
|
||||||
|
// Skips this range if the first and last IDs are both odd.
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(Range {
|
||||||
|
first: ids[0],
|
||||||
|
last: ids[1],
|
||||||
|
digits: a_log + 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if a_log % 2 == 0 {
|
||||||
|
// First ID becomes the smallest ID with a number of digits equal to 'a_log + 2'.
|
||||||
|
Some(Range {
|
||||||
|
first: 10_u64.pow(b_log),
|
||||||
|
last: ids[1],
|
||||||
|
digits: b_log + 1,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// Last ID becomes the largest ID with a number of digits equal to 'a_log + 1'.
|
||||||
|
Some(Range {
|
||||||
|
first: ids[0],
|
||||||
|
last: 10_u64.pow(b_log) - 1,
|
||||||
|
digits: b_log,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sum_invalid_ids(&self) -> u64 {
|
||||||
|
let power10 = 10_u64.pow(self.digits / 2);
|
||||||
|
let first_left = self.first / power10;
|
||||||
|
let last_left = self.last / power10;
|
||||||
|
let first_right = self.first % power10;
|
||||||
|
let last_right = self.last % power10;
|
||||||
|
let mut sum = 0;
|
||||||
|
// Checks, for a given range AB-CD, whether invalid ID AA is in the range.
|
||||||
|
if first_left >= first_right && (first_left < last_left || first_left <= last_right) {
|
||||||
|
sum += first_left;
|
||||||
|
}
|
||||||
|
// Calculates the sum of the in-between invalid IDs directly without loop, but we need to
|
||||||
|
// explicitly check whether there are any values.
|
||||||
|
if first_left + 1 <= last_left {
|
||||||
|
sum += (first_left + last_left) * (last_left - first_left - 1) / 2;
|
||||||
|
}
|
||||||
|
// Checks, for a given range AB-CD, whether invalid ID CC is in the range.
|
||||||
|
if first_left != last_left && last_left <= last_right {
|
||||||
|
sum += last_left;
|
||||||
|
}
|
||||||
|
sum * (power10 + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,14 @@ fn secret_entrance() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn gift_shop() {
|
||||||
|
assert_eq!(
|
||||||
|
Ok((1227775554, 0)),
|
||||||
|
solvers::run_solver(solvers::gift_shop::GiftShop {}, &EXAMPLE_PATHS)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn printing_department() {
|
fn printing_department() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
@@ -11,6 +11,14 @@ fn secret_entrance() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn gift_shop() {
|
||||||
|
assert_eq!(
|
||||||
|
Ok((38158151648, 0)),
|
||||||
|
solvers::run_solver(solvers::gift_shop::GiftShop {}, &solvers::DATA_PATHS)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn printing_department() {
|
fn printing_department() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
Reference in New Issue
Block a user