From 2c853833b5371cc921830c2bbfbdf04ceb018bc7 Mon Sep 17 00:00:00 2001 From: red Date: Wed, 27 Mar 2024 20:07:23 +0100 Subject: [PATCH] Improvement: Faster benches across 2017 --- Cargo.toml | 21 ++++++--- benches/year_2015_day_03.rs | 8 ++-- benches/year_2017_day_01.rs | 89 +++++++++++++++++++++++++++++++++++++ benches/year_2017_day_02.rs | 40 +++++++++++++++++ benches/year_2017_day_04.rs | 84 ++++++++++++++++++++++++++++++++++ src/year_2015.rs | 2 +- src/year_2015/day_03.rs | 14 +++--- src/year_2015/day_05.rs | 10 ++--- src/year_2015/day_16.rs | 6 +-- src/year_2016.rs | 2 +- src/year_2017.rs | 2 +- src/year_2017/day_01.rs | 33 +++++++++----- src/year_2017/day_02.rs | 17 ++++--- src/year_2017/day_03.rs | 36 +++++++-------- src/year_2017/day_04.rs | 22 ++++----- src/year_2017/day_05.rs | 12 ++--- src/year_2017/day_06.rs | 8 ++-- src/year_2017/day_07.rs | 9 +--- src/year_2017/day_08.rs | 13 +++--- src/year_2017/day_09.rs | 13 +++--- src/year_2017/day_10.rs | 33 +++++++------- src/year_2017/day_11.rs | 50 ++++++++------------- src/year_2017/day_12.rs | 22 ++++----- 23 files changed, 380 insertions(+), 166 deletions(-) create mode 100644 benches/year_2017_day_01.rs create mode 100644 benches/year_2017_day_02.rs create mode 100644 benches/year_2017_day_04.rs diff --git a/Cargo.toml b/Cargo.toml index 38d218a..4a63593 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,12 +42,6 @@ criterion = { version = "0.5.1", features = ["html_reports"] } [[bench]] name = "year_2015" harness = false -[[bench]] -name = "year_2016" -harness = false -[[bench]] -name = "year_2017" -harness = false # [[bench]] # name = "year_2015_day_01" # harness = false @@ -57,9 +51,24 @@ harness = false # [[bench]] # name = "year_2015_day_05" # harness = false +[[bench]] +name = "year_2016" +harness = false # [[bench]] # name = "year_2016_day_04" # harness = false # [[bench]] # name = "year_2016_day_09" # harness = false +[[bench]] +name = "year_2017" +harness = false +# [[bench]] +# name = "year_2017_day_01" +# harness = false +# [[bench]] +# name = "year_2017_day_02" +# harness = false +# [[bench]] +# name = "year_2017_day_04" +# harness = false diff --git a/benches/year_2015_day_03.rs b/benches/year_2015_day_03.rs index bb6e11c..0fec0cc 100644 --- a/benches/year_2015_day_03.rs +++ b/benches/year_2015_day_03.rs @@ -15,7 +15,7 @@ fn move_character(mut pos: (i8, i8), direction: char) -> (i8, i8) { pos } -fn day_03_v1_bset(input: &str) -> usize { +fn day_03_v1_bset(input: &str) -> u16 { let mut santa: (i8, i8) = (0, 0); let mut houses = BTreeSet::from([santa]); @@ -23,10 +23,10 @@ fn day_03_v1_bset(input: &str) -> usize { santa = move_character(santa, chr); houses.insert(santa); } - houses.len() + houses.len() as u16 } -fn day_03_v2_bset(input: &str) -> usize { +fn day_03_v2_bset(input: &str) -> u16 { let mut santa: (i8, i8) = (0, 0); let mut robot: (i8, i8) = (0, 0); let mut houses = BTreeSet::from([santa]); @@ -38,7 +38,7 @@ fn day_03_v2_bset(input: &str) -> usize { houses.insert(santa); houses.insert(robot); } - houses.len() + houses.len() as u16 } fn bench_year_2015_day_03_sets(c: &mut Criterion) { diff --git a/benches/year_2017_day_01.rs b/benches/year_2017_day_01.rs new file mode 100644 index 0000000..f826a9d --- /dev/null +++ b/benches/year_2017_day_01.rs @@ -0,0 +1,89 @@ +use advent_rs::year_2017::day_01; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; +use std::time::Duration; + +fn day_01_v2_naive(input: impl Into) -> u16 { + let characters = input + .into() + .trim_end() + .chars() + .map(|c| c as u8) + .collect::>(); + let length = characters.len(); + let dem_length = length / 2; + characters + .iter() + .enumerate() + .filter_map(|(idx, chr)| { + if *chr == characters[(idx + dem_length) % length] { + Some((*chr - 48) as u16) + } else { + None + } + }) + .sum() +} + +fn day_01_v2_zip(input: impl Into) -> u16 { + let characters = input + .into() + .trim_end() + .chars() + .map(|c| c as u8) + .collect::>(); + characters + .iter() + .zip(characters.iter().cycle().skip(characters.len() / 2)) + .filter_map(|(lhs, rhs)| { + if lhs == rhs { + Some((lhs - 48) as u16) + } else { + None + } + }) + .sum() +} + +// fn bench_year_2017_day_01_v1(c: &mut Criterion) { +// let mut group = c.benchmark_group("year_2017::day_01_v1"); +// group.warm_up_time(Duration::from_millis(100)); +// let input = include_str!("../inputs/year_2017/day_01_input"); +// group.bench_with_input(BenchmarkId::new("Naive", input.len()), input, |b, input| { +// b.iter(|| day_01_v1_naive(input)) +// }); +// assert_eq!(day_01::day_01_v1(input), 1_069); +// group.bench_with_input( +// BenchmarkId::new("Normal", input.len()), +// input, +// |b, input| b.iter(|| day_01::day_01_v1(input)), +// ); +// group.bench_with_input(BenchmarkId::new("Fast", input.len()), input, |b, input| { +// b.iter(|| day_01_v1_fast(input)) +// }); +// group.finish(); +// } + +fn bench_year_2017_day_01_v2(c: &mut Criterion) { + let mut group = c.benchmark_group("year_2017::day_01_v2"); + group.warm_up_time(Duration::from_millis(100)); + let input = include_str!("../inputs/year_2017/day_01_input"); + assert_eq!(day_01_v2_naive(input), 1_268); + assert_eq!(day_01_v2_zip(input), 1_268); + assert_eq!(day_01::day_01_v2(input), 1_268); + group.bench_with_input(BenchmarkId::new("Naive", input.len()), input, |b, input| { + b.iter(|| day_01_v2_naive(input)) + }); + group.bench_with_input(BenchmarkId::new("Zip", input.len()), input, |b, input| { + b.iter(|| day_01_v2_zip(input)) + }); + group.bench_with_input( + BenchmarkId::new("Normal", input.len()), + input, + |b, input| b.iter(|| day_01::day_01_v2(input)), + ); + + group.finish(); +} + +criterion_group!(bench_year_2017_day_01, bench_year_2017_day_01_v2); +criterion_main!(bench_year_2017_day_01); diff --git a/benches/year_2017_day_02.rs b/benches/year_2017_day_02.rs new file mode 100644 index 0000000..7502a29 --- /dev/null +++ b/benches/year_2017_day_02.rs @@ -0,0 +1,40 @@ +use advent_rs::year_2017::day_02; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; +use itertools::Itertools; +use std::time::Duration; + +pub fn day_02_v1_naive(input: impl Into) -> u16 { + input + .into() + .lines() + .map(|line| { + let numbers: Vec<_> = line + .split_whitespace() + .map(|number| number.parse::().unwrap()) + .sorted() + .collect(); + numbers.iter().max().unwrap() - numbers.iter().min().unwrap() + }) + .sum() +} + +fn bench_year_2017_day_02_v1(c: &mut Criterion) { + let mut group = c.benchmark_group("year_2017::day_02_v1"); + group.warm_up_time(Duration::from_millis(100)); + let input = include_str!("../inputs/year_2017/day_02_input"); + assert_eq!(day_02::day_02_v1(input), 53_978); + assert_eq!(day_02_v1_naive(input), 53_978); + group.bench_with_input(BenchmarkId::new("Naive", input.len()), input, |b, input| { + b.iter(|| day_02_v1_naive(input)) + }); + group.bench_with_input( + BenchmarkId::new("Normal", input.len()), + input, + |b, input| b.iter(|| day_02::day_02_v1(input)), + ); + + group.finish(); +} + +criterion_group!(bench_year_2017_day_02, bench_year_2017_day_02_v1); +criterion_main!(bench_year_2017_day_02); diff --git a/benches/year_2017_day_04.rs b/benches/year_2017_day_04.rs new file mode 100644 index 0000000..dd90eb3 --- /dev/null +++ b/benches/year_2017_day_04.rs @@ -0,0 +1,84 @@ +use advent_rs::year_2017::day_04; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; +use itertools::Itertools; +use std::{collections::HashSet, time::Duration}; + +pub fn day_04_v1_naive(input: impl Into) -> u16 { + input + .into() + .lines() + .filter(|line| { + line + .split_whitespace() + .sorted() + .group_by(|word| *word) + .into_iter() + .all(|(_word, group)| group.count() == 1) + }) + .count() as u16 +} + +pub fn day_04_v1_sorted(input: impl Into) -> u16 { + input + .into() + .lines() + .filter(|line| { + !line + .split_whitespace() + .sorted() + .collect::>() + .windows(2) + .any(|pair| pair[0] == pair[1]) + }) + .count() as u16 +} + +pub fn day_04_v1_with_set(input: impl Into) -> u16 { + input + .into() + .lines() + .filter(|line| { + let mut set = HashSet::new(); + for word in line.split_whitespace() { + if set.contains(word) { + return false; + } + set.insert(word); + } + true + }) + .count() as u16 +} + +fn bench_year_2017_day_04_v1(c: &mut Criterion) { + let mut group = c.benchmark_group("year_2017::day_04_v1"); + group.warm_up_time(Duration::from_millis(100)); + let input = include_str!("../inputs/year_2017/day_04_input"); + assert_eq!(day_04::day_04_v1(input), 466); + assert_eq!(day_04_v1_naive(input), 466); + assert_eq!(day_04_v1_sorted(input), 466); + assert_eq!(day_04_v1_with_set(input), 466); + group.bench_with_input(BenchmarkId::new("Naive", input.len()), input, |b, input| { + b.iter(|| day_04_v1_naive(input)) + }); + group.bench_with_input( + BenchmarkId::new("Sorted", input.len()), + input, + |b, input| b.iter(|| day_04_v1_sorted(input)), + ); + group.bench_with_input( + BenchmarkId::new("WithSet", input.len()), + input, + |b, input| b.iter(|| day_04_v1_with_set(input)), + ); + group.bench_with_input( + BenchmarkId::new("Normal", input.len()), + input, + |b, input| b.iter(|| day_04::day_04_v1(input)), + ); + + group.finish(); +} + +criterion_group!(bench_year_2017_day_04, bench_year_2017_day_04_v1); +criterion_main!(bench_year_2017_day_04); diff --git a/src/year_2015.rs b/src/year_2015.rs index 430d728..aab253c 100644 --- a/src/year_2015.rs +++ b/src/year_2015.rs @@ -84,7 +84,7 @@ pub mod day_25; /// assert_eq!(solution, Some("0".to_string())); /// ``` pub fn solve(day: u8, part: u8, input: impl Into) -> Option { - if part != 1 && part != 2 { + if part > 2 { return None; } match day { diff --git a/src/year_2015/day_03.rs b/src/year_2015/day_03.rs index 2322842..7493c24 100644 --- a/src/year_2015/day_03.rs +++ b/src/year_2015/day_03.rs @@ -47,7 +47,7 @@ fn move_character(pos: &mut (i8, i8), direction: u8) { // pos } -pub fn day_03_v1(input: impl Into) -> usize { +pub fn day_03_v1(input: impl Into) -> u16 { let mut santa: (i8, i8) = (0, 0); let mut houses = HashSet::from([santa]); @@ -56,10 +56,10 @@ pub fn day_03_v1(input: impl Into) -> usize { houses.insert(santa); } - houses.len() + houses.len() as u16 } -pub fn day_03_v2(input: impl Into) -> usize { +pub fn day_03_v2(input: impl Into) -> u16 { let mut santa: (i8, i8) = (0, 0); let mut robot: (i8, i8) = (0, 0); let mut houses = HashSet::from([santa]); @@ -71,10 +71,10 @@ pub fn day_03_v2(input: impl Into) -> usize { houses.insert(robot); } - houses.len() + houses.len() as u16 } -solvable!(day_03, day_03_v1, day_03_v2, usize); +solvable!(day_03, day_03_v1, day_03_v2, u16); #[cfg(test)] mod tests { @@ -82,7 +82,7 @@ mod tests { #[test] fn works_with_samples_v1() { - let sample_one: [(&str, usize); 3] = [ + let sample_one: [(&str, u16); 3] = [ (">", 2), ("^>v<", 4), ("^v^v^v^v^v", 2), @@ -95,7 +95,7 @@ mod tests { #[test] fn works_with_samples_v2() { - let sample_two: [(&str, usize); 3] = [ + let sample_two: [(&str, u16); 3] = [ ("^v", 3), ("^>v<", 3), ("^v^v^v^v^v", 11), diff --git a/src/year_2015/day_05.rs b/src/year_2015/day_05.rs index 26c8d5e..8cb85a1 100644 --- a/src/year_2015/day_05.rs +++ b/src/year_2015/day_05.rs @@ -88,23 +88,23 @@ fn string_is_nice_v2(input: &str) -> bool { twice_pair && repeated } -pub fn day_05_v1(input: impl Into) -> usize { +pub fn day_05_v1(input: impl Into) -> u16 { input .into() .lines() .filter(|line| string_is_nice_v1(line)) - .count() + .count() as u16 } -pub fn day_05_v2(input: impl Into) -> usize { +pub fn day_05_v2(input: impl Into) -> u16 { input .into() .lines() .filter(|line| string_is_nice_v2(line)) - .count() + .count() as u16 } -solvable!(day_05, day_05_v1, day_05_v2, usize); +solvable!(day_05, day_05_v1, day_05_v2, u16); #[cfg(test)] mod tests { diff --git a/src/year_2015/day_16.rs b/src/year_2015/day_16.rs index c043724..7f06d28 100644 --- a/src/year_2015/day_16.rs +++ b/src/year_2015/day_16.rs @@ -72,7 +72,7 @@ where true } -pub fn day_16_v1(input: impl Into) -> usize { +pub fn day_16_v1(input: impl Into) -> u16 { let ticker_tape = build_ticker_tape(); let mut index = 1; for aunt in input.into().lines() { @@ -89,7 +89,7 @@ pub fn day_16_v1(input: impl Into) -> usize { index } -pub fn day_16_v2(input: impl Into) -> usize { +pub fn day_16_v2(input: impl Into) -> u16 { let ticker_tape = build_ticker_tape(); let mut index = 1; for aunt in input.into().lines() { @@ -106,4 +106,4 @@ pub fn day_16_v2(input: impl Into) -> usize { index } -solvable!(day_16, day_16_v1, day_16_v2, usize); +solvable!(day_16, day_16_v1, day_16_v2, u16); diff --git a/src/year_2016.rs b/src/year_2016.rs index 2eb3ee0..a3d14f5 100644 --- a/src/year_2016.rs +++ b/src/year_2016.rs @@ -30,7 +30,7 @@ pub mod day_24; pub mod day_25; pub fn solve(day: u8, part: u8, input: impl Into) -> Option { - if part != 1 && part != 2 { + if part > 2 { return None; } diff --git a/src/year_2017.rs b/src/year_2017.rs index a5262a5..42845eb 100644 --- a/src/year_2017.rs +++ b/src/year_2017.rs @@ -16,7 +16,7 @@ pub mod day_11; pub mod day_12; pub fn solve(day: u8, part: u8, input: impl Into) -> Option { - if part != 1 && part != 2 { + if part > 2 { return None; } diff --git a/src/year_2017/day_01.rs b/src/year_2017/day_01.rs index 9925b50..26ef016 100644 --- a/src/year_2017/day_01.rs +++ b/src/year_2017/day_01.rs @@ -1,4 +1,4 @@ -pub fn day_01_v1(input: impl Into) -> usize { +pub fn day_01_v1(input: impl Into) -> u16 { let mut characters = input .into() .trim_end() @@ -8,28 +8,39 @@ pub fn day_01_v1(input: impl Into) -> usize { characters.push(characters[0]); characters .windows(2) - .filter(|pair| pair[0] == pair[1]) - .map(|pair| (pair[0] - 48) as usize) + .filter_map(|pair| { + if pair[0] == pair[1] { + Some((pair[0] - 48) as u16) + } else { + None + } + }) .sum() } -pub fn day_01_v2(input: impl Into) -> usize { +pub fn day_01_v2(input: impl Into) -> u16 { let characters = input .into() .trim_end() .chars() .map(|c| c as u8) .collect::>(); - let length = characters.len(); + let mut characters_rot = characters.clone(); + characters_rot.rotate_right(characters.len() / 2); characters .iter() - .enumerate() - .filter(|(idx, chr)| **chr == characters[(idx + length / 2) % length]) - .map(|(_idx, chr)| (*chr - 48) as usize) + .zip(characters_rot.iter()) + .filter_map(|(lhs, rhs)| { + if lhs == rhs { + Some((lhs - 48) as u16) + } else { + None + } + }) .sum() } -solvable!(day_01, day_01_v1, day_01_v2, usize); +solvable!(day_01, day_01_v1, day_01_v2, u16); #[cfg(test)] mod tests { @@ -37,7 +48,7 @@ mod tests { #[test] fn works_with_samples_v1() { - let sample_one: [(&str, usize); 4] = [ + let sample_one: [(&str, u16); 4] = [ ("1122", 3), ("1111", 4), ("1234", 0), @@ -49,7 +60,7 @@ mod tests { } #[test] fn works_with_samples_v2() { - let sample_two: [(&str, usize); 5] = [ + let sample_two: [(&str, u16); 5] = [ ("1212", 6), ("1221", 0), ("123425", 4), diff --git a/src/year_2017/day_02.rs b/src/year_2017/day_02.rs index 6fbce71..fd866bc 100644 --- a/src/year_2017/day_02.rs +++ b/src/year_2017/day_02.rs @@ -1,14 +1,14 @@ use itertools::Itertools; -pub fn day_02_v1(input: impl Into) -> usize { +pub fn day_02_v1(input: impl Into) -> u16 { input .into() .lines() .map(|line| { let mut max = 0; - let mut min = usize::MAX; + let mut min = u16::MAX; line.split_whitespace().for_each(|number| { - let number = number.parse::().unwrap(); + let number = number.parse::().unwrap(); max = std::cmp::max(max, number); min = std::cmp::min(min, number); }); @@ -17,19 +17,18 @@ pub fn day_02_v1(input: impl Into) -> usize { .sum() } -pub fn day_02_v2(input: impl Into) -> usize { +pub fn day_02_v2(input: impl Into) -> u16 { input .into() .lines() .map(|line| { line .split_whitespace() - .map(|number| number.parse::().unwrap()) + .map(|number| number.parse::().unwrap()) + .sorted() .combinations(2) .filter_map(|pair| { - if pair[0] % pair[1] == 0 { - Some(pair[0] / pair[1]) - } else if pair[1] % pair[0] == 0 { + if pair[1] % pair[0] == 0 { Some(pair[1] / pair[0]) } else { None @@ -41,7 +40,7 @@ pub fn day_02_v2(input: impl Into) -> usize { .sum() } -solvable!(day_02, day_02_v1, day_02_v2, usize); +solvable!(day_02, day_02_v1, day_02_v2, u16); #[cfg(test)] mod tests { diff --git a/src/year_2017/day_03.rs b/src/year_2017/day_03.rs index 6e60c38..09f9f1e 100644 --- a/src/year_2017/day_03.rs +++ b/src/year_2017/day_03.rs @@ -1,41 +1,41 @@ use std::collections::HashMap; // Thanks https://stackoverflow.com/a/61253346 -fn spiral(input: usize) -> (i64, i64) { +fn spiral(input: u32) -> (i32, i32) { let n = input as f64; let k = ((n.sqrt() - 1f64) / 2f64).ceil(); let mut t = (2f64 * k) + 1f64; let mut m = t.powf(2f64); t -= 1f64; if n >= (m - t) { - return ((k - (m - n)) as i64, -k as i64); + return ((k - (m - n)) as i32, -k as i32); } else { m -= t; } if n >= (m - t) { - return (-k as i64, (-k + (m - n)) as i64); + return (-k as i32, (-k + (m - n)) as i32); } else { m -= t; } if n >= (m - t) { - return ((-k + (m - n)) as i64, k as i64); + return ((-k + (m - n)) as i32, k as i32); } - (k as i64, (k - (m - n - t)) as i64) + (k as i32, (k - (m - n - t)) as i32) } -pub fn day_03_v1(input: impl Into) -> usize { - let number = input.into().trim_end().parse::().unwrap(); +pub fn day_03_v1(input: impl Into) -> u32 { + let number = input.into().trim_end().parse::().unwrap(); let position = spiral(number); - (position.0.unsigned_abs() + position.1.unsigned_abs()) as usize + (position.0.unsigned_abs() + position.1.unsigned_abs()) as u32 } #[inline] -fn get_neighbors(values: &HashMap<(i64, i64), usize>, position: (i64, i64)) -> usize { - let mut result: usize = 0; - for position_x in position.0 - 1i64..=position.0 + 1i64 { - for position_y in position.1 - 1i64..=position.1 + 1i64 { +fn get_neighbors(values: &HashMap<(i32, i32), u32>, position: (i32, i32)) -> u32 { + let mut result: u32 = 0; + for position_x in position.0 - 1i32..=position.0 + 1i32 { + for position_y in position.1 - 1i32..=position.1 + 1i32 { if let Some(position_value) = values.get(&(position_x, position_y)) { result += *position_value; } @@ -44,10 +44,10 @@ fn get_neighbors(values: &HashMap<(i64, i64), usize>, position: (i64, i64)) -> u result } -pub fn day_03_v2(input: impl Into) -> usize { - let target = input.into().trim_end().parse::().unwrap(); - let mut values: HashMap<(i64, i64), usize> = HashMap::new(); - values.insert((0i64, 0i64), 1); +pub fn day_03_v2(input: impl Into) -> u32 { + let target = input.into().trim_end().parse::().unwrap(); + let mut values: HashMap<(i32, i32), u32> = HashMap::new(); + values.insert((0i32, 0i32), 1); let mut counter = 1; loop { counter += 1; @@ -60,7 +60,7 @@ pub fn day_03_v2(input: impl Into) -> usize { } } -solvable!(day_03, day_03_v1, day_03_v2, usize); +solvable!(day_03, day_03_v1, day_03_v2, u32); #[cfg(test)] mod tests { @@ -68,7 +68,7 @@ mod tests { #[test] fn works_with_samples_v1() { - let sample_one: [(&str, usize); 4] = [ + let sample_one: [(&str, u32); 4] = [ ("1", 0), ("12", 3), ("23", 2), diff --git a/src/year_2017/day_04.rs b/src/year_2017/day_04.rs index 888ef77..54954e3 100644 --- a/src/year_2017/day_04.rs +++ b/src/year_2017/day_04.rs @@ -1,37 +1,37 @@ use itertools::Itertools; -pub fn day_04_v1(input: impl Into) -> usize { +pub fn day_04_v1(input: impl Into) -> u16 { input .into() .lines() .filter(|line| { - !line + line .split_whitespace() .sorted() .collect::>() .windows(2) - .any(|pair| pair[0] == pair[1]) + .all(|pair| pair[0] != pair[1]) }) - .count() + .count() as u16 } -pub fn day_04_v2(input: impl Into) -> usize { +pub fn day_04_v2(input: impl Into) -> u16 { input .into() .lines() .filter(|line| { - !line + line .split_whitespace() .map(|word| word.chars().sorted().collect::>()) .sorted() .collect::>() .windows(2) - .any(|pair| pair[0] == pair[1]) + .all(|pair| pair[0] != pair[1]) }) - .count() + .count() as u16 } -solvable!(day_04, day_04_v1, day_04_v2, usize); +solvable!(day_04, day_04_v1, day_04_v2, u16); #[cfg(test)] mod tests { @@ -39,7 +39,7 @@ mod tests { #[test] fn works_with_samples_v1() { - let sample_one: [(&str, usize); 3] = [ + let sample_one: [(&str, u16); 3] = [ ("aa bb cc dd ee", 1), ("aa bb cc dd aa", 0), ("aa bb cc dd aaa", 1), @@ -51,7 +51,7 @@ mod tests { #[test] fn works_with_samples_v2() { - let sample_two: [(&str, usize); 5] = [ + let sample_two: [(&str, u16); 5] = [ ("abcde fghij", 1), ("abcde xyz ecdab", 0), ("a ab abc abd abf abj", 1), diff --git a/src/year_2017/day_05.rs b/src/year_2017/day_05.rs index 67413ae..21a9311 100644 --- a/src/year_2017/day_05.rs +++ b/src/year_2017/day_05.rs @@ -1,11 +1,11 @@ -pub fn day_05_v1(input: impl Into) -> usize { +pub fn day_05_v1(input: impl Into) -> u32 { let mut instructions: Vec = input .into() .lines() .map(|line| line.parse::().unwrap()) .collect(); let mut pc: i16 = 0; - let mut moves: usize = 0; + let mut moves: u32 = 0; while let Some(instruction) = instructions.get_mut(pc as usize) { pc += *instruction; @@ -15,24 +15,24 @@ pub fn day_05_v1(input: impl Into) -> usize { moves } -pub fn day_05_v2(input: impl Into) -> usize { +pub fn day_05_v2(input: impl Into) -> u32 { let mut instructions: Vec = input .into() .lines() .map(|line| line.parse::().unwrap()) .collect(); let mut pc: i16 = 0; - let mut moves: usize = 0; + let mut moves: u32 = 0; while let Some(instruction) = instructions.get_mut(pc as usize) { pc += *instruction; - *instruction += if *instruction >= 3 { -1 } else { 1 }; + *instruction += if *instruction < 3 { 1 } else { -1 }; moves += 1; } moves } -solvable!(day_05, day_05_v1, day_05_v2, usize); +solvable!(day_05, day_05_v1, day_05_v2, u32); #[cfg(test)] mod tests { diff --git a/src/year_2017/day_06.rs b/src/year_2017/day_06.rs index c49f163..c9b65c8 100644 --- a/src/year_2017/day_06.rs +++ b/src/year_2017/day_06.rs @@ -23,7 +23,7 @@ fn max_idx(input: &[u8]) -> (usize, usize) { (idx, max) } -pub fn day_06_v1(input: impl Into) -> usize { +pub fn day_06_v1(input: impl Into) -> u32 { let mut towers = parse_input(&input.into()); let towers_len = towers.len(); let mut positions: HashSet> = HashSet::new(); @@ -41,10 +41,10 @@ pub fn day_06_v1(input: impl Into) -> usize { moves } -pub fn day_06_v2(input: impl Into) -> usize { +pub fn day_06_v2(input: impl Into) -> u32 { let mut towers = parse_input(&input.into()); let towers_len = towers.len(); - let mut positions: HashMap, usize> = HashMap::new(); + let mut positions: HashMap, u32> = HashMap::new(); let mut moves = 0; loop { @@ -60,7 +60,7 @@ pub fn day_06_v2(input: impl Into) -> usize { } } -solvable!(day_06, day_06_v1, day_06_v2, usize); +solvable!(day_06, day_06_v1, day_06_v2, u32); #[cfg(test)] mod tests { diff --git a/src/year_2017/day_07.rs b/src/year_2017/day_07.rs index 788e722..b85b357 100644 --- a/src/year_2017/day_07.rs +++ b/src/year_2017/day_07.rs @@ -139,15 +139,8 @@ pub fn day_07_v2(input: impl Into) -> String { .unwrap(); let weight_difference = bad_weights.0.abs_diff(bad_weights.1); (bad_node.size - weight_difference).to_string() - - // // let bad_weight_node = bottom.children.iter() - // // .find(|&name| tower.size_of(&name) == bad_weight_size) - // // .unwrap(); - // return "foo".to_string(); - // } - - // "foo".to_string() } + solvable!(day_07, day_07_v1, day_07_v2, String); #[cfg(test)] diff --git a/src/year_2017/day_08.rs b/src/year_2017/day_08.rs index 6d18631..aa43382 100644 --- a/src/year_2017/day_08.rs +++ b/src/year_2017/day_08.rs @@ -1,16 +1,16 @@ use std::collections::HashMap; -#[inline] -fn check_conditional(register: i16, conditions: &[&str]) -> bool { - let value = conditions[1].parse::().unwrap(); - match conditions[0] { +// #[inline] +fn check_conditional(register: i16, condition: &str, value: &str) -> bool { + let value = value.parse::().unwrap(); + match condition { ">" => register > value, "<" => register < value, ">=" => register >= value, "<=" => register <= value, "==" => register == value, "!=" => register != value, - _ => panic!("Invalid condition: {}", conditions[0]), + _ => panic!("Invalid condition: {}", condition), } } @@ -19,8 +19,9 @@ fn follow_instructions(input: &str) -> (i16, i16) { let mut best_max = 0; for line in input.lines() { let parts: Vec<&str> = line.split_whitespace().collect(); + assert_eq!(parts.len(), 7); let reg_cond = registers.get(parts[4]).unwrap_or(&0); - if check_conditional(*reg_cond, &parts[5..]) { + if check_conditional(*reg_cond, parts[5], parts[6]) { let reg_target = registers.entry(parts[0]).or_default(); let value = parts[2].parse::().unwrap(); match parts[1] { diff --git a/src/year_2017/day_09.rs b/src/year_2017/day_09.rs index 5645508..fc92d93 100644 --- a/src/year_2017/day_09.rs +++ b/src/year_2017/day_09.rs @@ -1,4 +1,4 @@ -fn traverse_input(input: &str) -> (usize, usize) { +fn traverse_input(input: &str) -> (u32, u32) { let mut result = 0; let mut garbage = 0; let mut depth = 0; @@ -27,15 +27,15 @@ fn traverse_input(input: &str) -> (usize, usize) { (result, garbage) } -pub fn day_09_v1(input: impl Into) -> usize { +pub fn day_09_v1(input: impl Into) -> u32 { traverse_input(&input.into()).0 } -pub fn day_09_v2(input: impl Into) -> usize { +pub fn day_09_v2(input: impl Into) -> u32 { traverse_input(&input.into()).1 } -solvable!(day_09, day_09_v1, day_09_v2, usize); +solvable!(day_09, day_09_v1, day_09_v2, u32); #[cfg(test)] mod tests { @@ -43,7 +43,7 @@ mod tests { #[test] fn works_with_samples_v1() { - let sample_one: [(&str, usize); 8] = [ + let sample_one: [(&str, u32); 8] = [ (r#"{}"#, 1), (r#"{{{}}}"#, 6), (r#"{{},{}}"#, 5), @@ -53,7 +53,6 @@ mod tests { (r#"{{},{},{},{}}"#, 9), (r#"{{},{},{},{}}"#, 3), ]; - for (sample, result) in sample_one { assert_eq!(day_09_v1(sample), result); } @@ -61,7 +60,7 @@ mod tests { #[test] fn works_with_samples_v2() { - let sample_two: [(&str, usize); 7] = [ + let sample_two: [(&str, u32); 7] = [ (r#"<>"#, 0), (r#""#, 17), (r#"<<<<>"#, 3), diff --git a/src/year_2017/day_10.rs b/src/year_2017/day_10.rs index d191120..7e307e2 100644 --- a/src/year_2017/day_10.rs +++ b/src/year_2017/day_10.rs @@ -1,24 +1,24 @@ use itertools::Itertools; #[inline] -fn parse_jumps_v1(input: &str) -> Vec { +fn parse_jumps_v1(input: &str) -> Vec { input .trim_end() .split(',') - .map(|number| number.trim().parse::().unwrap()) + .map(|number| number.trim().parse::().unwrap()) .collect() } #[inline] -fn parse_jumps_v2(input: &str) -> Vec { +fn parse_jumps_v2(input: &str) -> Vec { input .trim_end() .bytes() - .map(|number| number as usize) + .map(|number| number as u32) .collect() } -fn knot_hash(size: usize, jumps: &[usize], rounds: usize) -> Vec { +fn knot_hash(size: u32, jumps: &[u32], rounds: u32) -> Vec { let mut numbers: Vec<_> = (0..size).collect_vec(); let num_lens = numbers.len(); let mut jumps_done = 0; @@ -26,14 +26,18 @@ fn knot_hash(size: usize, jumps: &[usize], rounds: usize) -> Vec { for _ in 0..rounds { for jump in jumps.iter() { - let extract = numbers[0..*jump].iter().cloned().rev().collect_vec(); - numbers.splice(0..*jump, extract); - numbers.rotate_left((jump + skip_size) % num_lens); - jumps_done += (jump + skip_size) % num_lens; + let extract = numbers[0..*jump as usize] + .iter() + .cloned() + .rev() + .collect_vec(); + numbers.splice(0..*jump as usize, extract); + numbers.rotate_left(((jump + skip_size) % num_lens as u32) as usize); + jumps_done += (jump + skip_size) % num_lens as u32; skip_size += 1; } } - numbers.rotate_right(jumps_done % num_lens); + numbers.rotate_right(jumps_done as usize % num_lens); numbers } @@ -46,14 +50,13 @@ pub fn day_10_v1(input: impl Into) -> String { pub fn day_10_v2(input: impl Into) -> String { let mut jumps = parse_jumps_v2(&input.into()); jumps.append(&mut vec![17, 31, 73, 47, 23]); - let numbers = knot_hash(256, &jumps, 64); - numbers + + knot_hash(256, &jumps, 64) .chunks(16) - .map(|chunk| chunk.iter().fold(0, |acc, &val| acc ^ val)) + .map(|chunk| chunk.iter().fold(0, |acc, &val| acc ^ val) as u8) .map(|xor| format!("{:02x}", xor)) + .collect::>() .join("") - - // "foo".to_string() } solvable!(day_10, day_10_v1, day_10_v2, String); diff --git a/src/year_2017/day_11.rs b/src/year_2017/day_11.rs index 9fa6daa..cd06111 100644 --- a/src/year_2017/day_11.rs +++ b/src/year_2017/day_11.rs @@ -1,54 +1,40 @@ use itertools::Itertools; #[inline] -fn parse_input(input: &str) -> Vec<&str> { - input.trim_end().split(',').collect_vec() +fn parse_position(position: (i32, i32)) -> u32 { + (position.0.unsigned_abs() + position.1.unsigned_abs()) / 2 } -fn parse_position(position: (i32, i32)) -> usize { - ((position.0.unsigned_abs() + position.1.unsigned_abs()) / 2) as usize -} - -fn traverse(input: &str) -> (usize, usize) { - let directions = parse_input(input); +fn traverse(input: &str) -> (u32, u32) { + let directions = input.trim_end().split(',').collect_vec(); let mut position: (i32, i32) = (0, 0); let mut distance_max = 0; for direction in directions { - match direction { - "n" => position.1 -= 2, - "s" => position.1 += 2, - "nw" => { - position.0 -= 1; - position.1 -= 1; - } - "ne" => { - position.0 += 1; - position.1 -= 1; - } - "sw" => { - position.0 -= 1; - position.1 += 1; - } - "se" => { - position.0 += 1; - position.1 += 1; - } + let add_position = match direction { + "n" => (0, -2), + "s" => (0, 2), + "nw" => (-1, -1), + "ne" => (1, -1), + "sw" => (-1, 1), + "se" => (1, 1), _ => panic!("Invalid input: {}", direction), - } + }; + position.0 += add_position.0; + position.1 += add_position.1; distance_max = std::cmp::max(distance_max, parse_position(position)); } (parse_position(position), distance_max) } -pub fn day_11_v1(input: impl Into) -> usize { +pub fn day_11_v1(input: impl Into) -> u32 { traverse(&input.into()).0 } -pub fn day_11_v2(input: impl Into) -> usize { +pub fn day_11_v2(input: impl Into) -> u32 { traverse(&input.into()).1 } -solvable!(day_11, day_11_v1, day_11_v2, usize); +solvable!(day_11, day_11_v1, day_11_v2, u32); #[cfg(test)] mod tests { @@ -56,7 +42,7 @@ mod tests { #[test] fn works_with_samples_v1() { - let sample_one: [(&str, usize); 4] = [ + let sample_one: [(&str, u32); 4] = [ ("ne,ne,ne", 3), ("ne,ne,sw,sw", 0), ("ne,ne,s,s", 2), diff --git a/src/year_2017/day_12.rs b/src/year_2017/day_12.rs index d5f56fc..4d2f2c0 100644 --- a/src/year_2017/day_12.rs +++ b/src/year_2017/day_12.rs @@ -3,19 +3,19 @@ use std::collections::HashSet; #[derive(Default)] struct Village { - groups: Vec>, + groups: Vec>, } impl Village { - fn group_with(&self, needle: usize) -> Option { + fn group_with(&self, needle: u16) -> Option { self.groups.iter().position(|group| group.contains(&needle)) } - fn parse_node(input: &str) -> Vec { + fn parse_node(input: &str) -> Vec { let (root, links) = input.split_once(" <-> ").unwrap(); - let mut new_node = Vec::from([root.parse::().unwrap()]); + let mut new_node = Vec::from([root.parse::().unwrap()]); for link in links.split(", ") { - new_node.push(link.parse::().unwrap()); + new_node.push(link.parse::().unwrap()); } new_node.sort(); new_node @@ -39,29 +39,29 @@ impl Village { self.groups.push(final_node); } - pub fn group_zero(&mut self) -> &HashSet { + pub fn group_zero(&mut self) -> &HashSet { let idx = self.group_with(0).unwrap(); &self.groups[idx] } } -pub fn day_12_v1(input: impl Into) -> usize { +pub fn day_12_v1(input: impl Into) -> u16 { let mut village = Village::default(); for line in input.into().lines() { village.add_node(line); } - village.group_zero().len() + village.group_zero().len() as u16 } -pub fn day_12_v2(input: impl Into) -> usize { +pub fn day_12_v2(input: impl Into) -> u16 { let mut village = Village::default(); for line in input.into().lines() { village.add_node(line); } - village.groups.len() + village.groups.len() as u16 } -solvable!(day_12, day_12_v1, day_12_v2, usize); +solvable!(day_12, day_12_v1, day_12_v2, u16); #[cfg(test)] mod tests {