Skip to content

Instantly share code, notes, and snippets.

@hellow554
Last active December 3, 2019 12:14
Show Gist options
  • Save hellow554/6b66f62fc5d9efffc3a2c1ab57847c13 to your computer and use it in GitHub Desktop.
Save hellow554/6b66f62fc5d9efffc3a2c1ab57847c13 to your computer and use it in GitHub Desktop.
use std::collections::{HashMap, HashSet};
const INPUT: &str = include_str!("../input");
#[derive(Clone)]
enum Movement {
Up,
Down,
Left,
Right,
}
use Movement::*; // never do this in production, kids!
type Wire = Vec<Movement>;
fn parse(s: &str) -> Vec<Wire> {
s.lines()
.map(|l| {
l.split(',')
.flat_map(|v| {
let mov = match &v[..1] {
"U" => Up,
"D" => Down,
"L" => Left,
"R" => Right,
_ => unreachable!(),
};
vec![mov; v[1..].parse().unwrap()]
})
.collect()
})
.collect()
}
fn solve_a(wires: &[Wire]) -> i32 {
// grids is a Vec<HashSet<(i32, i32)>>
// in each hashset we insert the position a wire has
// in the end we just calculate the intersection and calculate
// the manhatten distance to origin (0, 0)
let grids = wires
.iter()
.map(|wire| {
wire.iter()
.scan((0_i32, 0_i32), |a, mov| {
match mov {
Right => a.0 += 1,
Left => a.0 -= 1,
Up => a.1 += 1,
Down => a.1 -= 1,
}
Some(*a)
})
.collect::<HashSet<_>>()
})
.collect::<Vec<_>>();
assert_eq!(grids.len(), 2);
let hs = grids[0].intersection(&grids[1]);
hs.map(|x| x.0.abs() + x.1.abs()).min().unwrap()
}
fn solve_b(wires: &[Wire]) -> i32 {
// similar to `solve_a`, but in this case our Hashset contains a
// triple where the third value is the signal delay
let grids = wires
.iter()
.map(|wire| {
wire.iter()
.enumerate()
.scan((0_i32, 0_i32), |a, (step, mov)| {
match mov {
Right => a.0 += 1,
Left => a.0 -= 1,
Up => a.1 += 1,
Down => a.1 -= 1,
}
Some((a.0, a.1, step))
})
.collect::<HashSet<_>>()
})
.collect::<Vec<_>>();
// in step two we only take the min signal delays in account
// and then convert it into a hashmap
let mut grids = grids
.into_iter()
.map(|grid| {
let mut new_grid: HashMap<_, usize> = HashMap::new();
for (x, y, s) in grid {
new_grid
.entry((x, y))
.and_modify(|entry| *entry = s.min(*entry))
.or_insert(s);
}
new_grid
})
.collect::<Vec<_>>();
// last step, do a insersect (`g2.get(_)?`) and then calculate the minimum signal delay
assert_eq!(2, grids.len());
let (g2, g1) = (grids.pop().unwrap(), grids.pop().unwrap());
g1.into_iter()
.filter_map(|x| Some((x, (x.0, *g2.get(&x.0)?))))
.map(|(e1, e2)| {
// +2 because we don't take origin into account
// in our original calculation (+1 for each wire)
e1.1 + e2.1 + 2
})
.min()
.unwrap() as i32
}
fn main() {
let input = parse(INPUT);
println!("A: {}", solve_a(&input));
println!("B: {}", solve_b(&input));
}
#[test]
fn ta() {
let input = "R8,U5,L5,D3
U7,R6,D4,L4";
let input = parse(input);
assert_eq!(solve_a(&input), 6);
let input = "R75,D30,R83,U83,L12,D49,R71,U7,L72
U62,R66,U55,R34,D71,R55,D58,R83";
let input = parse(input);
assert_eq!(solve_a(&input), 159);
let input = "R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51
U98,R91,D20,R16,D67,R40,U7,R15,U6,R7";
let input = parse(input);
assert_eq!(solve_a(&input), 135);
}
#[test]
fn tb() {
let input = "R8,U5,L5,D3
U7,R6,D4,L4";
let input = parse(input);
assert_eq!(solve_b(&input), 30);
let input = "R75,D30,R83,U83,L12,D49,R71,U7,L72
U62,R66,U55,R34,D71,R55,D58,R83";
let input = parse(input);
assert_eq!(solve_b(&input), 610);
let input = "R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51
U98,R91,D20,R16,D67,R40,U7,R15,U6,R7";
let input = parse(input);
assert_eq!(solve_b(&input), 410);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment