day16
This commit is contained in:
parent
f9d58356cd
commit
272761b05c
145
src/day16.rs
Normal file
145
src/day16.rs
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
use std::{ops::RangeInclusive, collections::HashSet};
|
||||||
|
|
||||||
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
|
use itertools::Itertools;
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
lazy_static!(
|
||||||
|
static ref RULE_RE: Regex = Regex::new(r"(.*): (\d+)-(\d+) or (\d+)-(\d+)").unwrap();
|
||||||
|
);
|
||||||
|
|
||||||
|
#[aoc_generator(day16)]
|
||||||
|
fn parse(input: &str) -> (Vec<(String, RangeInclusive<usize>, RangeInclusive<usize>)>, Vec<usize>, Vec<Vec<usize>>) {
|
||||||
|
let (rules, my_ticket, tickets) = input
|
||||||
|
.split("\n\n")
|
||||||
|
.collect_tuple()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let rules = RULE_RE
|
||||||
|
.captures_iter(rules)
|
||||||
|
.filter_map(|captures| {
|
||||||
|
Some((
|
||||||
|
captures.get(1)?.as_str().to_string(),
|
||||||
|
captures.get(2)?.as_str().parse::<usize>().ok()?..=captures.get(3)?.as_str().parse::<usize>().ok()?,
|
||||||
|
captures.get(4)?.as_str().parse::<usize>().ok()?..=captures.get(5)?.as_str().parse::<usize>().ok()?,
|
||||||
|
))
|
||||||
|
}).collect_vec();
|
||||||
|
|
||||||
|
let my_ticket = my_ticket
|
||||||
|
.lines()
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
.split(',')
|
||||||
|
.filter_map(|num| num.parse::<usize>().ok())
|
||||||
|
.collect_vec();
|
||||||
|
|
||||||
|
let tickets = tickets
|
||||||
|
.lines()
|
||||||
|
.skip(1)
|
||||||
|
.map(|line| {
|
||||||
|
line
|
||||||
|
.split(',')
|
||||||
|
.filter_map(|num| num.parse::<usize>().ok())
|
||||||
|
.collect_vec()
|
||||||
|
}).collect_vec();
|
||||||
|
|
||||||
|
(rules, my_ticket, tickets)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day16, part1)]
|
||||||
|
fn part1((rules, _, tickets): &(Vec<(String, RangeInclusive<usize>, RangeInclusive<usize>)>, Vec<usize>, Vec<Vec<usize>>)) -> usize {
|
||||||
|
let mut invalid = 0;
|
||||||
|
for ticket in tickets {
|
||||||
|
for item in ticket {
|
||||||
|
if !rules.iter().any(|rule| {
|
||||||
|
rule.1.contains(item) || rule.2.contains(item)
|
||||||
|
}) {
|
||||||
|
invalid += item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
invalid
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day16, part2)]
|
||||||
|
fn part2((rules, my_ticket, tickets): &(Vec<(String, RangeInclusive<usize>, RangeInclusive<usize>)>, Vec<usize>, Vec<Vec<usize>>)) -> usize {
|
||||||
|
let mut tickets = tickets.clone();
|
||||||
|
let mut rem = 0;
|
||||||
|
for (i, ticket) in tickets.clone().iter().enumerate() {
|
||||||
|
for item in ticket {
|
||||||
|
if !rules.iter().any(|rule| {
|
||||||
|
rule.1.contains(item) || rule.2.contains(item)
|
||||||
|
}) {
|
||||||
|
tickets.remove(i - rem);
|
||||||
|
rem += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut possible_rules = get_possible_rules(&tickets, rules);
|
||||||
|
let mut assigned_rules = [0; 20];
|
||||||
|
while let Some(i) = possible_rules.iter().position(|s| s.len() == 1) {
|
||||||
|
let v = *possible_rules[i].iter().next().unwrap();
|
||||||
|
assigned_rules[i] = v;
|
||||||
|
for s in &mut possible_rules { s.remove(&v); }
|
||||||
|
}
|
||||||
|
assigned_rules.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|(_,&rule)| rule < 6)
|
||||||
|
.map(|(i,_)| my_ticket[i])
|
||||||
|
.product()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_possible_rules(tickets: &Vec<Vec<usize>>, rules: &Vec<(String, RangeInclusive<usize>, RangeInclusive<usize>)>) -> Vec<HashSet<usize>> {
|
||||||
|
(0..20).map(|i|
|
||||||
|
(0..20).filter(|&j|
|
||||||
|
tickets.iter().all(|t| fits_rule(&rules[j], t[i]))
|
||||||
|
).collect()
|
||||||
|
).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fits_rule((_, r1,r2): &(String, RangeInclusive<usize>, RangeInclusive<usize>), v: usize) -> bool {
|
||||||
|
r1.contains(&v) || r2.contains(&v)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const EX: &str = r"class: 1-3 or 5-7
|
||||||
|
row: 6-11 or 33-44
|
||||||
|
seat: 13-40 or 45-50
|
||||||
|
|
||||||
|
your ticket:
|
||||||
|
7,1,14
|
||||||
|
|
||||||
|
nearby tickets:
|
||||||
|
7,3,47
|
||||||
|
40,4,50
|
||||||
|
55,2,20
|
||||||
|
38,6,12";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1_example() {
|
||||||
|
assert_eq!(part1(&parse(EX)), 71);
|
||||||
|
}
|
||||||
|
|
||||||
|
const EX2: &str = r"class: 0-1 or 4-19
|
||||||
|
row: 0-5 or 8-19
|
||||||
|
seat: 0-13 or 16-19
|
||||||
|
|
||||||
|
your ticket:
|
||||||
|
11,12,13
|
||||||
|
|
||||||
|
nearby tickets:
|
||||||
|
3,9,18
|
||||||
|
15,1,5
|
||||||
|
5,14,9";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2_example() {
|
||||||
|
assert_eq!(part2(&parse(EX2)), 1716);
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
mod day16;
|
||||||
mod day15;
|
mod day15;
|
||||||
mod day14;
|
mod day14;
|
||||||
mod day13;
|
mod day13;
|
||||||
|
Loading…
Reference in New Issue
Block a user