Add day 5 and day 7 solutions

[?]
Dec 24, 2020, 3:03 AM
6S7OD5A7AFBHTY55VATYR74O3TGMIOR7Y4ITUI6RKGLDMUWY2JNQC

Dependencies

Change contents

  • file addition: day5.rs (----------)
    [2.17]
    use std::convert::TryFrom;
    fn find_seat<I: Iterator<Item=char>>(source: &mut I) -> (u8, u8) {
    let mut row = 0;
    let mut col = 0;
    for c in source {
    match c {
    'F' => { row *= 2; },
    'B' => { row = row * 2 + 1; },
    'L' => { col *= 2; },
    'R' => { col = col * 2 + 1; },
    _ => (),
    }
    }
    (row,col)
    }
    fn seat_id(row: u8, col: u8) -> u16 {
    u16::from(row) * 8 + u16::from(col)
    }
    fn max_seat<I: Iterator<Item=u16>>(ids: &mut I) -> u16 {
    ids.max().unwrap()
    }
    fn my_seat<I: Iterator<Item=u16>>(ids: &mut I) -> u16 {
    let mut filled: Vec<bool> = Vec::with_capacity(1024);
    filled.resize(1024, false);
    for seat in ids {
    filled[usize::from(seat)] = true;
    };
    for (i,f) in filled.iter().enumerate() {
    if !f && i < 1023 && i > 0 && filled[i + 1] && filled[i - 1] {
    return u16::try_from(i).unwrap();
    }
    }
    panic!("not found")
    }
    fn main() {
    use std::env;
    use std::io::BufRead;
    let args: Vec<_> = env::args().collect();
    let lines = std::io::BufReader::new(std::fs::File::open(&args[1]).unwrap()).lines();
    let mut seats = lines.map(|l| {
    let (row,col) = find_seat(&mut l.unwrap().chars());
    seat_id(row, col)
    });
    println!("{}", match args[2].as_ref() {
    "1" => max_seat(&mut seats),
    "2" => my_seat(&mut seats),
    _ => panic!("unknown problem"),
    });
    }
  • file addition: day7.rs (----------)
    [2.17]
    use std::str::FromStr;
    use std::num::ParseIntError;
    struct Rule {
    outer: String,
    inner: Vec<(String,u8)>,
    }
    #[derive(Debug,Clone)]
    enum RuleParseError {
    Numeric(ParseIntError),
    Other,
    }
    impl From<ParseIntError> for RuleParseError {
    fn from(src: ParseIntError) -> Self {
    Self::Numeric(src)
    }
    }
    impl FromStr for Rule {
    type Err = RuleParseError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
    let mut words = s.split_whitespace();
    let mut outer = Vec::new();
    for w in words.by_ref() {
    if w == "bags" {
    break;
    } else {
    outer.push(w);
    }
    }
    let outer = Intercalate::new(outer.iter(), &" ").map(std::ops::Deref::deref).collect::<String>();
    match words.next() {
    Some("contain") => Ok(()),
    _ => Err(RuleParseError::Other),
    }?;
    let mut inner = Vec::new();
    loop {
    let count = match words.next() {
    None => Err(RuleParseError::Other),
    Some(w) => if w == "no" {
    match words.next() {
    Some("other") => Ok(()),
    _ => Err(RuleParseError::Other),
    }?;
    match words.next() {
    Some("bags.") => Ok(()),
    _ => Err(RuleParseError::Other),
    }?;
    return Ok(Rule {outer: outer, inner: inner});
    } else {
    w.parse().or_else(|e| Err(RuleParseError::Numeric(e)))
    },
    }?;
    let mut color = Vec::new();
    for w in words.by_ref() {
    if w == "bag," || w == "bags," || w == "bag." || w == "bags." {
    inner.push((Intercalate::new(color.iter(), &" ").map(std::ops::Deref::deref).collect::<String>(), count));
    if w.chars().next_back() == Some('.') {
    return Ok(Rule { outer: outer, inner: inner });
    } else {
    break;
    }
    } else {
    color.push(w);
    }
    }
    }
    }
    }
    struct Intercalate<I: Iterator> {
    sep: <I as Iterator>::Item,
    inner: std::iter::Peekable<I>,
    sep_phase: bool,
    }
    impl<I: Iterator> Intercalate<I> {
    fn new(inner: I, sep: <I as Iterator>::Item) -> Self {
    Self { sep: sep, inner: inner.peekable(), sep_phase: false }
    }
    }
    impl<I: Iterator> Iterator for Intercalate<I> where I::Item: Clone {
    type Item = I::Item;
    fn next(&mut self) -> Option<Self::Item> {
    if self.sep_phase {
    match self.inner.peek() {
    Some(_) => {
    self.sep_phase = false;
    Some(self.sep.clone())
    },
    None => None
    }
    } else {
    self.sep_phase = true;
    self.inner.next()
    }
    }
    }
    fn count_colors_containing(rules: Vec<Rule>, innermost: Vec<String>) -> usize {
    use std::collections::HashMap;
    use std::collections::HashSet;
    let mut flowback = HashMap::new();
    for rule in rules.iter() {
    for (inner,_) in rule.inner.iter() {
    flowback.entry(inner).or_insert_with(Vec::new).push(rule.outer.clone());
    }
    }
    let mut hits = HashSet::new();
    let mut q: Vec<String> = innermost.clone();
    loop {
    match q.pop() {
    None => break,
    Some(color) => {
    if !hits.contains(&color) {
    hits.insert(color.clone());
    match flowback.get(&color) {
    None => (),
    Some(colors) => q.append(&mut colors.clone()),
    }
    }
    },
    }
    };
    for color in innermost.iter() {
    hits.remove(color);
    }
    hits.len()
    }
    fn count_bags_in(rules: Vec<Rule>, outer: String) -> usize {
    use std::collections::HashMap;
    let mut counted: HashMap<String,usize> = HashMap::new();
    let tree: HashMap<_,_> = rules.iter().map(|rule| (rule.outer.clone(), rule.inner.clone())).collect();
    let mut q = vec![outer.clone()];
    loop {
    match q.pop() {
    None => break,
    Some(c) => match counted.get(&c) {
    Some(_) => (),
    None => if tree
    .get(&c)
    .iter()
    .flat_map(|v| v.iter()).all(|(r,_)|
    counted.contains_key(r)
    ) {
    counted.insert(c.clone(), tree
    .get(&c)
    .iter()
    .flat_map(|v| v.iter())
    .map(|(r,n)|
    (1 + counted
    .get(r)
    .map(|x| *x)
    .unwrap_or(0)
    ) * usize::from(*n)
    ).sum()
    );
    } else {
    q.push(c.clone());
    for (r,_) in tree.get(&c).iter().flat_map(|v| v.iter()) {
    q.push(r.clone())
    }
    },
    },
    }
    };
    match counted.get(&outer) {
    Some(r) => *r,
    None => 0,
    }
    }
    fn main() {
    use std::env;
    use std::io::BufRead;
    let args: Vec<_> = env::args().collect();
    let rules: Vec<Rule> = std::io::BufReader::new(std::fs::File::open(&args[1]).unwrap())
    .lines()
    .map(Result::unwrap)
    .map(|s| s.parse())
    .map(Result::unwrap)
    .collect();
    println!("{}", match args[2].as_ref() {
    "1" => count_colors_containing(rules, vec![String::from("shiny gold")]),
    "2" => count_bags_in(rules, String::from("shiny gold")),
    _ => panic!("No such problem"),
    });
    }