Solutions for 2022, as well as 2015-2018 and 2019 up to day 11
This commit is contained in:
commit
1895197c49
722 changed files with 375457 additions and 0 deletions
8
2018/day06_chronal_coordinates/Cargo.toml
Normal file
8
2018/day06_chronal_coordinates/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day06_chronal_coordinates"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
108
2018/day06_chronal_coordinates/challenge.txt
Normal file
108
2018/day06_chronal_coordinates/challenge.txt
Normal file
|
@ -0,0 +1,108 @@
|
|||
The device on your wrist beeps several times, and once again you feel like you're falling.
|
||||
|
||||
"Situation critical," the device announces. "Destination indeterminate. Chronal interference detected. Please specify new target coordinates."
|
||||
|
||||
The device then produces a list of coordinates (your puzzle input). Are they places it thinks are safe or dangerous? It recommends you check manual page 729. The Elves did not give you a manual.
|
||||
|
||||
*If they're dangerous,* maybe you can minimize the danger by finding the coordinate that gives the largest distance from the other points.
|
||||
|
||||
Using only the [Manhattan distance](https://en.wikipedia.org/wiki/Taxicab_geometry), determine the *area* around each coordinate by counting the number of [integer](https://en.wikipedia.org/wiki/Integer) X,Y locations that are *closest* to that coordinate (and aren't *tied in distance* to any other coordinate).
|
||||
|
||||
Your goal is to find the size of the *largest area* that isn't infinite. For example, consider the following list of coordinates:
|
||||
|
||||
```
|
||||
1, 1
|
||||
1, 6
|
||||
8, 3
|
||||
3, 4
|
||||
5, 5
|
||||
8, 9
|
||||
|
||||
```
|
||||
|
||||
If we name these coordinates `A` through `F`, we can draw them on a grid, putting `0,0` at the top left:
|
||||
|
||||
```
|
||||
..........
|
||||
.A........
|
||||
..........
|
||||
........C.
|
||||
...D......
|
||||
.....E....
|
||||
.B........
|
||||
..........
|
||||
..........
|
||||
........F.
|
||||
|
||||
```
|
||||
|
||||
This view is partial - the actual grid extends infinitely in all directions. Using the Manhattan distance, each location's closest coordinate can be determined, shown here in lowercase:
|
||||
|
||||
```
|
||||
aaaaa.cccc
|
||||
aAaaa.cccc
|
||||
aaaddecccc
|
||||
aadddeccCc
|
||||
..dDdeeccc
|
||||
bb.deEeecc
|
||||
bBb.eeee..
|
||||
bbb.eeefff
|
||||
bbb.eeffff
|
||||
bbb.ffffFf
|
||||
|
||||
```
|
||||
|
||||
Locations shown as `.` are equally far from two or more coordinates, and so they don't count as being closest to any.
|
||||
|
||||
In this example, the areas of coordinates A, B, C, and F are infinite - while not shown here, their areas extend forever outside the visible grid. However, the areas of coordinates D and E are finite: D is closest to 9 locations, and E is closest to 17 (both including the coordinate's location itself). Therefore, in this example, the size of the largest area is *17*.
|
||||
|
||||
*What is the size of the largest area* that isn't infinite?
|
||||
|
||||
Your puzzle answer was `3251`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
On the other hand, *if the coordinates are safe*, maybe the best you can do is try to find a *region* near as many coordinates as possible.
|
||||
|
||||
For example, suppose you want the sum of the [Manhattan distance](https://en.wikipedia.org/wiki/Taxicab_geometry) to all of the coordinates to be *less than 32*. For each location, add up the distances to all of the given coordinates; if the total of those distances is less than 32, that location is within the desired region. Using the same coordinates as above, the resulting region looks like this:
|
||||
|
||||
```
|
||||
..........
|
||||
.A........
|
||||
..........
|
||||
...###..C.
|
||||
..#D###...
|
||||
..###E#...
|
||||
.B.###....
|
||||
..........
|
||||
..........
|
||||
........F.
|
||||
|
||||
```
|
||||
|
||||
In particular, consider the highlighted location `4,3` located at the top middle of the region. Its calculation is as follows, where `abs()` is the [absolute value](https://en.wikipedia.org/wiki/Absolute_value) function:
|
||||
|
||||
* Distance to coordinate A: `abs(4-1) + abs(3-1) = 5`
|
||||
* Distance to coordinate B: `abs(4-1) + abs(3-6) = 6`
|
||||
* Distance to coordinate C: `abs(4-8) + abs(3-3) = 4`
|
||||
* Distance to coordinate D: `abs(4-3) + abs(3-4) = 2`
|
||||
* Distance to coordinate E: `abs(4-5) + abs(3-5) = 3`
|
||||
* Distance to coordinate F: `abs(4-8) + abs(3-9) = 10`
|
||||
* Total distance: `5 + 6 + 4 + 2 + 3 + 10 = 30`
|
||||
|
||||
Because the total distance to all coordinates (`30`) is less than 32, the location is *within* the region.
|
||||
|
||||
This region, which also includes coordinates D and E, has a total size of *16*.
|
||||
|
||||
Your actual region will need to be much larger than this example, though, instead including all locations with a total distance of less than *10000*.
|
||||
|
||||
*What is the size of the region containing all locations which have a total distance to all given coordinates of less than 10000?*
|
||||
|
||||
Your puzzle answer was `47841`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, you should [return to your Advent calendar](/2018) and try another puzzle.
|
||||
|
||||
If you still want to see it, you can [get your puzzle input](6/input).
|
79
2018/day06_chronal_coordinates/src/lib.rs
Normal file
79
2018/day06_chronal_coordinates/src/lib.rs
Normal file
|
@ -0,0 +1,79 @@
|
|||
use std::collections::{HashSet, HashMap};
|
||||
|
||||
pub fn run(input: &str, safe_distance: isize) -> (usize, usize) {
|
||||
let list: Vec<_> = input.lines().map(|line| line.split_once(", ").unwrap()).collect();
|
||||
let coordinates: Vec<_> = list.iter().map(|s| (s.0.parse::<isize>().unwrap(), s.1.parse::<isize>().unwrap())).collect();
|
||||
let areas = get_areas(&coordinates);
|
||||
// dbg!(&areas);
|
||||
let first = areas.iter().filter(|a| **a < usize::MAX).max().unwrap();
|
||||
let second = safe_area(&coordinates, safe_distance);
|
||||
(*first, second)
|
||||
}
|
||||
|
||||
fn safe_area(coordinates: &[(isize, isize)], safe_distance: isize) -> usize {
|
||||
let first = coordinates[0];
|
||||
let mut area = 0;
|
||||
(first.0-safe_distance/4..first.0+safe_distance/4).for_each(|x| {
|
||||
(first.1-safe_distance/4..first.1+safe_distance/4).for_each(|y| {
|
||||
if coordinates.iter().map(|c| c.0.abs_diff(x) + c.1.abs_diff(y)).sum::<usize>() < safe_distance as usize {
|
||||
area += 1;
|
||||
}
|
||||
});
|
||||
});
|
||||
area
|
||||
}
|
||||
|
||||
fn get_areas(coordinates: &[(isize, isize)]) -> Vec<usize> {
|
||||
let mut found = HashSet::new();
|
||||
for c in coordinates { found.insert(*c); }
|
||||
let mut sizes = vec![1; coordinates.len()];
|
||||
let mut last_step: Vec<Vec<(isize, isize)>> = coordinates.iter().map(|c| Vec::from([*c])).chain(Vec::new()).collect();
|
||||
for _ in 0..500 {
|
||||
let mut found_this_step = HashMap::new();
|
||||
for (origin_idx, origin) in last_step.iter().enumerate() {
|
||||
for open in origin {
|
||||
for neighbour_offset in [(-1, 0), (1, 0), (0, -1), (0, 1)] {
|
||||
let neighbour = (open.0 + neighbour_offset.0, open.1 + neighbour_offset.1);
|
||||
if !found.contains(&neighbour) {
|
||||
found_this_step.entry(neighbour).and_modify(|o| if *o != origin_idx { *o = last_step.len()-1; }).or_insert(origin_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for v in &mut last_step {
|
||||
*v = Vec::new();
|
||||
}
|
||||
for (coords, origin) in found_this_step {
|
||||
last_step[origin].push(coords);
|
||||
if origin < sizes.len()-1 {
|
||||
sizes[origin] += 1;
|
||||
}
|
||||
found.insert(coords);
|
||||
}
|
||||
}
|
||||
last_step.iter().take(coordinates.len()-1).enumerate().filter(|(_idx, v)| !v.is_empty()).map(|(idx, _v)| idx).for_each(|idx| sizes[idx] = usize::MAX);
|
||||
|
||||
sizes
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {name}")[..]).trim().to_string()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input, 32), (17, 16));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input, 10_000), (3251, 47841));
|
||||
}
|
||||
}
|
50
2018/day06_chronal_coordinates/tests/challenge_input
Normal file
50
2018/day06_chronal_coordinates/tests/challenge_input
Normal file
|
@ -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
|
6
2018/day06_chronal_coordinates/tests/sample_input
Normal file
6
2018/day06_chronal_coordinates/tests/sample_input
Normal file
|
@ -0,0 +1,6 @@
|
|||
1, 1
|
||||
1, 6
|
||||
8, 3
|
||||
3, 4
|
||||
5, 5
|
||||
8, 9
|
Loading…
Add table
Add a link
Reference in a new issue