This commit is contained in:
Fabian Schmidt 2024-12-10 10:32:05 +01:00
parent ada97e5ad6
commit 9b2497f31e
4 changed files with 395 additions and 0 deletions

View 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
View 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
View 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);
}
}

View File

@ -7,3 +7,5 @@ pub mod d6;
pub mod d7;
pub mod d8;
pub mod d9;
pub mod d10;