From fc8f28cf22a91566f23ec9ff250441445967b095 Mon Sep 17 00:00:00 2001 From: Jeremy Kaplan Date: Sun, 9 Dec 2018 14:22:41 -0800 Subject: [PATCH] Day 4 --- 2018/Cargo.lock | 91 ++++++++++++++++++++ 2018/Cargo.toml | 1 + 2018/src/day4.rs | 211 +++++++++++++++++++++++++++++++++++++++++++++++ 2018/src/main.rs | 3 + 4 files changed, 306 insertions(+) create mode 100644 2018/src/day4.rs diff --git a/2018/Cargo.lock b/2018/Cargo.lock index 988096e..3d46c36 100644 --- a/2018/Cargo.lock +++ b/2018/Cargo.lock @@ -1,4 +1,95 @@ +[[package]] +name = "aho-corasick" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "aoc2018" version = "0.1.0" +dependencies = [ + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] +[[package]] +name = "cfg-if" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazy_static" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.44" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ucd-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "utf8-ranges" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" +"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311" +"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16" +"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" +"checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" +"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" diff --git a/2018/Cargo.toml b/2018/Cargo.toml index 169ce49..8ac8ef7 100644 --- a/2018/Cargo.toml +++ b/2018/Cargo.toml @@ -4,3 +4,4 @@ version = "0.1.0" authors = ["Jeremy Kaplan "] [dependencies] +regex = "1" diff --git a/2018/src/day4.rs b/2018/src/day4.rs new file mode 100644 index 0000000..f0a9313 --- /dev/null +++ b/2018/src/day4.rs @@ -0,0 +1,211 @@ +use std::collections::HashMap; + +extern crate regex; + +const INPUT: &str = include_str!("input/day4.txt"); +// const INPUT: &str = include_str!("input/day4_test.txt"); + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] +struct Timestamp { + date: String, + hour: u32, + minute: u32, +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +enum Event { + WokeUp, + FellAsleep, + ShiftChange(String), +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +struct Entry { + timestamp: Timestamp, + event: Event, +} + +fn parse_input() -> Vec { + let re: regex::Regex = + regex::Regex::new(r"^\[(\d{4}-\d{2}-\d{2}) (\d{2}):(\d{2})] (.*)$").unwrap(); + let re_shift: regex::Regex = regex::Regex::new(r"^Guard #(\d+) begins shift$").unwrap(); + let mut entries = Vec::new(); + for line in str::lines(INPUT) { + let caps = re.captures(line).unwrap(); + let date = caps.get(1).unwrap().as_str().to_string(); + let hour = caps.get(2).unwrap().as_str().to_string().parse().unwrap(); + let minute = caps.get(3).unwrap().as_str().to_string().parse().unwrap(); + let ev = match caps.get(4).unwrap().as_str() { + "wakes up" => Event::WokeUp, + "falls asleep" => Event::FellAsleep, + shift => { + let caps = re_shift.captures(shift).unwrap(); + Event::ShiftChange(caps.get(1).unwrap().as_str().to_string()) + } + }; + entries.push(Entry { + timestamp: Timestamp { + date: date, + hour: hour, + minute: minute, + }, + event: ev, + }); + } + entries +} + +#[derive(Debug, Clone)] +enum State { + Awake, + Asleep, +} + +#[derive(Debug, Clone)] +struct Minute { + timestamp: Timestamp, + guard: String, + state: State, +} + +fn get_events(entries: &mut Vec) -> Vec { + entries.sort(); + match entries[0].event { + Event::ShiftChange(_) => (), + _ => panic!("Invalid entry list!"), + } + + let mut states = Vec::new(); + let mut guard = "".to_string(); + for e in entries { + let m = match &e.event { + Event::ShiftChange(g) => { + guard = g.to_string(); + Minute { + timestamp: e.timestamp.clone(), + guard: guard.to_string(), + state: State::Awake, + } + } + Event::FellAsleep => Minute { + timestamp: e.timestamp.clone(), + guard: guard.to_string(), + state: State::Asleep, + }, + Event::WokeUp => Minute { + timestamp: e.timestamp.clone(), + guard: guard.to_string(), + state: State::Awake, + }, + }; + states.push(m); + } + states +} + +fn sleep_intervals(ms: Vec) -> Vec<((String, u32, u32))> { + let mut i = 0; + let mut ps = Vec::new(); + while i + 1 < ms.len() { + let p1 = ms[i].clone(); + let p2 = ms[i + 1].clone(); + match (p1, p2) { + ( + Minute { + timestamp: + Timestamp { + date: _, + hour: _, + minute: m1, + }, + guard: g1, + state: State::Asleep, + }, + Minute { + timestamp: + Timestamp { + date: _, + hour: _, + minute: m2, + }, + guard: g2, + state: State::Awake, + }, + ) => { + if g1 == g2 { + ps.push((g1, m1, m2)); + } + } + _ => {} + } + i += 1; + } + ps +} + +fn mode(ms: Vec) -> u32 { + let mut buckets = HashMap::new(); + for m in ms { + let mut b = buckets.entry(m).or_insert(0); + *b += 1; + } + let mut elts: Vec<(&u32, &u32)> = buckets.iter().collect(); + elts.sort_by(|l, r| r.1.cmp(l.1)); + *(elts[0].0) +} + +fn interpolate_sleep(sleeps: Vec<(String, u32, u32)>) -> HashMap> { + let mut minutes_asleep: HashMap> = HashMap::new(); + for (g, m1, m2) in sleeps { + let mut ms = minutes_asleep.entry(g).or_insert(Vec::new()); + let mut m = m1; + while m < m2 { + ms.push(m); + m += 1; + } + } + minutes_asleep +} + +fn sleep_data() -> HashMap> { + let mut input = parse_input(); + let events = get_events(&mut input); + let sleeps = sleep_intervals(events); + let minutes_asleep = interpolate_sleep(sleeps); + minutes_asleep +} + +pub fn part1() -> u32 { + let mut most_asleep = ("".to_string(), Vec::new()); + for (g, ms) in sleep_data() { + if ms.len() > most_asleep.1.len() { + most_asleep = (g, ms); + } + } + + let guard = most_asleep.0.parse::().unwrap(); + let minute = mode(most_asleep.1); + minute * guard +} + +fn mode2(ms: Vec<(u32, u32)>) -> (u32, u32) { + let mut buckets = HashMap::new(); + for m in ms { + let mut b = buckets.entry(m).or_insert(0); + *b += 1; + } + let mut elts: Vec<(&(u32, u32), &u32)> = buckets.iter().collect(); + elts.sort_by(|l, r| r.1.cmp(l.1)); + *(elts[0].0) +} + +pub fn part2() -> u32 { + let mut points: Vec<(u32, u32)> = Vec::new(); + for (g, ms) in sleep_data() { + for m in ms { + points.push((g.parse::().unwrap(), m.clone())); + } + } + let (g, m) = mode2(points); + g * m +} diff --git a/2018/src/main.rs b/2018/src/main.rs index e6cf65f..bde3e90 100644 --- a/2018/src/main.rs +++ b/2018/src/main.rs @@ -1,6 +1,7 @@ mod day1; mod day2; mod day3; +mod day4; fn main() { println!("Day 1 part 1: {}", day1::part1()); @@ -9,4 +10,6 @@ fn main() { println!("Day 2 part 2: {}", day2::part2()); println!("Day 3 part 1: {}", day3::part1()); println!("Day 3 part 2: {}", day3::part2()); + println!("Day 4 part 1: {}", day4::part1()); + println!("Day 4 part 2: {}", day4::part2()); }