WIP: Re-implement using ndarray
This commit is contained in:
parent
5a7cd20ca6
commit
f38ec71c3f
3 changed files with 105 additions and 125 deletions
day-11/src
|
@ -1,32 +1,24 @@
|
|||
use std::fs;
|
||||
use std::iter;
|
||||
|
||||
use petgraph::graph::{DiGraph, Graph};
|
||||
use petgraph::visit::IntoNodeIdentifiers;
|
||||
use ndarray::Array2;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let input = fs::read_to_string("input")?;
|
||||
let layout = parse_layout(&input)?;
|
||||
|
||||
// Part 1
|
||||
let result = count_eventually_occupied_seats(&layout);
|
||||
let result = count_with_neighboring_seats(&layout);
|
||||
println!("{}", result);
|
||||
|
||||
// Part 2
|
||||
let result = count_with_directional_seats(&layout);
|
||||
println!("{}", result);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
type Layout = DiGraph<Seating, Direction>;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum Direction {
|
||||
NorthWest,
|
||||
North,
|
||||
NorthEast,
|
||||
West,
|
||||
East,
|
||||
SouthWest,
|
||||
South,
|
||||
SouthEast,
|
||||
}
|
||||
type Layout = Array2<Seating>;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
enum Seating {
|
||||
|
@ -47,92 +39,33 @@ impl Seating {
|
|||
}
|
||||
|
||||
fn parse_layout(input: &str) -> Result<Layout, String> {
|
||||
let mut output: Layout = Graph::new();
|
||||
let (i, j) = (
|
||||
input.lines().count(),
|
||||
input.lines().next().ok_or("Waiting room too small")?.len(),
|
||||
);
|
||||
|
||||
let grid: Vec<Vec<_>> = input
|
||||
// Padding the input data so that we can later comfortably produce
|
||||
// a convolution
|
||||
|
||||
let grid = input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
line.chars()
|
||||
.map(|c| Ok(output.add_node(Seating::new(c)?)))
|
||||
.collect()
|
||||
.flat_map(|line| {
|
||||
iter::once(Ok(Seating::Floor))
|
||||
.chain(line.chars().map(Seating::new))
|
||||
.chain(iter::once(Ok(Seating::Floor)))
|
||||
})
|
||||
.collect::<Result<_, String>>()?;
|
||||
.collect::<Result<Vec<Seating>, String>>()?;
|
||||
|
||||
for i in 0..grid.len() {
|
||||
for j in 0..grid[0].len() {
|
||||
if let Some(node) = grid.get(i).and_then(|row| row.get(j)) {
|
||||
for ((c, r), direction) in [
|
||||
((0, 0), Direction::NorthWest),
|
||||
((0, 1), Direction::North),
|
||||
((0, 2), Direction::NorthEast),
|
||||
((1, 0), Direction::West),
|
||||
((1, 2), Direction::East),
|
||||
((2, 0), Direction::SouthWest),
|
||||
((2, 1), Direction::South),
|
||||
((2, 2), Direction::SouthEast),
|
||||
]
|
||||
.iter()
|
||||
{
|
||||
if let (Some(c), Some(r)) = ((i + c).checked_sub(1), (j + r).checked_sub(1)) {
|
||||
if let Some(target) = grid.get(c).and_then(|row| row.get(r)) {
|
||||
output.add_edge(*node, *target, *direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(output)
|
||||
Array2::from_shape_vec((i, j), grid)
|
||||
.map_err(|_| "Non-square waiting rooms don't exist".to_string())
|
||||
}
|
||||
|
||||
fn count_eventually_occupied_seats(layout: &Layout) -> usize {
|
||||
let mut layout = layout.clone();
|
||||
fn count_with_neighboring_seats(layout: &Layout) -> usize {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
loop {
|
||||
let mut changes = 0;
|
||||
|
||||
layout = layout.map(
|
||||
|node, seat| match seat {
|
||||
Seating::Occupied => {
|
||||
if layout
|
||||
.neighbors(node)
|
||||
.filter(|seat| layout[*seat] == Seating::Occupied)
|
||||
.count()
|
||||
>= 4
|
||||
{
|
||||
changes += 1;
|
||||
Seating::Empty
|
||||
} else {
|
||||
*seat
|
||||
}
|
||||
}
|
||||
Seating::Empty => {
|
||||
if !layout
|
||||
.neighbors(node)
|
||||
.any(|seat| layout[seat] == Seating::Occupied)
|
||||
{
|
||||
changes += 1;
|
||||
Seating::Occupied
|
||||
} else {
|
||||
*seat
|
||||
}
|
||||
}
|
||||
Seating::Floor => Seating::Floor,
|
||||
},
|
||||
|_, direction| *direction,
|
||||
);
|
||||
|
||||
if changes == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
layout
|
||||
.node_identifiers()
|
||||
.map(|id| layout[id])
|
||||
.filter(|seat| *seat == Seating::Occupied)
|
||||
.count()
|
||||
fn count_with_directional_seats(layout: &Layout) -> usize {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -157,7 +90,30 @@ mod tests {
|
|||
);
|
||||
|
||||
let layout = parse_layout(&input)?;
|
||||
let result = count_eventually_occupied_seats(&layout);
|
||||
let result = count_with_neighboring_seats(&layout);
|
||||
|
||||
assert_eq!(result, 37);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_simple2() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let input = indoc!(
|
||||
"L.LL.LL.LL
|
||||
LLLLLLL.LL
|
||||
L.L.L..L..
|
||||
LLLL.LL.LL
|
||||
L.LL.LL.LL
|
||||
L.LLLLL.LL
|
||||
..L.L.....
|
||||
LLLLLLLLLL
|
||||
L.LLLLLL.L
|
||||
L.LLLLL.LL
|
||||
"
|
||||
);
|
||||
|
||||
let layout = parse_layout(&input)?;
|
||||
let result = count_with_directional_seats(&layout);
|
||||
|
||||
assert_eq!(result, 37);
|
||||
Ok(())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue