150 lines
4.5 KiB
Rust
150 lines
4.5 KiB
Rust
use chrono::prelude::*;
|
|
use chrono::Duration;
|
|
use chrono::NaiveDateTime;
|
|
use std::collections::HashMap;
|
|
use crate::utils;
|
|
|
|
enum Activity {
|
|
Starts(u32),
|
|
FallsAsleep,
|
|
Awakens,
|
|
}
|
|
|
|
#[derive(PartialEq)]
|
|
enum State {
|
|
Asleep,
|
|
Awake,
|
|
}
|
|
|
|
pub fn task1() {
|
|
use self::Activity::*;
|
|
let input = utils::read_file("input/day04.txt");
|
|
let mut input: Vec<_> = input
|
|
.lines()
|
|
.map(|line| {
|
|
// [1518-10-26 00:01] Guard #1069 begins shift
|
|
let time = NaiveDateTime::parse_from_str(&line[1..=16], "%Y-%m-%d %H:%M").unwrap();
|
|
let activity = if line.contains("falls asleep") {
|
|
Activity::FallsAsleep
|
|
} else if line.contains("wakes up") {
|
|
Activity::Awakens
|
|
} else {
|
|
let number: u32 = line.split(' ').find(|part| part.starts_with("#")).unwrap()[1..]
|
|
.parse()
|
|
.unwrap();
|
|
Activity::Starts(number)
|
|
};
|
|
(time, activity)
|
|
}).collect();
|
|
input.sort_by_key(|it| it.0);
|
|
|
|
let mut current_id: u32 = 0;
|
|
let mut current_state = State::Awake;
|
|
let mut last_time = input[0].0;
|
|
let mut sleep_map: HashMap<u32, [usize; 60]> = HashMap::new();
|
|
let minute = Duration::minutes(1);
|
|
for (time, activity) in input.into_iter() {
|
|
// for all minutes since last time slot fill arrays
|
|
let mut iter_time = last_time.clone();
|
|
while iter_time < time {
|
|
if current_state == State::Asleep && iter_time.hour() == 0 {
|
|
sleep_map.entry(current_id).or_insert([0; 60])[iter_time.minute() as usize] += 1;
|
|
}
|
|
iter_time += minute;
|
|
}
|
|
|
|
match activity {
|
|
Starts(id) => {
|
|
current_state = State::Awake;
|
|
current_id = id;
|
|
}
|
|
FallsAsleep => current_state = State::Asleep,
|
|
Awakens => current_state = State::Awake,
|
|
}
|
|
last_time = time;
|
|
}
|
|
|
|
let sleeper = sleep_map
|
|
.iter()
|
|
.map(|(id, schedule)| (id, schedule.iter().sum::<usize>()))
|
|
.max_by_key(|it| it.1)
|
|
.unwrap();
|
|
println!("Sleeper: {:?}", sleeper);
|
|
|
|
let worst_minute = sleep_map
|
|
.get(sleeper.0)
|
|
.unwrap()
|
|
.iter()
|
|
.enumerate()
|
|
.max_by_key(|it| it.1)
|
|
.unwrap()
|
|
.0;
|
|
|
|
println!("Worst minute: {}", worst_minute);
|
|
|
|
println!("Result: {}", *sleeper.0 as usize * worst_minute);
|
|
}
|
|
|
|
pub fn task2() {
|
|
use self::Activity::*;
|
|
let input = utils::read_file("input/day04.txt");
|
|
let mut input: Vec<_> = input
|
|
.lines()
|
|
.map(|line| {
|
|
// [1518-10-26 00:01] Guard #1069 begins shift
|
|
let time = NaiveDateTime::parse_from_str(&line[1..=16], "%Y-%m-%d %H:%M").unwrap();
|
|
let activity = if line.contains("falls asleep") {
|
|
Activity::FallsAsleep
|
|
} else if line.contains("wakes up") {
|
|
Activity::Awakens
|
|
} else {
|
|
let number: u32 = line.split(' ').find(|part| part.starts_with("#")).unwrap()[1..]
|
|
.parse()
|
|
.unwrap();
|
|
Activity::Starts(number)
|
|
};
|
|
(time, activity)
|
|
}).collect();
|
|
input.sort_by_key(|it| it.0);
|
|
|
|
let mut current_id: u32 = 0;
|
|
let mut current_state = State::Awake;
|
|
let mut last_time = input[0].0;
|
|
let mut sleep_map: HashMap<u32, [usize; 60]> = HashMap::new();
|
|
let minute = Duration::minutes(1);
|
|
for (time, activity) in input.into_iter() {
|
|
// for all minutes since last time slot fill arrays
|
|
let mut iter_time = last_time.clone();
|
|
while iter_time < time {
|
|
if current_state == State::Asleep && iter_time.hour() == 0 {
|
|
sleep_map.entry(current_id).or_insert([0; 60])[iter_time.minute() as usize] += 1;
|
|
}
|
|
iter_time += minute;
|
|
}
|
|
|
|
match activity {
|
|
Starts(id) => {
|
|
current_state = State::Awake;
|
|
current_id = id;
|
|
}
|
|
FallsAsleep => current_state = State::Asleep,
|
|
Awakens => current_state = State::Awake,
|
|
}
|
|
last_time = time;
|
|
}
|
|
|
|
let sleeper = sleep_map
|
|
.iter()
|
|
.max_by_key(|(_, array)| array.iter().max())
|
|
.unwrap();
|
|
let worst_minute = sleeper
|
|
.1
|
|
.iter()
|
|
.enumerate()
|
|
.max_by_key(|it| it.1)
|
|
.unwrap()
|
|
.0;
|
|
|
|
println!("Result 2: {}", *sleeper.0 as usize * worst_minute);
|
|
}
|