This commit is contained in:
2016-12-17 16:58:55 +01:00
parent 1215122512
commit 62bd430c86
5 changed files with 417 additions and 0 deletions

4
2016/11/Cargo.lock generated Normal file
View File

@@ -0,0 +1,4 @@
[root]
name = "11"
version = "0.1.0"

6
2016/11/Cargo.toml Normal file
View File

@@ -0,0 +1,6 @@
[package]
name = "11"
version = "0.1.0"
authors = ["logaritmisk <anders.e.olsson@gmail.com>"]
[dependencies]

4
2016/11/example.txt Normal file
View File

@@ -0,0 +1,4 @@
The first floor contains a hydrogen-compatible microchip and a lithium-compatible microchip.
The second floor contains a hydrogen generator.
The third floor contains a lithium generator.
The fourth floor contains nothing relevant.

4
2016/11/input.txt Normal file
View File

@@ -0,0 +1,4 @@
The first floor contains a thulium generator, a thulium-compatible microchip, a plutonium generator, and a strontium generator.
The second floor contains a plutonium-compatible microchip and a strontium-compatible microchip.
The third floor contains a promethium generator, a promethium-compatible microchip, a ruthenium generator, and a ruthenium-compatible microchip.
The fourth floor contains nothing relevant.

399
2016/11/src/main.rs Normal file
View File

