Day 4
This commit is contained in:
parent
a617d211ba
commit
fc8f28cf22
4 changed files with 306 additions and 0 deletions
91
2018/Cargo.lock
generated
91
2018/Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -4,3 +4,4 @@ version = "0.1.0"
|
|||
authors = ["Jeremy Kaplan <jdkaplan@metagram.net>"]
|
||||
|
||||
[dependencies]
|
||||
regex = "1"
|
||||
|
|
|
|||
211
2018/src/day4.rs
Normal file
211
2018/src/day4.rs
Normal file
|
|
@ -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<Entry> {
|
||||
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<Entry>) -> Vec<Minute> {
|
||||
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<Minute>) -> 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>) -> 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<String, Vec<u32>> {
|
||||
let mut minutes_asleep: HashMap<String, Vec<u32>> = 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<String, Vec<u32>> {
|
||||
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::<u32>().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::<u32>().unwrap(), m.clone()));
|
||||
}
|
||||
}
|
||||
let (g, m) = mode2(points);
|
||||
g * m
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue