Browse Source

Add day 3 part 2

master
parent
commit
7fe18a13d4
  1. 61
      src/day3.rs
  2. 2
      src/main.rs

61
src/day3.rs

@ -2,7 +2,7 @@ use std::io::BufRead;
use std::str::FromStr;
use std::num::ParseIntError;
use std::fmt::{self, Display};
use std::collections::HashSet;
use std::collections::{HashSet, HashMap};
use Segment::*;
@ -75,37 +75,60 @@ pub fn part1<F: BufRead> (mut input: F) {
println!("{}", res);
}
pub fn part2<F: BufRead> (mut input: F) {
let path1 = parse_input(&mut input);
let path2 = parse_input(&mut input);
let res = compute_first_intersection(path1, path2);
println!("{}", res);
}
fn parse_input<F: BufRead> (input: &mut F) -> Vec<Segment> {
let mut buf = String::new();
let _num_bytes = input.read_line(&mut buf).expect("Unable to read a line of input file");
buf.trim().split(",").filter_map(|segment| segment.parse().ok()).collect()
}
fn compute_first_intersection(path1: Vec<Segment>, path2: Vec<Segment>) -> i32 {
let steps1 = build_full_path(path1, 0, (0, 0), HashMap::new(), 1);
let steps2 = build_full_path(path2, 0, (0, 0), HashMap::new(), 1);
let seen1: HashSet<_> = steps1.keys().collect();
let seen2: HashSet<_> = steps2.keys().collect();
seen1.intersection(&seen2).map(|coord| steps1[coord] + steps2[coord]).min().unwrap()
}
fn compute_closest_intersection(path1: Vec<Segment>, path2: Vec<Segment>) -> i32 {
let seen1 = walk_on_path(path1, 0, (0, 0), HashSet::new());
let seen2 = walk_on_path(path2, 0, (0, 0), HashSet::new());
let steps1 = build_full_path(path1, 0, (0, 0), HashMap::new(), 1);
let steps2 = build_full_path(path2, 0, (0, 0), HashMap::new(), 1);
seen1.intersection(&seen2).map(|(x, y)| x.abs() + y.abs()).min().unwrap()
let seen1: HashSet<_> = steps1.keys().collect();
let seen2: HashSet<_> = steps2.keys().collect();
seen1.intersection(&seen2).map(|(x, y)| x.abs() + y.abs()).min().unwrap()
}
fn walk_on_path(
fn build_full_path(
path: Vec<Segment>,
index: usize,
(x0, y0): (i32, i32),
mut seen: HashSet<(i32, i32)>
) -> HashSet<(i32, i32)> {
mut steps: HashMap<(i32, i32), i32>,
current_step: i32
) -> HashMap<(i32, i32), i32> {
if index == path.len() {
seen
steps
} else {
let segment = &path[index];
let (dx, dy) = segment.direction();
let length = segment.length();
let mut current_step = current_step;
for i in 1..(length + 1) {
seen.insert((x0 + i * dx, y0 + i * dy));
steps.entry((x0 + i * dx, y0 + i * dy)).or_insert(current_step);
current_step += 1;
}
walk_on_path(path, index + 1, (x0 + length * dx, y0 + length * dy), seen)
build_full_path(path, index + 1, (x0 + length * dx, y0 + length * dy), steps, current_step)
}
}
@ -140,4 +163,22 @@ U98,R91,D20,R16,D67,R40,U7,R15,U6,R7
assert_eq!(res, *expected)
}
}
#[test]
fn test_compute_first_intersection() {
let mut input = r#"R8,U5,L5,D3
U7,R6,D4,L4
R75,D30,R83,U83,L12,D49,R71,U7,L72
U62,R66,U55,R34,D71,R55,D58,R83
R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51
U98,R91,D20,R16,D67,R40,U7,R15,U6,R7
"#.as_bytes();
let test_results = [30, 610, 410];
for expected in &test_results {
let path1 = parse_input(&mut input);
let path2 = parse_input(&mut input);
let res = compute_first_intersection(path1, path2);
assert_eq!(res, *expected)
}
}
}

2
src/main.rs

@ -38,7 +38,7 @@ fn main() {
let challenges = [
day1::part1, day1::part2,
day2::part1, day2::part2,
day3::part1,
day3::part1, day3::part2
];
if let Some(f) = challenges.get(challenge) {

Loading…
Cancel
Save