@@ -0,0 +1,399 @@
use std::collections::HashSet;
type Floor = usize;
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct Facility {
elevator: Floor,
components: Vec<(Floor, Floor)>,
top_floor: Floor
}
impl Facility {
pub fn new(elevator: Floor, top_floor: Floor) -> Self {
Facility {
elevator: elevator,
components: Vec::new(),
top_floor: top_floor - 1
}
}
pub fn is_done(&self) -> bool {
if self.elevator != self.top_floor {
return false;
}
for &(g, m) in self.components.iter() {
if g != self.top_floor {
return false;
}
if m != self.top_floor {
return false;
}
}
true
}
pub fn validate(&self) -> bool {
let mut generators = HashSet::new();
let mut microchips = HashSet::new();
for (i, &(g, m)) in self.components.iter().enumerate() {
if g == self.elevator {
generators.insert(i);
}
if m == self.elevator {
microchips.insert(i);
}
}
if !generators.is_empty() {
let diff = microchips.difference(&generators).collect::<Vec<_>>();
if !diff.is_empty() {
return false;
}
}
true
}
pub fn steps(&self) -> Vec<Facility> {
let mut variants = Vec::new();
for (i, &(g, m)) in self.components.iter().enumerate() {
if self.elevator < self.top_floor {
if g == self.elevator {
let mut variant = self.clone();
variant.elevator += 1;
variant.components[i].0 += 1;
if variant.validate() {
variants.push(variant);
}
}
if m == self.elevator {
let mut variant = self.clone();
variant.elevator += 1;
variant.components[i].1 += 1;
if variant.validate() {
variants.push(variant);
}
}
}
if self.elevator > 0 {
if g == self.elevator {
let mut variant = self.clone();
variant.elevator -= 1;
variant.components[i].0 -= 1;
if variant.validate() {
variants.push(variant);
}
}
if m == self.elevator {
let mut variant = self.clone();
variant.elevator -= 1;
variant.components[i].1 -= 1;
if variant.validate() {
variants.push(variant);
}
}
}
}
let mut components = self.components.iter().enumerate()
.flat_map(|(i, &(g, m))| vec![(i, 0, g), (i, 1, m)].into_iter())
.filter(|&(_, _, f)| f == self.elevator)
.map(|(i, c, _)| (i, c))
.collect::<Vec<_>>();
while !components.is_empty() {
let a = components.remove(0);
for b in components.iter() {
if self.elevator < self.top_floor {
let mut variant = self.clone();
variant.elevator += 1;
match a.1 {
0 => variant.components[a.0].0 += 1,
1 => variant.components[a.0].1 += 1,
_ => unreachable!()
}
match b.1 {
0 => variant.components[b.0].0 += 1,
1 => variant.components[b.0].1 += 1,
_ => unreachable!()
}
if variant.validate() {
variants.push(variant);
}
}
if self.elevator > 0 {
let mut variant = self.clone();
variant.elevator -= 1;
match a.1 {
0 => variant.components[a.0].0 -= 1,
1 => variant.components[a.0].1 -= 1,
_ => unreachable!()
}
match b.1 {
0 => variant.components[b.0].0 -= 1,
1 => variant.components[b.0].1 -= 1,
_ => unreachable!()
}
if variant.validate() {
variants.push(variant);
}
}
}
}
variants
}
}
fn main() {
let mut facilities = Vec::new();
let mut facility = Facility::new(0, 4);
// Thulium
facility.components.push((0, 0));
// Plutonium
facility.components.push((0, 1));
// Strontium
facility.components.push((0, 1));
// Promethium
facility.components.push((2, 2));
// Ruthenium
facility.components.push((2, 2));
// Elerium
facility.components.push((0, 0));
// Dilithium
facility.components.push((0, 0));
facility.steps();
facilities.push(facility);
let mut checked = HashSet::new();
for i in 0..100 {
let mut step_variants = Vec::new();
for facility in facilities.clone() {
if checked.contains(&facility) {
continue;
}
let mut variants = facility.steps();
checked.insert(facility);
step_variants.append(&mut variants);
}
println!("step={}, variants={}", i + 1, step_variants.len());
let done = step_variants.iter().filter(|x| x.is_done()).count();
if done > 0 {
println!("DONE!");
break;
}
facilities = step_variants;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_step_01() {
let mut facility = Facility::new(0, 4);
// Hydrogen
facility.components.push((1, 0));
// Lithium
facility.components.push((2, 0));
assert_eq!(true, facility.validate());
assert_eq!(false, facility.is_done());
}
#[test]
fn test_step_02() {
let mut facility = Facility::new(1, 4);
// Hydrogen
facility.components.push((1, 1));
// Lithium
facility.components.push((2, 0));
assert_eq!(true, facility.validate());
assert_eq!(false, facility.is_done());
}
#[test]
fn test_step_03() {
let mut facility = Facility::new(2, 4);
// Hydrogen
facility.components.push((2, 2));
// Lithium
facility.components.push((2, 0));
assert_eq!(true, facility.validate());
assert_eq!(false, facility.is_done());
}
#[test]
fn test_step_04() {
let mut facility = Facility::new(1, 4);
facility.components.push((2, 1));
facility.components.push((2, 0));
assert_eq!(true, facility.validate());
assert_eq!(false, facility.is_done());
}
#[test]
fn test_step_05() {
let mut facility = Facility::new(0, 4);
facility.components.push((2, 0));
facility.components.push((2, 0));
assert_eq!(true, facility.validate());
assert_eq!(false, facility.is_done());
}
#[test]
fn test_step_06() {
let mut facility = Facility::new(0, 4);
facility.components.push((2, 1));
facility.components.push((2, 1));
assert_eq!(true, facility.validate());
assert_eq!(false, facility.is_done());
}
#[test]
fn test_step_07() {
let mut facility = Facility::new(0, 4);
facility.components.push((2, 2));
facility.components.push((2, 2));
assert_eq!(true, facility.validate());
assert_eq!(false, facility.is_done());
}
#[test]
fn test_step_08() {
let mut facility = Facility::new(0, 4);
facility.components.push((2, 3));
facility.components.push((2, 3));
assert_eq!(true, facility.validate());
assert_eq!(false, facility.is_done());
}
#[test]
fn test_step_09() {
let mut facility = Facility::new(0, 4);
facility.components.push((2, 2));
facility.components.push((2, 3));
assert_eq!(true, facility.validate());
assert_eq!(false, facility.is_done());
}
#[test]
fn test_step_10() {
let mut facility = Facility::new(0, 4);
facility.components.push((3, 2));
facility.components.push((3, 3));
assert_eq!(true, facility.validate());
assert_eq!(false, facility.is_done());
}
#[test]
fn test_step_11() {
let mut facility = Facility::new(0, 4);
facility.components.push((3, 2));
facility.components.push((3, 2));
assert_eq!(true, facility.validate());
assert_eq!(false, facility.is_done());
}
#[test]
fn test_step_12() {
let mut facility = Facility::new(3, 4);
facility.components.push((3, 3));
facility.components.push((3, 3));
assert_eq!(true, facility.validate());
assert_eq!(true, facility.is_done());
}
#[test]
fn test_validate_01() {
let mut facility = Facility::new(0, 4);
facility.components.push((1, 0));
facility.components.push((0, 1));
assert_eq!(false, facility.validate());
}
}