Skip to content

Commit

Permalink
Year 2015: Day 17
Browse files Browse the repository at this point in the history
  • Loading branch information
joshleaves committed Mar 1, 2024
1 parent 3231160 commit 3160670
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 20 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ Of note:
- The changelog 2015.5.2 has been rewritten from each commit content.
- This file may be amended entirely in the future to adhere to the [GNU Changelog style](https://www.gnu.org/prep/standards/html_node/Style-of-Change-Logs.html#Style-of-Change-Logs)

## [2015.17.1]
### Added
- Solved [exercice for 2015, day 17](src/year_2015/day_17.rs).


## [2015.16.1]
### Added
- Solved [exercice for 2015, day 16](src/year_2015/day_16.rs).
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "advent-rs"
version = "2015.16.1"
version = "2015.17.1"
edition = "2021"
authors = ["Arnaud 'red' Rouyer"]
readme = "README.md"
Expand Down
25 changes: 25 additions & 0 deletions NOTES_2015.md
Original file line number Diff line number Diff line change
Expand Up @@ -475,3 +475,28 @@ year_2015::day_16/year_2015::day_16_v2
</details>
This one was already easy in Ruby, and it's just as easy in Rust.

## Day 17: No Such Thing as Too Much

<details>
<summary>📊Tests and benchmarks</summary>

```
test year_2015::day_17::tests::works_with_samples_v1 ... ok
test year_2015::day_17::tests::works_with_samples_v2 ... ok
test year_2015_day_17 ... ok
year_2015::day_17/year_2015::day_17_v1
time: [9.3768 ms 9.3931 ms 9.4143 ms]
year_2015::day_17/year_2015::day_17_v2
time: [9.3911 ms 9.4139 ms 9.4419 ms]
```
</details>

<details>
<summary>Ruby version comments</summary>

> Nothing really complicated here, or that we haven't seen yet.
</details>
Heh, I'm getting to used to this stuff that it compiled on the second try, and passed the tests on the second. Reworking my Ruby algorithm into Ruby wasn't complicated either.
11 changes: 11 additions & 0 deletions benches/advent-bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use advent_rs::year_2015::day_13;
use advent_rs::year_2015::day_14;
use advent_rs::year_2015::day_15;
use advent_rs::year_2015::day_16;
use advent_rs::year_2015::day_17;
use criterion::{black_box, criterion_group, criterion_main, Criterion};

pub fn year_2015_benchmark(c: &mut Criterion) {
Expand Down Expand Up @@ -178,6 +179,16 @@ pub fn year_2015_benchmark(c: &mut Criterion) {
b.iter(|| day_16::day_16_v2(black_box(input_year_2015_day_16)))
});
g2015_day_16.finish();

let mut g2015_day_17 = c.benchmark_group("year_2015::day_17");
let input_year_2015_day_17 = include_str!("../inputs/year_2015_day_17_input");
g2015_day_17.bench_function("year_2015::day_17_v1", |b| {
b.iter(|| day_17::day_17_v1(black_box(input_year_2015_day_17)))
});
g2015_day_17.bench_function("year_2015::day_17_v2", |b| {
b.iter(|| day_17::day_17_v2(black_box(input_year_2015_day_17)))
});
g2015_day_17.finish();
}

criterion_group!(benches, year_2015_benchmark);
Expand Down
20 changes: 20 additions & 0 deletions inputs/year_2015_day_17_input
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
43
3
4
10
21
44
4
6
47
41
34
17
17
44
36
31
46
9
27
38
2 changes: 2 additions & 0 deletions src/year_2015.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub mod day_13;
pub mod day_14;
pub mod day_15;
pub mod day_16;
pub mod day_17;

/// Returns the solution for a specified exercise and input.
///
Expand Down Expand Up @@ -59,6 +60,7 @@ pub fn solve(day: u8, part: u8, input: impl Into<String>) -> Option<String> {
14 => return Some(format!("{}", day_14::day_14(part, input))),
15 => return Some(format!("{}", day_15::day_15(part, input))),
16 => return Some(format!("{}", day_16::day_16(part, input))),
17 => return Some(format!("{}", day_17::day_17(part, input))),
_ => return None,
}
}
19 changes: 0 additions & 19 deletions src/year_2015/day_16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,22 +107,3 @@ pub fn day_16_v2(input: impl Into<String>) -> usize {
}

solvable!(day_16, day_16_v1, day_16_v2, usize);

// #[cfg(test)]
// mod tests {
// use super::*;

