Add skeleton for day 16 #14

Open
tlater wants to merge 3 commits from tlater/day-16 into master
3 changed files with 124 additions and 8 deletions
Showing only changes of commit dd5fafc242 - Show all commits

50
day-16/Cargo.lock generated
View file

@ -1,10 +1,21 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "day-16" name = "day-16"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"indoc", "indoc",
"lazy_static",
"regex",
] ]
[[package]] [[package]]
@ -30,6 +41,18 @@ dependencies = [
"unindent", "unindent",
] ]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "memchr"
version = "2.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
[[package]] [[package]]
name = "proc-macro-hack" name = "proc-macro-hack"
version = "0.5.19" version = "0.5.19"
@ -54,6 +77,24 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "regex"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"thread_local",
]
[[package]]
name = "regex-syntax"
version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.54" version = "1.0.54"
@ -65,6 +106,15 @@ dependencies = [
"unicode-xid", "unicode-xid",
] ]
[[package]]
name = "thread_local"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
dependencies = [
"lazy_static",
]
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.2.1" version = "0.2.1"

View file

@ -8,3 +8,5 @@ edition = "2018"
[dependencies] [dependencies]
indoc = "0.3" indoc = "0.3"
lazy_static = "1.4"
regex = "1.4"

View file

@ -1,23 +1,87 @@
use std::collections::HashMap;
use std::fs; use std::fs;
use std::ops::RangeInclusive;
use lazy_static::lazy_static;
use regex::Regex;
type Rules = HashMap<String, (RangeInclusive<u32>, RangeInclusive<u32>)>;
type Ticket = Vec<u32>;
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let input = fs::read_to_string("input")?; let input = fs::read_to_string("input")?;
let (_, tickets) = parse_tickets(&input)?; let (rules, _, tickets) = parse_tickets(&input)?;
// Part 1 // Part 1
let invalid = get_invalid_values(&tickets); let invalid = get_invalid_values(&rules, &tickets);
println!("{}", invalid.iter().sum::<u32>()); println!("{}", invalid.iter().sum::<u32>());
Ok(()) Ok(())
} }
fn parse_tickets(input: &str) -> Result<(Vec<u32>, Vec<Vec<u32>>), &str> { fn parse_tickets(input: &str) -> Result<(Rules, Ticket, Vec<Ticket>), String> {
unimplemented!() let blocks: Vec<&str> = input.split("\n\n").collect();
let parse_u32 = |val: &str| {
val.parse::<u32>()
.map_err(|e| format!("Invalid number: {}", e))
};
if blocks.len() < 3 {
Err("Input incomplete")?;
} }
fn get_invalid_values(tickets: &Vec<Vec<u32>>) -> Vec<u32> { let rules = blocks[0]
unimplemented!() .lines()
.map(|line| {
lazy_static! {
static ref RULE_RE: Regex =
Regex::new(r"([[:alpha:]]+?): (\d+)-(\d+) or (\d+)-(\d+)")
.expect("Regex should compile");
}
let caps = RULE_RE
.captures(line)
.ok_or(format!("Invalid rule line: {}", line))?;
let name = caps[1].to_string();
let range1 = parse_u32(&caps[2])?..=parse_u32(&caps[3])?;
let range2 = parse_u32(&caps[4])?..=parse_u32(&caps[5])?;
Ok((name, (range1, range2)))
})
.collect::<Result<Rules, String>>()?;
let own_ticket = blocks[1]
.lines()
.skip(1)
.next()
.ok_or("Input incomplete")?
.split(',')
.map(|c| parse_u32(c))
.collect::<Result<Ticket, String>>()?;
let other_tickets = blocks[2]
.lines()
.skip(1)
.map(|line| line.split(',').map(|c| parse_u32(c)).collect())
.collect::<Result<Vec<Ticket>, String>>()?;
Ok((rules, own_ticket, other_tickets))
}
fn get_invalid_values(rules: &Rules, tickets: &Vec<Ticket>) -> Vec<u32> {
tickets
.iter()
.flat_map(|ticket| {
ticket.iter().filter(|value| {
!rules
.values()
.any(|(rule1, rule2)| rule1.contains(value) || rule2.contains(value))
})
})
.copied()
.collect()
} }
#[cfg(test)] #[cfg(test)]
@ -44,8 +108,8 @@ mod tests {
" "
); );
let (_, tickets) = parse_tickets(input)?; let (rules, _, tickets) = parse_tickets(input)?;
let invalid = get_invalid_values(&tickets); let invalid = get_invalid_values(&rules, &tickets);
assert_eq!(invalid.iter().sum::<u32>(), 71); assert_eq!(invalid.iter().sum::<u32>(), 71);