Compare commits

...

2 Commits

Author SHA1 Message Date
30edbeb9b9 day 7 2022-12-07 16:12:30 +01:00
67fc0bbcb5 drop the itertools again 2022-12-07 11:01:46 +01:00
6 changed files with 1273 additions and 2 deletions

1096
inputs/day7.txt Normal file

File diff suppressed because it is too large Load Diff

8
src/bin/day07_1.rs Normal file
View File

@@ -0,0 +1,8 @@
use std::fs;
use aoc2022::day07::process_part_1;
fn main() {
let file = fs::read_to_string("./inputs/day7.txt").unwrap();
println!("{}", process_part_1(&file));
}

8
src/bin/day07_2.rs Normal file
View File

@@ -0,0 +1,8 @@
use std::fs;
use aoc2022::day07::process_part_2;
fn main() {
let file = fs::read_to_string("./inputs/day7.txt").unwrap();
println!("{}", process_part_2(&file));
}

View File

@@ -1,4 +1,4 @@
use itertools::Itertools;
use std::collections::BTreeSet;
pub fn process_part_1(input: &str) -> usize {
find_unique_window_start(input, 4)
@@ -14,7 +14,7 @@ pub fn find_unique_window_start(input: &str, window_size: usize) -> usize {
.chars()
.collect::<Vec<_>>()
.windows(window_size)
.take_while(|x| x.iter().unique().count() != x.len())
.take_while(|x| x.iter().collect::<BTreeSet<_>>().len() != x.len())
.count()
}

158
src/day07.rs Normal file
View File

@@ -0,0 +1,158 @@
use std::collections::BTreeMap;
use nom::branch::alt;
use nom::bytes::complete::{tag, take_till1};
use nom::character::complete::{newline, space1};
use nom::character::{complete, is_newline};
use nom::multi::separated_list1;
use nom::IResult;
pub fn process_part_1(input: &str) -> u32 {
let (_, commands) = parse_commands(input).unwrap();
let directories = build_directory_tree_from_commands(commands);
directories.values().filter(|size| **size <= 100_000).sum()
}
pub fn process_part_2(input: &str) -> u32 {
let (_, commands) = parse_commands(input).unwrap();
let directories = build_directory_tree_from_commands(commands);
let total_space = 70_000_000;
let required_space = 30_000_000;
let current_space = total_space - *directories.get("").unwrap();
let wanted_space = required_space - current_space;
directories
.values()
.filter(|size| **size >= wanted_space)
.map(|size| *size)
.min()
.unwrap_or(0)
}
fn build_directory_tree_from_commands(commands: Vec<Command>) -> BTreeMap<String, u32> {
let mut cwd: Vec<&str> = vec![];
let mut directories: BTreeMap<String, u32> = BTreeMap::new();
for command in commands {
match command {
Command::Cd("/") => {
cwd = vec![];
}
Command::Cd("..") => {
cwd.pop();
}
Command::Cd(name) => {
cwd.push(name);
}
Command::Ls(files) => {
for file in files {
match file {
DirEntry::File { name: _name, size } => {
for i in 0..=cwd.len() {
directories
.entry(cwd[..i].join("/"))
.and_modify(|f| *f += size)
.or_insert(size);
}
}
_ => {}
}
}
}
}
}
directories
}
#[derive(Debug)]
enum Command<'a> {
Cd(&'a str),
Ls(Vec<DirEntry<'a>>),
}
#[derive(Debug)]
enum DirEntry<'a> {
Dir(&'a str),
File { name: &'a str, size: u32 },
}
fn parse_commands(input: &str) -> IResult<&str, Vec<Command>> {
separated_list1(newline, parse_command)(input)
}
fn parse_command(input: &str) -> IResult<&str, Command> {
let (input, _) = tag("$ ")(input)?;
alt((parse_cd, parse_ls))(input)
}
fn parse_cd(input: &str) -> IResult<&str, Command> {
let (input, _) = tag("cd")(input)?;
let (input, _) = space1(input)?;
let (input, arg) = parse_file_name(input)?;
Ok((input, Command::Cd(arg)))
}
fn parse_ls(input: &str) -> IResult<&str, Command> {
let (input, _) = tag("ls")(input)?;
let (input, _) = newline(input)?;
let (input, entries) =
separated_list1(tag("\n"), alt((parse_dir_entry_dir, parse_dir_entry_file)))(input)?;
Ok((input, Command::Ls(entries)))
}
fn parse_dir_entry_dir(input: &str) -> IResult<&str, DirEntry> {
let (input, _) = tag("dir ")(input)?;
let (input, name) = parse_file_name(input)?;
Ok((input, DirEntry::Dir(name)))
}
fn parse_dir_entry_file(input: &str) -> IResult<&str, DirEntry> {
let (input, size) = complete::u32(input)?;
let (input, _) = tag(" ")(input)?;
let (input, name) = parse_file_name(input)?;
Ok((input, DirEntry::File { name, size }))
}
fn parse_file_name(input: &str) -> IResult<&str, &str> {
take_till1(|c| is_newline(c as u8))(input)
}
#[cfg(test)]
mod tests {
use super::*;
const INPUT: &str = "$ cd /
$ ls
dir a
14848514 b.txt
8504156 c.dat
dir d
$ cd a
$ ls
dir e
29116 f
2557 g
62596 h.lst
$ cd e
$ ls
584 i
$ cd ..
$ cd ..
$ cd d
$ ls
4060174 j
8033020 d.log
5626152 d.ext
7214296 k";
#[test]
fn day1() {
assert_eq!(process_part_1(INPUT), 95437);
}
#[test]
fn day2() {
assert_eq!(process_part_2(INPUT), 24933642);
}
}

View File

@@ -7,3 +7,4 @@ pub mod day03;
pub mod day04;
pub mod day05;
pub mod day06;
pub mod day07;