y2024d10
This commit is contained in:
parent
ada97e5ad6
commit
9b2497f31e
41
y2024/resources/10_input.txt
Normal file
41
y2024/resources/10_input.txt
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
21056789894321015012980123498787601045687
|
||||||
|
32346543765601156703474544567896012138796
|
||||||
|
10107632659892349821563678989345643029655
|
||||||
|
23218101256781015430412101071234754910544
|
||||||
|
14569870345432016321003012560109867801033
|
||||||
|
05678963256789127879854303456078105932122
|
||||||
|
18723450109898038910765210010563254541001
|
||||||
|
69011201298788945125898998323454569679852
|
||||||
|
78760345345654876034787677401235378089760
|
||||||
|
89456896012503876965014586512765432123601
|
||||||
|
32387987003412965872123298703890101984512
|
||||||
|
01291876121101234989456107654965278854603
|
||||||
|
00180145030980325678327890217874369763254
|
||||||
|
14343232145671013454310691307893454610169
|
||||||
|
23432165430110302169234582456732108905678
|
||||||
|
96547078923231231078105673454321097214523
|
||||||
|
87678432214348940987017894765870986341014
|
||||||
|
96589541009857654320123765891963475498765
|
||||||
|
01434630111766789010432143210452560167876
|
||||||
|
32345721210951999016549054789301001456965
|
||||||
|
21076890129810878321678945643219812332109
|
||||||
|
78789001234723765430321238756106734323458
|
||||||
|
09654160345654210389210109987005125010767
|
||||||
|
12323271657601345678780125678014056541893
|
||||||
|
25414987798542343456690034329123987932012
|
||||||
|
56905677810439652987501145016510345801101
|
||||||
|
67856298923128721987432156987421256789210
|
||||||
|
22347107654098910876543087870330107654301
|
||||||
|
11298231012347654305678898981278798987652
|
||||||
|
00109545691056763211219767874569678690343
|
||||||
|
12065456783345894320105656913450569541289
|
||||||
|
43874321092132101899234541002321256632176
|
||||||
|
54930010561001234788765432211056746789045
|
||||||
|
67821123472390545654123101347849839874330
|
||||||
|
78934010589487698763034567456931028765221
|
||||||
|
67785697696590101672105698741022210540100
|
||||||
|
58696788787781234589789789012013307632101
|
||||||
|
49545459810170301075674654323454458989032
|
||||||
|
30432365923965432165463210498569567976543
|
||||||
|
21021876854876523678354112347678678875301
|
||||||
|
30010966763987014589210001456565589765432
|
20
y2024/src/bin/d10.rs
Normal file
20
y2024/src/bin/d10.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use std::fs;
|
||||||
|
|
||||||
|
use y2024::days::d10;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
part1();
|
||||||
|
part2();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part1() {
|
||||||
|
let root = env!("CARGO_MANIFEST_DIR");
|
||||||
|
let content = fs::read_to_string(format!("{root}/resources/10_input.txt")).unwrap();
|
||||||
|
println!("{}", d10::process_part1(&content));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part2() {
|
||||||
|
let root = env!("CARGO_MANIFEST_DIR");
|
||||||
|
let content = fs::read_to_string(format!("{root}/resources/10_input.txt")).unwrap();
|
||||||
|
println!("{}", d10::process_part2(&content));
|
||||||
|
}
|
332
y2024/src/days/d10.rs
Normal file
332
y2024/src/days/d10.rs
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default, Hash, PartialEq, Eq)]
|
||||||
|
struct TrailTile {
|
||||||
|
coords: (i32, i32),
|
||||||
|
height: u8,
|
||||||
|
up: Option<bool>,
|
||||||
|
down: Option<bool>,
|
||||||
|
left: Option<bool>,
|
||||||
|
right: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TrailTile {
|
||||||
|
fn get_neighbors(&self, map: &[Vec<TrailTile>]) -> Vec<TrailTile> {
|
||||||
|
let mut neighbors = Vec::new();
|
||||||
|
if let Some(up) = self.up {
|
||||||
|
if up {
|
||||||
|
let neighbor = map[self.coords.1 as usize - 1][self.coords.0 as usize];
|
||||||
|
if neighbor.height == self.height + 1 {
|
||||||
|
neighbors.push(neighbor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(down) = self.down {
|
||||||
|
if down {
|
||||||
|
let neighbor = map[self.coords.1 as usize + 1][self.coords.0 as usize];
|
||||||
|
if neighbor.height == self.height + 1 {
|
||||||
|
neighbors.push(neighbor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(left) = self.left {
|
||||||
|
if left {
|
||||||
|
let neighbor = map[self.coords.1 as usize][self.coords.0 as usize - 1];
|
||||||
|
if neighbor.height == self.height + 1 {
|
||||||
|
neighbors.push(neighbor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(right) = self.right {
|
||||||
|
if right {
|
||||||
|
let neighbor = map[self.coords.1 as usize][self.coords.0 as usize + 1];
|
||||||
|
if neighbor.height == self.height + 1 {
|
||||||
|
neighbors.push(neighbor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
neighbors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_part1(input: &str) -> i32 {
|
||||||
|
let map = input
|
||||||
|
.lines()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(yidx, line)| {
|
||||||
|
line.as_bytes()
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(xidx, &height)| TrailTile {
|
||||||
|
coords: (xidx as i32, yidx as i32),
|
||||||
|
height,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.collect_vec()
|
||||||
|
})
|
||||||
|
.collect_vec();
|
||||||
|
let mut updated_map = Vec::new();
|
||||||
|
let mut trailheads = Vec::new();
|
||||||
|
for row in map.iter() {
|
||||||
|
let mut new_row = Vec::new();
|
||||||
|
for tile in row {
|
||||||
|
let up = match map.get((tile.coords.1 - 1) as usize) {
|
||||||
|
Some(row) => {
|
||||||
|
let up = row[tile.coords.0 as usize];
|
||||||
|
Some(up.height == tile.height + 1)
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
let down = match map.get((tile.coords.1 + 1) as usize) {
|
||||||
|
Some(row) => {
|
||||||
|
let down = row[tile.coords.0 as usize];
|
||||||
|
Some(down.height == tile.height + 1)
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
let left = map[tile.coords.1 as usize]
|
||||||
|
.get((tile.coords.0 - 1) as usize)
|
||||||
|
.map(|left| left.height == tile.height + 1);
|
||||||
|
let right = map[tile.coords.1 as usize]
|
||||||
|
.get((tile.coords.0 + 1) as usize)
|
||||||
|
.map(|right| right.height == tile.height + 1);
|
||||||
|
let tile = TrailTile {
|
||||||
|
up,
|
||||||
|
down,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
..*tile
|
||||||
|
};
|
||||||
|
if tile.height == b'0' {
|
||||||
|
trailheads.push(tile);
|
||||||
|
}
|
||||||
|
//print!(
|
||||||
|
// "{}: {}, {} ",
|
||||||
|
// tile.height as char, tile.coords.0, tile.coords.1
|
||||||
|
//);
|
||||||
|
new_row.push(tile);
|
||||||
|
}
|
||||||
|
//println!();
|
||||||
|
updated_map.push(new_row);
|
||||||
|
}
|
||||||
|
let mut res = 0;
|
||||||
|
//println!("0 {trailheads:?}");
|
||||||
|
for trailhead in trailheads {
|
||||||
|
let mut neighbors = trailhead.get_neighbors(&updated_map);
|
||||||
|
//println!("1 {neighbors:?}");
|
||||||
|
for _idx in 2..=9 {
|
||||||
|
//println!("{idx}");
|
||||||
|
if neighbors.is_empty() {
|
||||||
|
//println!("empty");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let inner_neighbors = neighbors.clone();
|
||||||
|
neighbors.clear();
|
||||||
|
for neighbor in inner_neighbors {
|
||||||
|
neighbors.extend_from_slice(&neighbor.get_neighbors(&updated_map));
|
||||||
|
}
|
||||||
|
//println!("{idx} {neighbors:?}");
|
||||||
|
}
|
||||||
|
res += neighbors.iter().unique().count();
|
||||||
|
}
|
||||||
|
res as i32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_part2(input: &str) -> i32 {
|
||||||
|
let map = input
|
||||||
|
.lines()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(yidx, line)| {
|
||||||
|
line.as_bytes()
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(xidx, &height)| TrailTile {
|
||||||
|
coords: (xidx as i32, yidx as i32),
|
||||||
|
height,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.collect_vec()
|
||||||
|
})
|
||||||
|
.collect_vec();
|
||||||
|
let mut updated_map = Vec::new();
|
||||||
|
let mut trailheads = Vec::new();
|
||||||
|
for row in map.iter() {
|
||||||
|
let mut new_row = Vec::new();
|
||||||
|
for tile in row {
|
||||||
|
let up = match map.get((tile.coords.1 - 1) as usize) {
|
||||||
|
Some(row) => {
|
||||||
|
let up = row[tile.coords.0 as usize];
|
||||||
|
Some(up.height == tile.height + 1)
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
let down = match map.get((tile.coords.1 + 1) as usize) {
|
||||||
|
Some(row) => {
|
||||||
|
let down = row[tile.coords.0 as usize];
|
||||||
|
Some(down.height == tile.height + 1)
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
let left = map[tile.coords.1 as usize]
|
||||||
|
.get((tile.coords.0 - 1) as usize)
|
||||||
|
.map(|left| left.height == tile.height + 1);
|
||||||
|
let right = map[tile.coords.1 as usize]
|
||||||
|
.get((tile.coords.0 + 1) as usize)
|
||||||
|
.map(|right| right.height == tile.height + 1);
|
||||||
|
let tile = TrailTile {
|
||||||
|
up,
|
||||||
|
down,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
..*tile
|
||||||
|
};
|
||||||
|
if tile.height == b'0' {
|
||||||
|
trailheads.push(tile);
|
||||||
|
}
|
||||||
|
//print!(
|
||||||
|
// "{}: {}, {} ",
|
||||||
|
// tile.height as char, tile.coords.0, tile.coords.1
|
||||||
|
//);
|
||||||
|
new_row.push(tile);
|
||||||
|
}
|
||||||
|
//println!();
|
||||||
|
updated_map.push(new_row);
|
||||||
|
}
|
||||||
|
let mut res = 0;
|
||||||
|
//println!("0 {trailheads:?}");
|
||||||
|
for trailhead in trailheads {
|
||||||
|
let mut neighbors = trailhead.get_neighbors(&updated_map);
|
||||||
|
//println!("1 {neighbors:?}");
|
||||||
|
for _idx in 2..=9 {
|
||||||
|
//println!("{idx}");
|
||||||
|
if neighbors.is_empty() {
|
||||||
|
//println!("empty");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let inner_neighbors = neighbors.clone();
|
||||||
|
neighbors.clear();
|
||||||
|
for neighbor in inner_neighbors {
|
||||||
|
neighbors.extend_from_slice(&neighbor.get_neighbors(&updated_map));
|
||||||
|
}
|
||||||
|
//println!("{idx} {neighbors:?}");
|
||||||
|
}
|
||||||
|
res += neighbors.len();
|
||||||
|
}
|
||||||
|
res as i32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const INPUT_SMALL: &str = "0123
|
||||||
|
1234
|
||||||
|
8765
|
||||||
|
9876";
|
||||||
|
|
||||||
|
const INPUT_LARGE: &str = "89010123
|
||||||
|
78121874
|
||||||
|
87430965
|
||||||
|
96549874
|
||||||
|
45678903
|
||||||
|
32019012
|
||||||
|
01329801
|
||||||
|
10456732";
|
||||||
|
|
||||||
|
const INPUT_SIMPLIFIED_1: &str = "...0...
|
||||||
|
...1...
|
||||||
|
...2...
|
||||||
|
6543456
|
||||||
|
7.....7
|
||||||
|
8.....8
|
||||||
|
9.....9";
|
||||||
|
const INPUT_SIMPLIFIED_2: &str = "..90..9
|
||||||
|
...1.98
|
||||||
|
...2..7
|
||||||
|
6543456
|
||||||
|
765.987
|
||||||
|
876....
|
||||||
|
987....";
|
||||||
|
const INPUT_SIMPLIFIED_3: &str = "10..9..
|
||||||
|
2...8..
|
||||||
|
3...7..
|
||||||
|
4567654
|
||||||
|
...8..3
|
||||||
|
...9..2
|
||||||
|
.....01";
|
||||||
|
|
||||||
|
const INPUT_SIMPLIFIED_4: &str = ".....0.
|
||||||
|
..4321.
|
||||||
|
..5..2.
|
||||||
|
..6543.
|
||||||
|
..7..4.
|
||||||
|
..8765.
|
||||||
|
..9....";
|
||||||
|
|
||||||
|
const INPUT_SIMPLIFIED_5: &str = "012345
|
||||||
|
123456
|
||||||
|
234567
|
||||||
|
345678
|
||||||
|
4.6789
|
||||||
|
56789.";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1_small() {
|
||||||
|
let result = process_part1(INPUT_SMALL);
|
||||||
|
assert_eq!(result, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1_large() {
|
||||||
|
let result = process_part1(INPUT_LARGE);
|
||||||
|
assert_eq!(result, 36);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1_simplified_1() {
|
||||||
|
let result = process_part1(INPUT_SIMPLIFIED_1);
|
||||||
|
assert_eq!(result, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1_simplified_2() {
|
||||||
|
let result = process_part1(INPUT_SIMPLIFIED_2);
|
||||||
|
assert_eq!(result, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1_simplified_3() {
|
||||||
|
let result = process_part1(INPUT_SIMPLIFIED_3);
|
||||||
|
assert_eq!(result, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2_small() {
|
||||||
|
let result = process_part2(INPUT_SMALL);
|
||||||
|
assert_eq!(result, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2_large() {
|
||||||
|
let result = process_part2(INPUT_LARGE);
|
||||||
|
assert_eq!(result, 81);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2_simplified_2() {
|
||||||
|
let result = process_part2(INPUT_SIMPLIFIED_2);
|
||||||
|
assert_eq!(result, 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2_simplified_4() {
|
||||||
|
let result = process_part2(INPUT_SIMPLIFIED_4);
|
||||||
|
assert_eq!(result, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2_simplified_5() {
|
||||||
|
let result = process_part2(INPUT_SIMPLIFIED_5);
|
||||||
|
assert_eq!(result, 227);
|
||||||
|
}
|
||||||
|
}
|
@ -7,3 +7,5 @@ pub mod d6;
|
|||||||
pub mod d7;
|
pub mod d7;
|
||||||
pub mod d8;
|
pub mod d8;
|
||||||
pub mod d9;
|
pub mod d9;
|
||||||
|
|
||||||
|
pub mod d10;
|
||||||
|
Loading…
Reference in New Issue
Block a user