y2015d17 + fix some warnings
This commit is contained in:
parent
7f93abc07d
commit
9438245d84
20
y2015/resources/17_input.txt
Normal file
20
y2015/resources/17_input.txt
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
11
|
||||||
|
30
|
||||||
|
47
|
||||||
|
31
|
||||||
|
32
|
||||||
|
36
|
||||||
|
3
|
||||||
|
1
|
||||||
|
5
|
||||||
|
3
|
||||||
|
32
|
||||||
|
36
|
||||||
|
15
|
||||||
|
11
|
||||||
|
46
|
||||||
|
26
|
||||||
|
28
|
||||||
|
1
|
||||||
|
19
|
||||||
|
3
|
20
y2015/src/bin/d17.rs
Normal file
20
y2015/src/bin/d17.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use std::fs;
|
||||||
|
|
||||||
|
use y2015::days::d17;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
part1();
|
||||||
|
part2();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part1() {
|
||||||
|
let root = env!("CARGO_MANIFEST_DIR");
|
||||||
|
let content = fs::read_to_string(format!("{root}/resources/17_input.txt")).unwrap();
|
||||||
|
println!("{}", d17::process_part1(&content, 150));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part2() {
|
||||||
|
let root = env!("CARGO_MANIFEST_DIR");
|
||||||
|
let content = fs::read_to_string(format!("{root}/resources/17_input.txt")).unwrap();
|
||||||
|
println!("{}", d17::process_part2(&content, 150));
|
||||||
|
}
|
@ -173,10 +173,6 @@ pub fn process_part1(input: &str) -> i64 {
|
|||||||
biggest_score
|
biggest_score
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_part2(input: &str) -> u32 {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -59,16 +59,3 @@ pub fn process_part2(input: &str) -> String {
|
|||||||
}
|
}
|
||||||
"".to_string()
|
"".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
const INPUT: &str = "{{EXAMPLE}}";
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn part2() {
|
|
||||||
let result = process_part2(INPUT);
|
|
||||||
assert_eq!(result, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
113
y2015/src/days/d17.rs
Normal file
113
y2015/src/days/d17.rs
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
use std::{error::Error, fmt::Debug};
|
||||||
|
|
||||||
|
pub fn process_part1(input: &str, litres: u32) -> u32 {
|
||||||
|
let containers = input
|
||||||
|
.lines()
|
||||||
|
.map(|container| container.parse::<u32>().unwrap())
|
||||||
|
.collect::<Vec<u32>>();
|
||||||
|
let mut correct_combinations = Vec::new();
|
||||||
|
for k in 1..=containers.len() {
|
||||||
|
let num_combinations = binomial(containers.len(), k);
|
||||||
|
for i in 1..=num_combinations {
|
||||||
|
let res = combination(containers.clone(), k, i).unwrap();
|
||||||
|
if res.iter().sum::<u32>() == litres {
|
||||||
|
correct_combinations.push(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
correct_combinations.len() as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_part2(input: &str, litres: u32) -> u32 {
|
||||||
|
let containers = input
|
||||||
|
.lines()
|
||||||
|
.map(|container| container.parse::<u32>().unwrap())
|
||||||
|
.collect::<Vec<u32>>();
|
||||||
|
let mut correct_combinations = Vec::new();
|
||||||
|
for k in 1..=containers.len() {
|
||||||
|
let num_combinations = binomial(containers.len(), k);
|
||||||
|
for i in 1..=num_combinations {
|
||||||
|
let res = combination(containers.clone(), k, i).unwrap();
|
||||||
|
if res.iter().sum::<u32>() == litres {
|
||||||
|
correct_combinations.push(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !correct_combinations.is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
correct_combinations.len() as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn combination<T: Clone + Debug>(
|
||||||
|
elements: Vec<T>,
|
||||||
|
k: usize,
|
||||||
|
nth: usize,
|
||||||
|
) -> Result<Vec<T>, Box<dyn Error>> {
|
||||||
|
let num_elements = elements.len();
|
||||||
|
let num_combinations = binomial(num_elements, k);
|
||||||
|
if nth > num_combinations || k > num_elements || nth == 0 || k == 0 {
|
||||||
|
return Err(Box::from("Out of bounds"));
|
||||||
|
}
|
||||||
|
let mut i = 0;
|
||||||
|
let mut remaining_k = k;
|
||||||
|
let mut comb = Vec::new();
|
||||||
|
let mut remainder = nth - 1;
|
||||||
|
while remaining_k > 0 {
|
||||||
|
// Count the number of combinations that start with elements[i]
|
||||||
|
// example with n = 5, k = 2
|
||||||
|
// nth <= 4 select first
|
||||||
|
// nth <= 7 select second
|
||||||
|
// nth <= 9 select third
|
||||||
|
// nth == 10 select fourth
|
||||||
|
let count = binomial(num_elements - i - 1, remaining_k - 1);
|
||||||
|
if remainder < count {
|
||||||
|
// If the nth combination is within the count, pick this element
|
||||||
|
comb.push(elements[i].clone());
|
||||||
|
remaining_k -= 1;
|
||||||
|
} else {
|
||||||
|
remainder -= count;
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
Ok(comb)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn factorial(num: usize) -> usize {
|
||||||
|
let mut fact = 1;
|
||||||
|
for n in 1..=num {
|
||||||
|
fact *= n;
|
||||||
|
}
|
||||||
|
fact
|
||||||
|
}
|
||||||
|
|
||||||
|
fn binomial(n: usize, k: usize) -> usize {
|
||||||
|
if k > n {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
factorial(n) / (factorial(k) * factorial(n - k))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const INPUT: &str = "20
|
||||||
|
15
|
||||||
|
10
|
||||||
|
5
|
||||||
|
5";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1() {
|
||||||
|
let result = process_part1(INPUT, 25);
|
||||||
|
assert_eq!(result, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2() {
|
||||||
|
let result = process_part2(INPUT, 25);
|
||||||
|
assert_eq!(result, 3);
|
||||||
|
}
|
||||||
|
}
|
@ -15,3 +15,5 @@ pub mod d8;
|
|||||||
pub mod d9;
|
pub mod d9;
|
||||||
|
|
||||||
pub mod d16;
|
pub mod d16;
|
||||||
|
|
||||||
|
pub mod d17;
|
||||||
|
Loading…
Reference in New Issue
Block a user