WIP: Re-implement using ndarray
This commit is contained in:
parent
3c3ef92ff8
commit
85bbc6e9d8
80
day-11/Cargo.lock
generated
80
day-11/Cargo.lock
generated
|
@ -11,29 +11,7 @@ name = "day-11"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indoc",
|
"indoc",
|
||||||
"petgraph",
|
"ndarray",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fixedbitset"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hashbrown"
|
|
||||||
version = "0.9.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "indexmap"
|
|
||||||
version = "1.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
"hashbrown",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -60,13 +38,53 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "petgraph"
|
name = "matrixmultiply"
|
||||||
version = "0.5.1"
|
version = "0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
|
checksum = "916806ba0031cd542105d916a97c8572e1fa6dd79c9c51e7eb43a09ec2dd84c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fixedbitset",
|
"rawpointer",
|
||||||
"indexmap",
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ndarray"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c0d5c9540a691d153064dc47a4db2504587a75eae07bf1d73f7a596ebc73c04"
|
||||||
|
dependencies = [
|
||||||
|
"matrixmultiply",
|
||||||
|
"num-complex",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
"rawpointer",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -93,6 +111,12 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rawpointer"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.54"
|
version = "1.0.54"
|
||||||
|
|
|
@ -8,4 +8,4 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
indoc = "0.3"
|
indoc = "0.3"
|
||||||
petgraph = "0.5"
|
ndarray = "0.14"
|
||||||
|
|
|
@ -1,32 +1,24 @@
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::iter;
|
||||||
|
|
||||||
use petgraph::graph::{DiGraph, Graph};
|
use ndarray::Array2;
|
||||||
use petgraph::visit::IntoNodeIdentifiers;
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let input = fs::read_to_string("input")?;
|
let input = fs::read_to_string("input")?;
|
||||||
let layout = parse_layout(&input)?;
|
let layout = parse_layout(&input)?;
|
||||||
|
|
||||||
// Part 1
|
// 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);
|
println!("{}", result);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
type Layout = DiGraph<Seating, Direction>;
|
type Layout = Array2<Seating>;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
enum Direction {
|
|
||||||
NorthWest,
|
|
||||||
North,
|
|
||||||
NorthEast,
|
|
||||||
West,
|
|
||||||
East,
|
|
||||||
SouthWest,
|
|
||||||
South,
|
|
||||||
SouthEast,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
enum Seating {
|
enum Seating {
|
||||||
|
@ -47,92 +39,33 @@ impl Seating {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_layout(input: &str) -> Result<Layout, String> {
|
fn parse_layout(input: &str) -> Result<Layout, String> {
|
||||||
let mut output: Layout = Graph::new();
|
let (i, j) = (
|
||||||
|
input.lines().count(),
|
||||||
let grid: Vec<Vec<_>> = input
|
input.lines().next().ok_or("Waiting room too small")?.len(),
|
||||||
.lines()
|
|
||||||
.map(|line| {
|
|
||||||
line.chars()
|
|
||||||
.map(|c| Ok(output.add_node(Seating::new(c)?)))
|
|
||||||
.collect()
|
|
||||||
})
|
|
||||||
.collect::<Result<_, 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn count_eventually_occupied_seats(layout: &Layout) -> usize {
|
|
||||||
let mut layout = layout.clone();
|
|
||||||
|
|
||||||
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 {
|
// Padding the input data so that we can later comfortably produce
|
||||||
break;
|
// a convolution
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
layout
|
let grid = input
|
||||||
.node_identifiers()
|
.lines()
|
||||||
.map(|id| layout[id])
|
.flat_map(|line| {
|
||||||
.filter(|seat| *seat == Seating::Occupied)
|
iter::once(Ok(Seating::Floor))
|
||||||
.count()
|
.chain(line.chars().map(Seating::new))
|
||||||
|
.chain(iter::once(Ok(Seating::Floor)))
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<Seating>, String>>()?;
|
||||||
|
|
||||||
|
Array2::from_shape_vec((i, j), grid)
|
||||||
|
.map_err(|_| "Non-square waiting rooms don't exist".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count_with_neighboring_seats(layout: &Layout) -> usize {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count_with_directional_seats(layout: &Layout) -> usize {
|
||||||
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -157,7 +90,30 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
let layout = parse_layout(&input)?;
|
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);
|
assert_eq!(result, 37);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in a new issue