// #[test]
// fn works_with_samples_v1() {
// let sample: &str = r#"Butterscotch: capacity -1, durability -2, flavor 6, texture 3, calories 8\n\
// Cinnamon: capacity 2, durability 3, flavor -2, texture -1, calories 3"#;
// assert_eq!(day_16_v1(sample), 62_842_880);
// }

// #[test]
// fn works_with_samples_v2() {
// let sample: &str = r#"Butterscotch: capacity -1, durability -2, flavor 6, texture 3, calories 8\n\
// Cinnamon: capacity 2, durability 3, flavor -2, texture -1, calories 3"#;
// assert_eq!(day_16_v2(sample), 57_600_000);
// }
// }
95 changes: 95 additions & 0 deletions src/year_2015/day_17.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
const EGGNOG_LITERS: usize = 150;

fn parse_file(input: String) -> Vec<usize> {
let mut inputs: Vec<usize> = vec![];
for line in input.lines() {
let Ok(value) = line.parse::<usize>() else {
panic!("Invalid number: {}", line)
};
inputs.push(value);
}

inputs
}

fn build_combinations(
liters: usize,
containers_left: Vec<usize>,
containers_build: Vec<usize>,
) -> Vec<Vec<usize>> {
let mut solutions: Vec<Vec<usize>> = vec![];
let container_size: usize = containers_build.iter().sum::<usize>();
if container_size >= liters || containers_left.is_empty() {
if container_size == liters {
solutions.push(containers_build);
}
return solutions;
}
for idx in 0..containers_left.len() {
let next_containers_left: Vec<usize> = containers_left[idx + 1..].to_owned();
let mut next_containers_build: Vec<usize> = containers_build.clone();
next_containers_build.push(containers_left[idx]);
let mut new_solutions = build_combinations(liters, next_containers_left, next_containers_build);
solutions.append(&mut new_solutions);
}

solutions
}

fn build_solutions(liters: usize, containers: &Vec<usize>) -> Vec<Vec<usize>> {
let mut solutions: Vec<Vec<usize>> = vec![];
let mut start: usize = 0;
loop {
if containers[start..].iter().sum::<usize>() < liters {
return solutions;
}
let containers_left: Vec<usize> = containers[start + 1..].to_owned();
let containers_build: Vec<usize> = vec![containers[start]];
let mut new_solutions = build_combinations(liters, containers_left, containers_build);
solutions.append(&mut new_solutions);
start += 1;
}
}

pub fn day_17_v1(input: impl Into<String>) -> usize {
let containers: Vec<usize> = parse_file(input.into());
let solutions = build_solutions(EGGNOG_LITERS, &containers);

solutions.len()
}

pub fn day_17_v2(input: impl Into<String>) -> usize {
let containers: Vec<usize> = parse_file(input.into());
let mut solutions = build_solutions(EGGNOG_LITERS, &containers);
let Some(min_solution) = solutions.iter().map(|s| s.len()).min() else {
panic!("No minimum size: {:?}", solutions)
};
solutions.retain(|s| s.len() == min_solution);

solutions.len()
}

solvable!(day_17, day_17_v1, day_17_v2, usize);

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn works_with_samples_v1() {
let sample: Vec<usize> = vec![20, 15, 10, 5, 5];
let solutions = build_solutions(25, &sample);
assert_eq!(solutions.len(), 4);
}

#[test]
fn works_with_samples_v2() {
let sample: Vec<usize> = vec![20, 15, 10, 5, 5];
let mut solutions = build_solutions(25, &sample);
let Some(min_solution) = solutions.iter().map(|s| s.len()).min() else {
panic!("No minimum size: {:?}", solutions)
};
solutions.retain(|s| s.len() == min_solution);
assert_eq!(solutions.len(), 3);
}
}
8 changes: 8 additions & 0 deletions tests/year_2015_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use advent_rs::year_2015::day_13;
use advent_rs::year_2015::day_14;
use advent_rs::year_2015::day_15;
use advent_rs::year_2015::day_16;
use advent_rs::year_2015::day_17;

#[test]
fn year_2015_day_01() {
Expand Down Expand Up @@ -125,3 +126,10 @@ fn year_2015_day_16() {
assert_eq!(day_16::day_16_v1(input), 373);
assert_eq!(day_16::day_16_v2(input), 260);
}

#[test]
fn year_2015_day_17() {
let input = include_str!("../inputs/year_2015_day_17_input");
assert_eq!(day_17::day_17_v1(input), 1638);
assert_eq!(day_17::day_17_v2(input), 17);
}

0 comments on commit 3160670

Please sign in to comment.