139 lines
3.9 KiB
Rust
139 lines
3.9 KiB
Rust
---cargo
|
|
[profile.dev]
|
|
opt-level = 3
|
|
---
|
|
|
|
static CONTENT: &'static str = include_str!("./inputs/09_1.txt");
|
|
|
|
const PRINT: bool = false;
|
|
|
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
|
enum Cell {
|
|
Empty,
|
|
Red,
|
|
Green,
|
|
}
|
|
|
|
fn main() {
|
|
let points: Vec<(usize, usize)> = CONTENT.lines().map(|l| l.trim()).filter(|l| !l.is_empty()).map(|l| {
|
|
let (first, second) = l.split_once(',').unwrap();
|
|
|
|
let first = first.parse::<usize>().unwrap();
|
|
let second = second.parse::<usize>().unwrap();
|
|
|
|
(first, second)
|
|
}).collect();
|
|
// println!("Points:\n{:?}", points);
|
|
|
|
let grid_width: usize = points.iter().map(|(x, _)| *x).max().unwrap()+1;
|
|
let grid_height: usize = points.iter().map(|(y, _)| *y).max().unwrap()+1;
|
|
|
|
let mut grid = vec![Cell::Empty;grid_width*grid_height];
|
|
for parts in points.windows(2).chain(core::iter::once(&[points.last().copied().unwrap(), points.first().copied().unwrap()] as &[(usize, usize)])) {
|
|
let start = parts[0];
|
|
let end = parts[1];
|
|
|
|
let g_points = line_point_iter(start, end);
|
|
|
|
grid[start.1 *grid_width+ start.0] = Cell::Red;
|
|
for (x,y) in g_points {
|
|
grid[y*grid_width+x] = Cell::Green;
|
|
}
|
|
}
|
|
print_grid(&grid, grid_width, grid_height);
|
|
|
|
let inner_point = points.windows(2)
|
|
.filter(|p| {
|
|
let start = p[0];
|
|
let end = p[1];
|
|
|
|
start.0 == end.0
|
|
}).filter_map(|p| {
|
|
let start = p[0];
|
|
let end = p[1];
|
|
|
|
line_point_iter(start, end).next()
|
|
}).flat_map(|(x, y)| {
|
|
[(x-1, y), (x+1, y)]
|
|
}).filter(|(x, y)| {
|
|
(0..grid_width).contains(x)
|
|
}).find(|(x, y)| {
|
|
let c = (0..*x).map(|x| grid[y*grid_width + x]).filter(|c| *c == Cell::Green).count();
|
|
|
|
c == 1
|
|
}).unwrap();
|
|
|
|
let mut queue = vec![inner_point];
|
|
while let Some((x, y)) = queue.pop() {
|
|
if !(0..grid_width).contains(&x) {
|
|
continue;
|
|
}
|
|
if !(0..grid_height).contains(&y) {
|
|
continue;
|
|
}
|
|
|
|
if grid[y*grid_width+x] != Cell::Empty {
|
|
continue;
|
|
}
|
|
|
|
grid[y*grid_width+x] = Cell::Green;
|
|
|
|
queue.extend([(x-1, y), (x+1, y), (x, y-1), (x, y+1)]);
|
|
}
|
|
|
|
println!("After filling");
|
|
print_grid(&grid, grid_width, grid_height);
|
|
|
|
let mut rects: Vec<((usize, usize), (usize, usize), usize)> = points.iter()
|
|
.flat_map(|p| core::iter::repeat(*p).zip(points.iter().copied()))
|
|
.filter(|(f, s)| f != s)
|
|
.map(|(f, s)| (f, s, (f.0.abs_diff(s.0)+1) * (f.1.abs_diff(s.1)+1)))
|
|
.filter(|(f, s, _)| {
|
|
let x0 = f.0.min(s.0);
|
|
let x1 = f.0.max(s.0);
|
|
|
|
let y0 = f.1.min(s.1);
|
|
let y1 = f.1.max(s.1);
|
|
|
|
(x0..=x1).flat_map(|x| {
|
|
core::iter::repeat(x).zip(y0..=y1)
|
|
}).all(|(x, y)| grid[y*grid_width+x] != Cell::Empty)
|
|
})
|
|
.collect();
|
|
|
|
rects.sort_by_key(|(_, _, a)| *a);
|
|
|
|
// println!("Rectangle: {:?}", rects);
|
|
|
|
println!("Largest: {:?}", rects.last().unwrap());
|
|
}
|
|
|
|
fn print_grid(grid: &[Cell], width: usize, height: usize) {
|
|
if !PRINT {
|
|
return;
|
|
}
|
|
|
|
for y in 0..height {
|
|
for x in 0..width {
|
|
match grid[y*width+x] {
|
|
Cell::Empty => print!("."),
|
|
Cell::Red => print!("#"),
|
|
Cell::Green => print!("X"),
|
|
};
|
|
}
|
|
println!();
|
|
}
|
|
}
|
|
|
|
fn line_point_iter(start: (usize, usize), end: (usize, usize)) -> Box<dyn Iterator<Item = (usize, usize)>> {
|
|
if start.0 == end.0 {
|
|
let s = start.1.min(end.1);
|
|
let e = start.1.max(end.1);
|
|
Box::new(core::iter::repeat(start.0).zip(s..e).skip(1))
|
|
} else {
|
|
let s = start.0.min(end.0);
|
|
let e = start.0.max(end.0);
|
|
Box::new((s..e).zip(core::iter::repeat(start.1)).skip(1))
|
|
}
|
|
}
|