Skip to content

Commit

Permalink
Year 2018: Day 06
Browse files Browse the repository at this point in the history
  • Loading branch information
joshleaves committed May 21, 2024
1 parent 0e03067 commit 84c8c5e
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ 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)

## [2018.6.1]
### Added
- Solved [exercice for 2018, day 06](src/year_2018/06.rs).

## [2018.5.1]
### Added
- Solved [exercice for 2018, day 05](src/year_2018/05.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 = "2018.5.1"
version = "2018.6.1"
edition = "2021"
authors = ["Arnaud 'red' Rouyer"]
readme = "README.md"
Expand Down
4 changes: 4 additions & 0 deletions NOTES_2018.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ There's something about this "find the most used record" type of exercises that
## Day 05: Alchemical Reduction

As a programmer, your MUST have used, at least once, the command [`man ascii`](https://man.archlinux.org/man/core/man-pages/ascii.7.en), if only to find the integer value of a specific number. But were you to look specifically at the hexadecimal table, something may have caught your attention: uppercase letters, and their equivalent lowercase values, are all separated by 32 characters. Now, isn't that a nice number that plays VERY WELL with bit masks? Here's a little [playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=d9a88346debfc3c2470c6b1527202f30) to help you!

## Day 06: Chronal Coordinates

At first, I felt like expanding each area one by one, until I realised that just calculating distances was just easier.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ I'm also adding notes that may be useful if you're (like me) discovering Rust:
- [2015, complete!](NOTES_2015.md)
- [2016, complete!](NOTES_2016.md)
- [2017, complete!](NOTES_2017.md)
- [2018, up to day 05](NOTES_2018.md)
- [2018, up to day 06](NOTES_2018.md)

# Regarding style rules
I'm gonna use a mix of what `cargo fmt` does, with some stuff that feels more natural to me.
Expand Down
19 changes: 18 additions & 1 deletion benches/year_2018.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use advent_rs::year_2018::day_02;
use advent_rs::year_2018::day_03;
use advent_rs::year_2018::day_04;
use advent_rs::year_2018::day_05;
use advent_rs::year_2018::day_06;
use criterion::{black_box, criterion_group, criterion_main, Criterion};

fn year_2018_day_01(c: &mut Criterion) {
Expand Down Expand Up @@ -80,12 +81,28 @@ fn year_2018_day_05(c: &mut Criterion) {
g2018_day_05.finish();
}

fn year_2018_day_06(c: &mut Criterion) {
let input = include_str!("../inputs/year_2018/day_06_input");
assert_eq!(day_06::day_06_v1(input), 3_251);
assert_eq!(day_06::day_06_v2(input), 47_841);

let mut g2018_day_06 = c.benchmark_group("year_2018::day_06");
g2018_day_06.bench_function("year_2018::day_06_v1", |b| {
b.iter(|| day_06::day_06_v1(black_box(input)))
});
g2018_day_06.bench_function("year_2018::day_06_v2", |b| {
b.iter(|| day_06::day_06_v2(black_box(input)))
});
g2018_day_06.finish();
}

criterion_group!(
benches,
year_2018_day_01,
year_2018_day_02,
year_2018_day_03,
year_2018_day_04,
year_2018_day_05
year_2018_day_05,
year_2018_day_06
);
criterion_main!(benches);
50 changes: 50 additions & 0 deletions inputs/year_2018/day_06_input
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
118, 274
102, 101
216, 203
208, 251
309, 68
330, 93
91, 179
298, 278
201, 99
280, 272
141, 312
324, 290
41, 65
305, 311
198, 68
231, 237
164, 224
103, 189
216, 207
164, 290
151, 91
166, 250
129, 149
47, 231
249, 100
262, 175
299, 237
62, 288
228, 219
224, 76
310, 173
80, 46
312, 65
183, 158
272, 249
57, 141
331, 191
163, 359
271, 210
142, 137
349, 123
55, 268
160, 82
180, 70
231, 243
133, 353
246, 315
164, 206
229, 97
268, 94
9 changes: 9 additions & 0 deletions src/year_2018.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod day_02;
pub mod day_03;
pub mod day_04;
pub mod day_05;
pub mod day_06;

pub fn solve(day: u8, part: u8, input: impl Into<String>) -> Option<String> {
if part > 2 {
Expand All @@ -19,6 +20,7 @@ pub fn solve(day: u8, part: u8, input: impl Into<String>) -> Option<String> {
3 => Some(day_03::day_03(part, input).to_string()),
4 => Some(day_04::day_04(part, input).to_string()),
5 => Some(day_05::day_05(part, input).to_string()),
6 => Some(day_06::day_06(part, input).to_string()),
_ => None,
}
}
Expand Down Expand Up @@ -61,4 +63,11 @@ mod tests {
assert_eq!(day_05::day_05_v1(input), 11_298);
assert_eq!(day_05::day_05_v2(input), 5_148);
}

#[test]
fn day_06() {
let input = include_str!("../inputs/year_2018/day_06_input");
assert_eq!(day_06::day_06_v1(input), 3_251);
assert_eq!(day_06::day_06_v2(input), 47_841);
}
}
136 changes: 136 additions & 0 deletions src/year_2018/day_06.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
use std::cmp::Ordering;
use std::collections::HashMap;
use std::collections::HashSet;

use itertools::Itertools;

type Coordinate = (i32, i32);

struct ChronalCoordinates {
points: HashMap<u8, Coordinate>,
left: i32,
top: i32,
right: i32,
bottom: i32,
}

impl ChronalCoordinates {
fn new(input: &str) -> Self {
let mut left = std::i32::MAX;
let mut top = std::i32::MAX;
let mut right = std::i32::MIN;
let mut bottom = std::i32::MIN;

let points = input
.lines()
.enumerate()
.map(|(line_id, line)| {
let line_id = line_id as u8 + 1u8;
let coord: Coordinate = line
.split(", ")
.map(|v| v.parse::<i32>().unwrap())
.collect_tuple()
.unwrap();
left = std::cmp::min(left, coord.0);
top = std::cmp::min(top, coord.1);
right = std::cmp::max(right, coord.0);
bottom = std::cmp::max(bottom, coord.1);
(line_id, coord)
})
.collect::<HashMap<u8, Coordinate>>();

ChronalCoordinates {
points,
left,
top,
right,
bottom,
}
}

fn solve_part_one(&self) -> u32 {
let mut countable_ids: HashMap<u8, u32> = HashMap::new();
let mut infinite_ids: HashSet<u8> = HashSet::new();

for x in self.left..=self.right {
for y in self.top..=self.bottom {
let mut closest_distance = std::i32::MAX;
let mut closest_id = 0;

for (id, point) in self.points.iter() {
let distance = (x - point.0).abs() + (y - point.1).abs();

match distance.cmp(&closest_distance) {
Ordering::Greater => (),
Ordering::Equal => closest_id = 0,
Ordering::Less => {
closest_distance = distance;
closest_id = *id;
}
}

if closest_id == 0 {
continue;
}
}

if x == self.left || x == self.right || y == self.top || y == self.bottom {
infinite_ids.insert(closest_id);
countable_ids.remove(&closest_id);
} else if !infinite_ids.contains(&closest_id) {
*countable_ids.entry(closest_id).or_insert(0) += 1;
}
}
}

*countable_ids.iter().max_by_key(|(_, v)| *v).unwrap().1
}

fn solve_part_two(&self, max_size: i32) -> u32 {
let mut area = 0;

for x in self.left..=self.right {
for y in self.top..=self.bottom {
let distance = self.points.iter().fold(0, |acc, (_, point)| {
acc + (x - point.0).abs() + (y - point.1).abs()
});
if distance < max_size {
area += 1;
}
}
}

area
}
}

pub fn day_06_v1(input: impl Into<String>) -> u32 {
ChronalCoordinates::new(&input.into()).solve_part_one()
}
pub fn day_06_v2(input: impl Into<String>) -> u32 {
ChronalCoordinates::new(&input.into()).solve_part_two(10_000)
}

solvable!(day_06, day_06_v1, day_06_v2, u32);

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

const SAMPLE: &str = "1, 1\n\
1, 6\n\
8, 3\n\
3, 4\n\
5, 5\n\
8, 9";

#[test]
fn works_with_samples_v1() {
assert_eq!(day_06_v1(SAMPLE), 17);
}

#[test]
fn works_with_samples_v2() {
assert_eq!(ChronalCoordinates::new(SAMPLE).solve_part_two(32), 16);
}
}

0 comments on commit 84c8c5e

Please sign in to comment.