From 4246a04138dbc19bbb3f958861dc56554befc7a0 Mon Sep 17 00:00:00 2001 From: Daniel Seiller Date: Wed, 16 Dec 2020 18:28:07 +0100 Subject: [PATCH] Day 16 --- src/day10.rs | 32 +---------- src/day14.rs | 2 +- src/day16.rs | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 + 4 files changed, 153 insertions(+), 32 deletions(-) create mode 100644 src/day16.rs diff --git a/src/day10.rs b/src/day10.rs index f9330b3..ee399a6 100644 --- a/src/day10.rs +++ b/src/day10.rs @@ -37,38 +37,8 @@ fn solve_part_2_rec( // println!("-{}", node); ret } - -fn solve_part_2_it(node: u16, goal: u16, map: &HashMap>) -> usize { - // let mut cache: HashMap<(u16, u16), usize> = HashMap::new(); - // let mut used = HashSet::new(); - // let mut stack=Vec::new(); - // // stack.push((node); - // if node == goal { - // return 1; - // } - // let mut ret = 0; - // while let Some(node) = stack.pop() { - // for next in map.get(&node).iter().map(|v| v.iter()).flatten() { - // if used.contains(next) { - // continue; - // }; - // used.insert(*next); - // let value = match cache.get(&(node, *next)) { - // Some(value) => *value, - // None => { - // let value = solve_part_2_rec(*next, goal, map, used, cache); - // cache.insert((node, *next), value); - // value - // } - // }; - // ret += value; - // used.remove(next); - // } - // } - return 0; -} - pub struct Data(pub Vec); + impl Data { #[inline(always)] fn count_paths(&self) -> usize { diff --git a/src/day14.rs b/src/day14.rs index ee97c72..e4004de 100644 --- a/src/day14.rs +++ b/src/day14.rs @@ -73,7 +73,7 @@ pub fn input_generator(input: &str) -> Data { let mut mask_and = 0; let mut mask_or = 0; let mut char_buf = vec![]; - for (n, c) in line.split("=").nth(1).unwrap().trim().chars().enumerate() { + for (_, c) in line.split("=").nth(1).unwrap().trim().chars().enumerate() { char_buf.push(c); mask_and <<= 1; mask_or <<= 1; diff --git a/src/day16.rs b/src/day16.rs new file mode 100644 index 0000000..56dfa74 --- /dev/null +++ b/src/day16.rs @@ -0,0 +1,149 @@ +use aoc_runner_derive::{aoc, aoc_generator}; +use std::collections::{HashMap, HashSet}; +#[derive(Debug)] +pub struct Input { + ranges: HashMap>, + my_ticket: Vec, + other_tickets: Vec>, +} + +type Data = Input; + +#[aoc_generator(day16)] +pub fn input_generator(input: &str) -> Data { + let l = input.lines(); + let ranges: HashMap> = l + .take_while(|l| l.trim().len() != 0) + .map(|s| { + let parts: Vec<_> = s.to_owned().split(": ").map(|v| v.to_owned()).collect(); + let name = parts.get(0).unwrap().trim().to_owned(); + let ranges: Vec<(usize, usize)> = parts + .get(1) + .unwrap() + .to_owned() + .split(" or ") + .map(|l| { + let r: Vec = l + .to_owned() + .split("-") + .map(|v| v.to_owned().parse().unwrap()) + .collect(); + (r[0], r[1]) + }) + .collect(); + (name, ranges) + }) + .collect(); + let mut l = input.lines().skip(ranges.len() + 2); + let my_ticket = l + .next() + .unwrap() + .split(",") + .map(|v| v.parse().unwrap()) + .collect(); + let other_tickets = l + .skip(2) + .map(|nums| nums.split(",").map(|v| v.parse().unwrap()).collect()) + .collect(); + Data { + ranges, + my_ticket, + other_tickets, + } +} + +fn in_ranges(num: usize, ranges: &Vec<(usize, usize)>) -> bool { + let mut in_range = false; + for (min, max) in ranges { + in_range |= (num >= *min) && (num <= *max); + } + return in_range; +} + +#[aoc(day16, part1)] +pub fn solve_part1(input: &Data) -> usize { + let mut inv_nums = vec![]; + for ticket in &input.other_tickets { + for num in ticket { + let mut in_any_range = false; + for range in input.ranges.values() { + let mut in_range = false; + for (min, max) in range { + in_range |= (num >= min) && (num <= max); + } + in_any_range |= in_range; + } + if !in_any_range { + inv_nums.push(*num); + } + } + } + inv_nums.iter().sum() +} + +#[aoc(day16, part2)] +pub fn solve_part2(input: &Data) -> usize { + let mut field_candicates: Vec> = vec![HashSet::new(); input.my_ticket.len()]; + let mut valid_tickets = vec![]; + for ticket in &input.other_tickets { + let mut valid = true; + for num in ticket { + let mut in_any_range = false; + for range in input.ranges.values() { + let mut in_range = false; + for (min, max) in range { + in_range |= (num >= min) && (num <= max); + } + in_any_range |= in_range; + } + if !in_any_range { + valid = false; + break; + } + } + if valid { + valid_tickets.push(ticket.clone()); + } + } + for field in input.ranges.keys() { + for f in field_candicates.iter_mut() { + f.insert(field.clone()); + } + } + for (field, ranges) in &input.ranges { + for ticket in &valid_tickets { + for (i, num) in ticket.iter().enumerate() { + if !in_ranges(*num, ranges) { + field_candicates[i].remove(field); + } + } + } + } + let mut fixed: HashSet = HashSet::new(); + let mut field_candicates: Vec<(usize, HashSet)> = + field_candicates.drain(..).enumerate().collect(); + field_candicates.sort_unstable_by_key(|(_, v)| v.len()); + while field_candicates.iter().any(|(_, v)| v.len() != 1) { + for c in field_candicates.iter_mut() { + if c.1.len() == 1 { + fixed.extend(c.1.iter().cloned()); + } else { + for val in &fixed { + c.1.remove(val); + } + } + } + } + field_candicates.sort_unstable_by_key(|(n, _)| *n); + let field_names: Vec = field_candicates + .drain(..) + .map(|(_, n)| n.iter().next().unwrap().clone()) + .collect(); + let mut ret = 1; + for (field, value) in field_names.iter().zip(input.my_ticket.iter()) { + if field.starts_with("departure") { + ret *= value; + } + } + return ret; +} diff --git a/src/lib.rs b/src/lib.rs index b5ee9f1..2b1429d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,4 +13,6 @@ pub mod day11; pub mod day12; pub mod day13; pub mod day14; +pub mod day15; +pub mod day16; aoc_lib! { year = 2020 }