Skip to content

Commit 7ded964

Browse files
committed
Day 12 - Hill Climbing Algorithm ⛰
1 parent cae50f6 commit 7ded964

File tree

5 files changed

+206
-0
lines changed

5 files changed

+206
-0
lines changed

.github/workflows/Day-12.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Day-12
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
paths:
7+
- '**12*'
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@v2
15+
- name: Build
16+
run: cargo build --release --verbose
17+
- name: Run
18+
run: time target/release/aoc 12

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ This is primarily a learning experience, and the code may not be following best
1919
| 9 | Rope Bridge | | | |
2020
| 10 | Cathode-Ray Tube | [src/day_10.rs](src/day_10.rs) | [src/day_10.data](src/day_10.data) | `0m0.003s` | [![Day-10](https://github.com/leifgehrmann/advent-of-code-2022/actions/workflows/Day-10.yml/badge.svg?branch=main)](https://github.com/leifgehrmann/advent-of-code-2022/actions/workflows/Day-10.yml?query=branch%3Amain)
2121
| 11 | Monkey in the Middle | [src/day_11.rs](src/day_11.rs) | [src/day_11.data](src/day_11.data) | `0m0.030s` | [![Day-11](https://github.com/leifgehrmann/advent-of-code-2022/actions/workflows/Day-11.yml/badge.svg?branch=main)](https://github.com/leifgehrmann/advent-of-code-2022/actions/workflows/Day-11.yml?query=branch%3Amain)
22+
| 12 | Hill Climbing Algorithm | [src/day_12.rs](src/day_12.rs) | [src/day_12.data](src/day_12.data) | | [![Day-12](https://github.com/leifgehrmann/advent-of-code-2022/actions/workflows/Day-12.yml/badge.svg?branch=main)](https://github.com/leifgehrmann/advent-of-code-2022/actions/workflows/Day-12.yml?query=branch%3Amain)
2223

2324
_The measured execution time in GitHub Actions_
2425

src/day_12.data

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
abccccccccaaaaaaaccaaaaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccaaaaaa
2+
abccccccccaaaaaaaccaaaaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccaaaaaa
3+
abccccccccccaaaaaaccaaaaaaaaaaaaaaaaccccccccccccccccacccccccccccccccccccaaaaa
4+
abcccccaaaacaaaaaaccaaaaaaaaaaaaaaaaacccccccccccccccaaaccccaccccccccccccccaaa
5+
abccccaaaaacaaccccccaaaaaacaaacaacaaaaaaacccccccccccaaaacccaacccccccccccccaaa
6+
abaaccaaaaaaccccaaacaaaacacaaacaaccaaaaaacccccccccccaklaccccccccccccccccccaac
7+
abaaccaaaaaaccaaaaaacccccccaaacccaaaaaaaccccccccccckkkllllccccccccccccccccccc
8+
abaaccaaaaaaccaaaaaacccccccaaaaacaaaaaaacccccccccckkkklllllcccccccaaaccaccccc
9+
abacccccaacccccaaaaacccccccaaaaaccaaaaaaacccccccckkkkpppllllccccccaaaaaaccccc
10+
abacccccccccccaaaaacccccccccaaaacccaaaaaaccccccckkkkpppppplllccccddddaaaccccc
11+
abccccccccccccaaaaaccccccccccaaaccaaaccccccccccckkkppppppppllllldddddddaccccc
12+
abccacccccccccccccccccccccccccccccaaccccccccccckkkopppupppplllmmmmdddddaacccc
13+
abccaaacaaaccccccccccccccccccccaaaaaaaaccccccckkkkopuuuuupppllmmmmmmddddacccc
14+
abccaaaaaaaccccccccccccccccccccaaaaaaaacccccjjkkkooouuuuuuppqqqqqmmmmddddcccc
15+
abccaaaaaacccccccccccccccaaccccccaaaacccccjjjjjjoooouuxuuuppqqqqqqmmmmdddcccc
16+
abcaaaaaaaacccccccccccccaaacccccaaaaaccccjjjjoooooouuuxxuuvvvvvqqqqmmmdddcccc
17+
abaaaaaaaaaacccccccaaaaaaacaacccaacaaacccjjjooooouuuuxxxxvvvvvvvqqqmmmdddcccc
18+
abaaaaaaaaaacccaaacaaaaaaaaaacccacccaaccjjjooootttuuuxxxyyvyyvvvqqqmmmeeecccc
19+
abcccaaacaaacccaaaaaaacaaaaaccccccccccccjjjooottttxxxxxxyyyyyyvvqqqmmmeeccccc
20+
abcccaaacccccccaaaaaacaaaaaccccaaccaacccjjjnnntttxxxxxxxyyyyyvvvqqqnneeeccccc
21+
SbccccaacccccccaaaaaaaaacaaacccaaaaaacccjjjnnntttxxxEzzzzyyyyvvqqqnnneeeccccc
22+
abcccccccccccccaaaaaaaaacaaccccaaaaaccccjjjnnnttttxxxxyyyyyvvvrrrnnneeecccccc
23+
abcccaacccccccaaaaaaaaaccccccccaaaaaacccciiinnnttttxxxyyyyywvvrrrnnneeecccccc
24+
abcccaaaaaaccaaaaaaaacccccccccaaaaaaaaccciiiinnnttttxyyywyyywvrrrnnneeecccccc
25+
abcccaaaaaaccaaaaaaaacccccccccaaaaaaaacccciiinnnntttxwywwyyywwwrrnnneeecccccc
26+
abcaaaaaaaccaaaaaaaaaccccccccccccaacccccccciiinnnttwwwwwwwwwwwwrrnnneeecccccc
27+
abcaaaaaaaccaaaaaacccccccccccccccaaccccccaaiiiinnttwwwwwwwwwwwrrrnnnffecccccc
28+
abcccaaaaaaccaaaaaccccccccccccccccccccaaaaaciiinnssswwwssssrwwrrrnnnfffcccccc
29+
abaacaaccaaccaaaccccccccaacccccccccccccaaaaaiiinnssssssssssrrrrrronnfffcccccc
30+
abaccaaccaacccccccccaaacaacccccccccccccaaaaaiiimmmssssssmoosrrrrooonffaaacccc
31+
abaaaccccaaaaaaccccccaaaaaccccccccccccaaaaaccihmmmmsssmmmoooooooooofffaaacccc
32+
abaaaccccaaaaaacccccccaaaaaacccccccccccccaacchhhmmmmmmmmmoooooooooffffaaccccc
33+
abaacccaaaaaaaccccccaaaaaaaaccccaaccccccccccchhhhmmmmmmmgggggooofffffaaaccccc
34+
abaacccaaaaaaaccccccaaaaaaaccccaaaaccccccccccchhhhmmmmhggggggggfffffaaaaccccc
35+
abccccccaaaaaaacccccaacaaaaacccaaaaccccccccccchhhhhhhhggggggggggfffaacaaccccc
36+
abccaacccaaaaaaccccccccaaaaaccaaaaacccccccccccchhhhhhhggaaaaaaccccccccccccccc
37+
abccaaaccaaccccccccccccccaaaaaaaaaccccccccccccccchhhhaaaccaaaacccccccccccccaa
38+
abaaaaaaaccccccccccccccccaaaaaaaaccccccccccccccccccccaaaccccaaccccccccccccaaa
39+
abaaaaaaaccccccccaaaccccacaaaaaacccccccccccccccccccccaaaccccccccccccccccccaaa
40+
abaaaaaacccccccaaaaacaaaaaaaaaaacccccccccccccccccccccaaccccccccccccccccaaaaaa
41+
abaaaaaacccccccaaaaaaaaaaaaaaaaaaacccccccccccccccccccccccccccccccccccccaaaaaa

src/day_12.rs

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
use crate::input_reader;
2+
use std::cmp::Ordering;
3+
use std::collections::VecDeque;
4+
use std::collections::HashMap;
5+
use std::hash::Hash;
6+
use std::hash::Hasher;
7+
8+
type Cost = usize;
9+
10+
#[derive(Debug, Clone, Copy)]
11+
struct Pos {
12+
x: i32,
13+
y: i32,
14+
}
15+
16+
impl Hash for Pos {
17+
fn hash<H: Hasher>(&self, state: &mut H) {
18+
self.x.hash(state);
19+
self.y.hash(state);
20+
}
21+
}
22+
23+
impl PartialEq for Pos {
24+
fn eq(&self, other: &Self) -> bool {
25+
self.x == other.x && self.y == other.y
26+
}
27+
}
28+
impl Eq for Pos {}
29+
30+
#[derive(Debug, Eq)]
31+
struct Processable {
32+
pos: Pos,
33+
net_cost: Cost
34+
}
35+
36+
impl Processable {
37+
pub fn new(pos: Pos, net_cost: Cost) -> Self {
38+
Processable {
39+
pos,
40+
net_cost
41+
}
42+
}
43+
}
44+
45+
impl PartialOrd for Processable {
46+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
47+
Some(self.cmp(other))
48+
}
49+
}
50+
51+
impl Ord for Processable {
52+
fn cmp(&self, other: &Self) -> Ordering {
53+
self.net_cost.cmp(&other.net_cost)
54+
}
55+
}
56+
57+
impl PartialEq for Processable {
58+
fn eq(&self, other: &Self) -> bool {
59+
self.net_cost == other.net_cost
60+
}
61+
}
62+
63+
fn get_neighbors(map: &Vec<Vec<i32>>, pos: Pos) -> Vec<Pos> {
64+
let w = map[0].len() as i32;
65+
let h = map.len() as i32;
66+
let points: Vec<(i32, i32)> = vec![(1, 0), (-1, 0), (0, 1), (0, -1)];
67+
return points.iter().map(|&point| {
68+
let new_pos = Pos { x: pos.x + point.0, y: pos.y + point.1 };
69+
if new_pos.x < 0 ||
70+
new_pos.x >= w ||
71+
new_pos.y < 0 ||
72+
new_pos.y >= h
73+
{
74+
return None;
75+
}
76+
let a = map[pos.y as usize][pos.x as usize];
77+
let b = map[new_pos.y as usize][new_pos.x as usize];
78+
if a + 1 < b {
79+
return None;
80+
}
81+
return Some(new_pos);
82+
}).filter_map(|e| e).collect()
83+
}
84+
85+
fn part1(map: &Vec<Vec<i32>>, start: Pos, end: Pos) {
86+
// A simplified version of Dijkstra.
87+
let mut processed: HashMap<Pos, Cost> = HashMap::new();
88+
let mut to_process: VecDeque<Processable> = VecDeque::new();
89+
to_process.push_back(Processable::new(start, 0));
90+
processed.insert(start, 0);
91+
92+
while to_process.len() > 0 {
93+
// Ensure elements are from least costly to most costly.
94+
to_process.make_contiguous().sort();
95+
let processable = to_process.pop_front().unwrap();
96+
for neighbor in get_neighbors(map, processable.pos) {
97+
let new_cost = processable.net_cost + 1;
98+
// Skip points that have already been processed
99+
if processed.contains_key(&neighbor) && processed[&neighbor] <= new_cost {
100+
continue;
101+
}
102+
processed.insert(neighbor, new_cost);
103+
to_process.push_back(Processable::new(neighbor, new_cost));
104+
}
105+
}
106+
println!("Part 1: {}", processed.get(&end).unwrap());
107+
}
108+
109+
pub fn run() {
110+
let input = input_reader::read_file_in_cwd("src/day_12.data");
111+
112+
let lines: Vec<&str> = input.split("\n").collect();
113+
let mut start_y = 0;
114+
let mut start_x = 0;
115+
let mut end_y = 0;
116+
let mut end_x = 0;
117+
let mut y = 0;
118+
let mut x = 0;
119+
let map: Vec<Vec<i32>> = lines.iter().map(|&val| {
120+
y += 1;
121+
x = 0;
122+
let cells: Vec<char> = val.chars().collect();
123+
return cells.iter().map(|&val| {
124+
x += 1;
125+
// Make comparing values easier by converting special cases like S and E
126+
// as numeric values.
127+
if val == 'S' {
128+
start_x = x - 1;
129+
start_y = y - 1;
130+
return 'a' as i32 - 1
131+
} else if val == 'E' {
132+
end_x = x - 1;
133+
end_y = y - 1;
134+
return 'z' as i32 + 1
135+
}
136+
return val as i32
137+
}).collect();
138+
}).collect();
139+
140+
let start = Pos { x: start_x, y: start_y };
141+
let end = Pos { x: end_x, y: end_y };
142+
143+
part1(&map, start, end);
144+
}

src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ mod day_08;
1010
// mod day_09;
1111
mod day_10;
1212
mod day_11;
13+
mod day_12;
1314

1415
fn main() {
1516
let day: String = std::env::args().nth(1).expect(
@@ -29,6 +30,7 @@ fn main() {
2930
// "09" => day_09::run(),
3031
"10" => day_10::run(),
3132
"11" => day_11::run(),
33+
"12" => day_12::run(),
3234
_ => println!("No valid day given. Possible options are: 01-25."),
3335
};
3436
}

0 commit comments

Comments
 (0)