Optimize day 5
This commit is contained in:
parent
bcddb22135
commit
45600f5dd1
@ -1,12 +1,12 @@
|
|||||||
|
#![feature(int_abs_diff)]
|
||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
extern crate test;
|
extern crate test;
|
||||||
use aoc2021::common::*;
|
use aoc2021::common::*;
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use itertools::Itertools;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
const DAY: usize = 5;
|
const DAY: usize = 5;
|
||||||
type Parsed = Vec<((usize, usize), (usize, usize))>;
|
type Coordinate = (i16, i16); // twice as fast as using i64s ¯\_(ツ)_/¯
|
||||||
|
type Parsed = Vec<(Coordinate, Coordinate)>;
|
||||||
|
|
||||||
fn parse_input(raw: &str) -> Parsed {
|
fn parse_input(raw: &str) -> Parsed {
|
||||||
raw.lines()
|
raw.lines()
|
||||||
@ -16,34 +16,43 @@ fn parse_input(raw: &str) -> Parsed {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part1(parsed: &Parsed) -> usize {
|
fn solve<F: FnMut(&(Coordinate, Coordinate)) -> Vec<Coordinate>>(parsed: &Parsed, f: F) -> usize {
|
||||||
let mut map: HashMap<_, _, _> = FnvHashMap::default();
|
|
||||||
parsed
|
parsed
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|cs| match cs {
|
.flat_map(f)
|
||||||
((x1, y1), (x2, y2)) if x1 == x2 => (*y1.min(y2)..=*y1.max(y2)).map(|y| (*x1, y)).collect(),
|
.fold(FnvHashMap::default(), |mut map, c| {
|
||||||
((x1, y1), (x2, y2)) if y1 == y2 => (*x1.min(x2)..=*x1.max(x2)).map(|x| (x, *y1)).collect(),
|
*map.entry(c).or_insert(0) += 1;
|
||||||
_ => vec![],
|
map
|
||||||
})
|
})
|
||||||
.for_each(|c| *map.entry(c).or_insert(0) += 1);
|
.values()
|
||||||
map.values().filter(|&&n| n > 1).count()
|
.filter(|&&n| n > 1)
|
||||||
|
.count()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part1(parsed: &Parsed) -> usize {
|
||||||
|
solve(parsed, |&cs| match cs {
|
||||||
|
((x1, y1), (x2, y2)) if x1 == x2 => (y1.min(y2)..=y1.max(y2)).map(|y| (x1, y)).collect(),
|
||||||
|
((x1, y1), (x2, y2)) if y1 == y2 => (x1.min(x2)..=x1.max(x2)).map(|x| (x, y1)).collect(),
|
||||||
|
_ => vec![],
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part2(parsed: &Parsed) -> usize {
|
fn part2(parsed: &Parsed) -> usize {
|
||||||
let mut map: HashMap<_, _, _> = FnvHashMap::default();
|
let offset = |x1, x2| (x1 < x2) as i16 - (x1 > x2) as i16;
|
||||||
parsed
|
solve(parsed, |&((mut x1, mut y1), (x2, y2))| {
|
||||||
.iter()
|
let mut coords = Vec::with_capacity(x1.abs_diff(x2).max(y1.abs_diff(y2)) as usize + 1);
|
||||||
.flat_map(|cs| match cs {
|
let x_offset = offset(x1, x2);
|
||||||
((x1, y1), (x2, y2)) if x1 == x2 => (*y1.min(y2)..=*y1.max(y2)).map(|y| (*x1, y)).collect_vec(),
|
let y_offset = offset(y1, y2);
|
||||||
((x1, y1), (x2, y2)) if y1 == y2 => (*x1.min(x2)..=*x1.max(x2)).map(|x| (x, *y1)).collect(),
|
loop {
|
||||||
((x1, y1), (x2, y2)) if x1 < x2 && y1 < y2 => (*x1..=*x2).zip(*y1..=*y2).collect(),
|
coords.push((x1, y1));
|
||||||
((x1, y1), (x2, y2)) if x1 < x2 && y1 > y2 => (*x1..=*x2).zip((*y2..=*y1).rev()).collect(),
|
if x1 == x2 && y1 == y2 {
|
||||||
((x1, y1), (x2, y2)) if x1 > x2 && y1 < y2 => (*x2..=*x1).rev().zip(*y1..=*y2).collect(),
|
break;
|
||||||
((x1, y1), (x2, y2)) if x1 > x2 && y1 > y2 => (*x2..=*x1).rev().zip((*y2..=*y1).rev()).collect(),
|
}
|
||||||
_ => unreachable!(),
|
x1 += x_offset;
|
||||||
})
|
y1 += y_offset;
|
||||||
.for_each(|c| *map.entry(c).or_insert(0) += 1);
|
}
|
||||||
map.values().filter(|&&n| n > 1).count()
|
coords
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
Loading…
Reference in New Issue
Block a user