Skip to content

Commit 0957f63

Browse files
author
mflinn-broad
committed
finish day 13
1 parent 5205101 commit 0957f63

File tree

5 files changed

+170
-0
lines changed

5 files changed

+170
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
/target
22
/inputs
3+
/outputs

src/days/day12.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
use crate::util;
22
use petgraph::graphmap::UnGraphMap;
3+
use petgraph::dot::{Dot, Config};
34
use std::collections::HashSet;
5+
use std::fs::File;
6+
use std::io::Write;
47

58
pub fn run() {
69
let raw_input = util::read_input("inputs/day12.txt").unwrap();
710
let input = process(&raw_input);
811

912
println!("Part 1: {}", part_1(&input));
1013
println!("Part 2: {}", part_2(&input));
14+
15+
make_diagram(&input).unwrap();
1116
}
1217

1318
fn process(input: &str) -> Vec<(&str, &str)> {
@@ -118,6 +123,16 @@ fn count_paths_v2<'a>(
118123
count
119124
}
120125

126+
fn make_diagram(input: &Vec<(&str, &str)>) -> std::io::Result<()> {
127+
let cave_map = UnGraphMap::<&str, ()>::from_edges(input);
128+
129+
let cave_diagram = Dot::with_config(&cave_map, &[Config::EdgeNoLabel]);
130+
131+
let cave_diagram = format!("{:?}", cave_diagram);
132+
let mut file = File::create("outputs/cave.txt")?;
133+
file.write_all(cave_diagram.as_bytes())
134+
}
135+
121136
#[cfg(test)]
122137
mod tests {
123138
use super::*;

src/days/day13.rs

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
use itertools::Itertools;
2+
3+
use crate::util;
4+
5+
pub fn run() {
6+
let raw_input = util::read_input("inputs/day13.txt").unwrap();
7+
let input = process(&raw_input);
8+
println!("Part 1: {}", part_1((&input.0, &input.1)));
9+
println!("Part 2: \n{}\n", part_2((input.0, &input.1)));
10+
}
11+
12+
fn part_1(input: (&Vec<Point>, &Vec<Fold>)) -> usize {
13+
let (points, folds) = input;
14+
compute_fold(points, folds[0]).iter().count()
15+
}
16+
17+
fn part_2(input: (Vec<Point>, &Vec<Fold>)) -> String {
18+
let (points, folds) = input;
19+
let final_points: Vec<Point> = folds.iter()
20+
.fold(points, |acc, fold| {
21+
compute_fold(&acc, *fold)
22+
});
23+
24+
let max_x = final_points.iter()
25+
.max_by(|a, b| a.x.cmp(&b.x)).unwrap().x;
26+
let max_y = final_points.iter()
27+
.max_by(|a, b| a.y.cmp(&b.y)).unwrap().y;
28+
29+
let mut grid: Vec<Vec<char>> = vec![vec![' '; max_x + 1]; max_y + 1];
30+
final_points.iter().for_each(|point| grid[point.y][point.x] = '#');
31+
32+
let grid: Vec<String> = grid.iter()
33+
.map(|line| line.iter().collect())
34+
.collect();
35+
36+
grid.join("\n")
37+
38+
}
39+
40+
#[derive(Debug, Clone, Copy)]
41+
struct Fold {
42+
axis: Axis,
43+
pos: usize,
44+
}
45+
46+
#[derive(Debug, Clone, Copy)]
47+
enum Axis {
48+
X,
49+
Y,
50+
}
51+
52+
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
53+
struct Point {
54+
x: usize,
55+
y: usize
56+
}
57+
58+
fn compute_fold(points: &Vec<Point>, fold: Fold) -> Vec<Point> {
59+
let mapped_points: Vec<Point> = match fold.axis {
60+
Axis::X => {
61+
points.iter()
62+
.filter(|point| point.x != fold.pos)
63+
.map(|point| {
64+
Point {
65+
x: fold.pos - (fold.pos.abs_diff(point.x)),
66+
y: point.y
67+
}
68+
})
69+
.collect()
70+
}
71+
Axis::Y => {
72+
points.iter()
73+
.filter(|point| point.y != fold.pos)
74+
.map(|point| {
75+
Point {
76+
x: point.x,
77+
y: fold.pos - (fold.pos.abs_diff(point.y))
78+
}
79+
})
80+
.collect()
81+
}
82+
};
83+
84+
mapped_points.into_iter()
85+
.unique()
86+
.collect()
87+
}
88+
89+
fn process(input: &str) -> (Vec<Point>, Vec<Fold>) {
90+
let (dots_str, folds_str) = input.split_once("\n\n").unwrap();
91+
let dots: Vec<Point> = dots_str.lines()
92+
.map(|line| {
93+
let (x, y) = line.trim().split_once(',').unwrap();
94+
Point {
95+
x: x.parse().unwrap(),
96+
y: y.parse().unwrap(),
97+
}
98+
})
99+
.collect();
100+
101+
let folds: Vec<Fold> = folds_str.lines()
102+
.map(|line| {
103+
line.trim().split_whitespace().nth(2)
104+
})
105+
.map(|fold_str| {
106+
let fold_str = fold_str.unwrap();
107+
let (axis, pos) = fold_str.split_once('=').unwrap();
108+
if axis == "x" {
109+
Fold {
110+
axis: Axis::X,
111+
pos: pos.parse().unwrap(),
112+
}
113+
} else {
114+
Fold {
115+
axis: Axis::Y,
116+
pos: pos.parse().unwrap(),
117+
}
118+
}
119+
})
120+
.collect();
121+
122+
(dots, folds)
123+
}
124+
125+
#[cfg(test)]
126+
mod tests {
127+
use super::*;
128+
extern crate test;
129+
use test::Bencher;
130+
131+
#[bench]
132+
fn bench_part_1(b: &mut Bencher) {
133+
let raw_input = util::read_input("inputs/day13.txt").unwrap();
134+
b.iter(|| {
135+
let input = process(&raw_input);
136+
part_1((&input.0, &input.1));
137+
});
138+
}
139+
140+
#[bench]
141+
fn bench_part_2(b: &mut Bencher) {
142+
let raw_input = util::read_input("inputs/day13.txt").unwrap();
143+
b.iter(|| {
144+
let input = process(&raw_input);
145+
part_2((input.0, &input.1));
146+
});
147+
}
148+
}

src/days/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ pub mod day6;
1010
pub mod day7;
1111
pub mod day8;
1212
pub mod day9;
13+
pub mod day13;

src/main.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ fn main() {
6666
day12::run();
6767
day_durations.insert(12, day_12_start.elapsed());
6868

69+
let day_13_start = Instant::now();
70+
println!("Day 13 --------");
71+
day13::run();
72+
day_durations.insert(13, day_13_start.elapsed());
73+
6974
let total_duration = start.elapsed();
7075

7176
println!("Total time to run all solutions: {:?}", total_duration);

0 commit comments

Comments
 (0)