parent
a2dc11280c
commit
2f29b13e7b
@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "day7"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Avril <flanchan@cumallover.me>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
generational-arena = "0.2.8"
|
@ -0,0 +1,103 @@
|
|||||||
|
use std::{
|
||||||
|
mem,
|
||||||
|
ops,
|
||||||
|
hash::{Hash, Hasher,},
|
||||||
|
};
|
||||||
|
use generational_arena::{
|
||||||
|
Arena,
|
||||||
|
Index,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Eq)]
|
||||||
|
pub struct Bag
|
||||||
|
{
|
||||||
|
name: String,
|
||||||
|
contains: Vec<Index>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for Bag {
|
||||||
|
#[inline] fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
self.as_ref().hash(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> PartialEq<T> for Bag
|
||||||
|
where T: AsRef<BagRef>
|
||||||
|
{
|
||||||
|
fn eq(&self, other: &T) -> bool
|
||||||
|
{
|
||||||
|
self.as_ref() == other.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Bag
|
||||||
|
{
|
||||||
|
pub fn new(name: String) -> Self
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
name,
|
||||||
|
contains: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn push_contents(&mut self, idx: Index)
|
||||||
|
{
|
||||||
|
self.contains.push(idx)
|
||||||
|
}
|
||||||
|
pub fn bags_in<'a>(&'a self, w: &'a Arena<Bag>) -> impl Iterator<Item = &'a BagRef> + 'a
|
||||||
|
{
|
||||||
|
self.contains.iter().filter_map(move |x| w.get(x.clone())).map(Self::as_ref)
|
||||||
|
}
|
||||||
|
pub fn contains_in(&self, w: &Arena<Bag>, bag: impl AsRef<BagRef>) -> bool
|
||||||
|
{
|
||||||
|
for x in self.bags_in(w)
|
||||||
|
{
|
||||||
|
if x == bag.as_ref() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<BagRef> for Bag
|
||||||
|
{
|
||||||
|
#[inline] fn as_ref(&self) -> &BagRef
|
||||||
|
{
|
||||||
|
BagRef::new_unchecked(&self.name[..])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Deref for Bag
|
||||||
|
{
|
||||||
|
type Target = BagRef;
|
||||||
|
#[inline] fn deref(&self) -> &Self::Target {
|
||||||
|
self.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct BagRef
|
||||||
|
{
|
||||||
|
name: str
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<BagRef> for BagRef
|
||||||
|
{
|
||||||
|
#[inline] fn as_ref(&self) -> &BagRef
|
||||||
|
{
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl BagRef
|
||||||
|
{
|
||||||
|
#[inline] fn new_unchecked<'a>(from: &'a str) -> &'a BagRef
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
mem::transmute(from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
#![feature(str_split_once)]
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
mod parse;
|
||||||
|
mod bag;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
use std::{
|
||||||
|
io::{
|
||||||
|
self, BufRead,
|
||||||
|
},
|
||||||
|
sync::{
|
||||||
|
mpsc,
|
||||||
|
},
|
||||||
|
thread,
|
||||||
|
marker::*,
|
||||||
|
collections::{HashMap, HashSet,},
|
||||||
|
};
|
||||||
|
use generational_arena::{
|
||||||
|
Arena, Index,
|
||||||
|
};
|
||||||
|
use super::bag;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
struct Rule
|
||||||
|
{
|
||||||
|
contents: Vec<(usize, String)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_rest(from: mpsc::Receiver<String>) -> HashMap<String, Rule>
|
||||||
|
{
|
||||||
|
let mut out = HashMap::new();
|
||||||
|
while let Ok(line) = from.recv() {
|
||||||
|
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
struct UnlinkedBag<'a>
|
||||||
|
{
|
||||||
|
name: &'a str,
|
||||||
|
cont: Rule,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MaybeLinked<'a>
|
||||||
|
{
|
||||||
|
Unlinked(UnlinkedBag<'a>),
|
||||||
|
Linked(bag::Bag),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse<R: BufRead>(from: R) -> Result<Arena<bag::Bag>, io::Error>
|
||||||
|
{
|
||||||
|
let mut all_possible = HashSet::<String>::new();
|
||||||
|
let (tx, rx) = mpsc::channel();
|
||||||
|
let w = thread::spawn(move || parse_rest(rx));
|
||||||
|
|
||||||
|
macro_rules! unwrap {
|
||||||
|
(? $opt:expr) => {
|
||||||
|
match $opt {
|
||||||
|
Some(v) => v,
|
||||||
|
_ => continue,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($res:expr) => {
|
||||||
|
unwrap!(? $res.ok())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for line in from.lines()
|
||||||
|
{
|
||||||
|
let mut line = line?;
|
||||||
|
|
||||||
|
let irest = {
|
||||||
|
const SPLIT: &str = "bags contain";
|
||||||
|
let bn = {
|
||||||
|
let idx = unwrap!(? line.find(SPLIT));
|
||||||
|
&line[..idx]
|
||||||
|
};
|
||||||
|
all_possible.insert(bn.trim().to_owned());
|
||||||
|
};
|
||||||
|
unwrap!(tx.send(line));
|
||||||
|
}
|
||||||
|
let (mut unlinked, nref) = {
|
||||||
|
let mut ulinks = w.join().unwrap();
|
||||||
|
let mut unlinked = Arena::with_capacity(all_possible.len());
|
||||||
|
let mut nref = HashMap::new();
|
||||||
|
for name in all_possible.iter()
|
||||||
|
{
|
||||||
|
let urule = ulinks.remove(name).unwrap();
|
||||||
|
let idx = unlinked.insert(MaybeLinked::Unlinked(UnlinkedBag{name, cont: urule}));
|
||||||
|
nref.insert(name, idx);
|
||||||
|
}
|
||||||
|
(unlinked, nref)
|
||||||
|
};
|
||||||
|
|
||||||
|
let indecies: Vec<_> = unlinked.iter().map(|(i, _)| i).collect();
|
||||||
|
for idx in indecies.into_iter()
|
||||||
|
{
|
||||||
|
let current = unlinked.get_mut(idx).unwrap();
|
||||||
|
let linked = match current {
|
||||||
|
MaybeLinked::Unlinked(UnlinkedBag{name, cont: rule}) => {
|
||||||
|
let mut linking = bag::Bag::new(name.to_owned());
|
||||||
|
for (_, cont) in rule.contents.iter() {
|
||||||
|
linking.push_contents(*nref.get(cont).unwrap());
|
||||||
|
}
|
||||||
|
linking
|
||||||
|
},
|
||||||
|
_=> continue,
|
||||||
|
};
|
||||||
|
*current = MaybeLinked::Linked(linked);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: how tf can we convert from Arena<MaybeLinked<_>> into Arena<_>?????
|
||||||
|
|
||||||
|
todo!()
|
||||||
|
}
|
Loading…
Reference in new issue