This commit is contained in:
RussellChamp committed 2024-12-03 13:48:18 -05:00
1 parent 35caf9bf69
commit c97610ef61
10 files changed
+305

No files matched your search

+71
View File
@@ -0,0 +1,71 @@
advent_of_code::solution!(1);
pub fn part_one(input: &str) -> Option<u32> {
let mut vec_a = Vec::new();
let mut vec_b = Vec::new();
let mut result = 0;
for line in input.split('\n').filter(|l| !l.is_empty()) {
let vals: Vec<&str> = line.split(" ").collect();
let a = vals[0].parse::<u32>().unwrap();
let b = vals[1].parse::<u32>().unwrap();
vec_a.push(a);
vec_b.push(b);
}
vec_a.sort();
vec_b.sort();
for i in 0..vec_a.len() {
let diff = vec_a[i].abs_diff(vec_b[i]);
result += diff;
// println!("Line {}: abs({} - {}) = {}", i+1, vec_a[i], vec_b[i], diff)
}
// println!("Total {result}");
return Some(result);
}
pub fn part_two(input: &str) -> Option<u32> {
let mut vec_a = Vec::new();
let mut vec_b = Vec::new();
let mut result = 0;
for line in input.split('\n').filter(|l| !l.is_empty()) {
let vals: Vec<&str> = line.split(" ").collect();
let a = vals[0].parse::<u32>().unwrap();
let b = vals[1].parse::<u32>().unwrap();
vec_a.push(a);
vec_b.push(b);
}
vec_a.sort();
vec_b.sort();
for i in 0..vec_a.len() {
let needle = vec_a[i];
let found = vec_b.iter().filter(|&&b| b == needle).count() as u32;
let similarity = found * needle;
result += similarity;
// println!("Line {}: {} found {} times = {}, total {}", i + 1, needle, found, similarity, result);
}
// println!("Total {result}");
return Some(result);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, Some(11));
}
#[test]
fn test_part_two() {
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, Some(31));
}
}
+114
View File
@@ -0,0 +1,114 @@
advent_of_code::solution!(2);
pub fn part_one(input: &str) -> Option<u32> {
let valid_reports = input.split('\n').fold(0, |total, line| {
if line.is_empty() { return total };
let values: Vec<_> = line.split(" ").map(|f| f.parse::<u32>().unwrap()).collect();
let is_valid = is_valid_report(&values);
// println!("Report {} {} valid", line, if is_valid { "is" } else { "is NOT" });
if is_valid { return total + 1 } else { return total };
});
return Some(valid_reports);
}
pub fn part_two(input: &str) -> Option<u32> {
let valid_reports = input.split('\n').fold(0, |total, line| {
if line.is_empty() { return total };
let values: Vec<_> = line.split(" ").map(|f| f.parse::<u32>().unwrap()).collect();
let is_valid = is_any_valid_report(&values);
// println!("Report {} {} valid", line, if is_valid { "is" } else { "is NOT" });
if is_valid { return total + 1 } else { return total };
});
return Some(valid_reports);
}
enum Direction {
Unknown,
Increasing,
Decreasing,
}
fn is_valid_report(values: &Vec<u32>) -> bool {
let mut direction = Direction::Unknown;
// println!("Checking values {:?}", values);
let mut last_report = *values.first().unwrap();
for r in &values[1..] {
let report = *r;
if matches!(direction, Direction::Unknown) {
direction = if report > last_report {
Direction::Increasing
} else {
Direction::Decreasing
};
}
if report == last_report {
return false;
};
if matches!(direction, Direction::Increasing)
&& (report < last_report || report > last_report + 3)
{
return false;
};
if matches!(direction, Direction::Decreasing)
&& (report > last_report || report + 3 < last_report)
{
return false;
};
last_report = report;
}
return true;
}
fn is_any_valid_report(values: &Vec<u32>) -> bool {
if is_valid_report(values) {
return true;
}
let length = values.len();
for idx in 0..length {
if is_valid_report(&copy_except(values, idx)) {
return true;
}
}
return false;
}
fn copy_except(values: &Vec<u32>, exclude_idx: usize) -> Vec<u32> {
let mut new_values: Vec<u32> = Vec::new();
let mut idx = 0;
for value in values {
if idx != exclude_idx {
new_values.push(*value);
}
idx += 1;
}
// println!("copied new values {:?}", new_values);
return new_values;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, Some(2));
}
#[test]
fn test_part_two() {
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, Some(4));
}
}
+60
View File
@@ -0,0 +1,60 @@
advent_of_code::solution!(3);
use regex::Regex;
pub fn part_one(input: &str) -> Option<u32> {
let mul_regex = Regex::new(r"mul\((\d\d?\d?),(\d\d?\d?)\)").unwrap();
let result = mul_regex.captures_iter(input).fold(0, |total, cap| {
let (_, [a_str, b_str]) = cap.extract();
let a = a_str.parse::<u32>().unwrap();
let b = b_str.parse::<u32>().unwrap();
let product = a * b;
return total + product;
});
return Some(result);
}
pub fn part_two(input: &str) -> Option<u32> {
let mul_regex = Regex::new(r"(do)\(\)()()|(don\'t)\(\)()()|(mul)\((\d\d?\d?),(\d\d?\d?)\)").unwrap();
let (_, result) = mul_regex.captures_iter(input).fold((true, 0), |(enabled, total), cap| {
let (_, [command, a_str, b_str]) = cap.extract();
// println!("Captures: {command} ({a_str}, {b_str})");
match command {
"do" => return (true, total),
"don't" => return (false, total),
"mul" => {
if !enabled { return (enabled, total) };
let a = a_str.parse::<u32>().unwrap();
let b = b_str.parse::<u32>().unwrap();
let product = a * b;
return (enabled, total + product)
},
_ => panic!("Could not match command {command}"),
}
});
return Some(result);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, Some(161));
}
#[test]
fn test_part_two() {
let result = part_two(&advent_of_code::template::read_file_part("examples", DAY, 2));
assert_eq!(result, Some(48));
}
}