Skip to content

Commit

Permalink
Day 6 (unoptimized)
Browse files Browse the repository at this point in the history
  • Loading branch information
UnderscoreTud committed Dec 6, 2024
1 parent cea0792 commit 3342276
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 9 deletions.
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
<!--- benchmarking table --->
## Benchmarks

| Day | Part 1 | Part 2 |
| :---: | :---: | :---: |
| [Day 1](./src/bin/01.rs) | `61.4µs` | `106.8µs` |
| [Day 2](./src/bin/02.rs) | `220.6µs` | `404.8µs` |
| [Day 3](./src/bin/03.rs) | `561.0µs` | `565.5µs` |
| [Day 4](./src/bin/04.rs) | `560.8µs` | `161.9µs` |
| [Day 5](./src/bin/05.rs) | `340.4µs` | `328.0µs` |

**Total: 3.31ms**
| Day | Part 1 | Part 2 |
|:---------------------------------------:| :---: | :---: |
| [Day 1](./src/bin/01.rs) | `61.4µs` | `106.8µs` |
| [Day 2](./src/bin/02.rs) | `220.6µs` | `404.8µs` |
| [Day 3](./src/bin/03.rs) | `561.0µs` | `565.5µs` |
| [Day 4](./src/bin/04.rs) | `560.8µs` | `161.9µs` |
| [Day 5](./src/bin/05.rs) | `344.6µs` | `323.6µs` |
| [Day 6](./src/bin/06.rs) (unoptimized) | `494.4µs` | `956.4ms` |

**Total: 960.21ms**
<!--- benchmarking table --->

---
Expand Down
10 changes: 10 additions & 0 deletions data/examples/06.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
....#.....
.........#
..........
..#.......
.......#..
..........
.#..^.....
........#.
#.........
......#...
141 changes: 141 additions & 0 deletions src/bin/06.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
use std::collections::HashSet;
use itertools::Itertools;

advent_of_code::solution!(6);

struct Map {
dimensions: (isize, isize),
obstacles: HashSet<(isize, isize)>,
visited_pos: HashSet<(isize, isize)>,
starting_pos: (isize, isize),
}

impl Map {

fn parse(input: &str) -> Map {
let (mut columns, mut rows) = (0, 0);
let mut starting_pos = (0, 0);
let mut obstacles = HashSet::new();
let visited_pos = HashSet::new();
input.lines()
.enumerate()
.map(|(y, line)| {
rows = y;
line.chars()
.enumerate()
.map(|(x, char)| {
columns = x;
match char {
'^' => starting_pos = (x as isize, y as isize),
'#' => {
obstacles.insert((x as isize, y as isize));
}
_ => {}
}
char
})
.collect_vec()
})
.collect_vec();
Map {
dimensions: (columns as isize + 1, rows as isize + 1),
obstacles,
visited_pos,
starting_pos,
}
}

fn is_obstacle(&self, pos: &(isize, isize)) -> bool {
self.obstacles.contains(pos)
}

fn farthest_point(&mut self, starting_pos: &(isize, isize), direction: &(isize, isize)) -> Option<(isize, isize)> {
let mut pos = *starting_pos;
while self.is_in_map(&pos) {
self.visited_pos.insert(pos);
let next_pos = (pos.0 + direction.0, pos.1 + direction.1);
if self.is_obstacle(&next_pos) {
return Some(pos);
}
pos = next_pos;
}
None
}

fn is_in_map(&self, pos: &(isize, isize)) -> bool {
(0..self.dimensions.0).contains(&pos.0) && (0..self.dimensions.1).contains(&pos.1)
}

fn predict_path(&mut self) -> bool {
let mut current_pos = self.starting_pos;
let mut direction = 0;
while let Some(next_pos) = self.farthest_point(&current_pos, &DIRECTIONS[direction]) {
direction = (direction + 1) % 4;
current_pos = next_pos;
}
false
}

fn has_loop(&mut self) -> bool {
let mut current_pos = self.starting_pos;
let mut direction = 0;
let mut turns = HashSet::new();
while let Some(next_pos) = self.farthest_point(&current_pos, &DIRECTIONS[direction]) {
if turns.contains(&(current_pos, direction)) {
return true;
}
turns.insert((current_pos, direction));
direction = (direction + 1) % 4;
current_pos = next_pos;
}
false
}

}

const DIRECTIONS: [(isize, isize); 4] = [
(0, -1),
(1, 0),
(0, 1),
(-1, 0),
];

pub fn part_one(input: &str) -> Option<u32> {
let mut map = Map::parse(input);
map.predict_path();
Some(map.visited_pos.len() as u32)
}

pub fn part_two(input: &str) -> Option<u32> {
let mut obstructions = 0;
let mut map = Map::parse(input);
map.predict_path();
let mut original_path = map.visited_pos;
original_path.remove(&map.starting_pos);
for pos in original_path {
map.obstacles.insert(pos);
map.visited_pos = HashSet::new();
if map.has_loop() {
obstructions += 1;
}
map.obstacles.remove(&pos);
}
Some(obstructions)
}

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

#[test]
fn test_part_one() {
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, Some(41));
}

#[test]
fn test_part_two() {
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, Some(6));
}
}

0 comments on commit 3342276

Please sign in to comment.