[rs] Solve 2022_07 part 1

This commit is contained in:
Joscha 2022-12-07 13:34:59 +01:00
parent d1f20886fb
commit 04f61205cb
7 changed files with 1198 additions and 0 deletions

1045
inputs/2022/2022_07.input Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,2 @@
Part 1: 1243729
Part 2: ???

View file

@ -46,6 +46,7 @@ days! {
Y2022D04: "2022_04", Y2022D04: "2022_04",
Y2022D05: "2022_05", Y2022D05: "2022_05",
Y2022D06: "2022_06", Y2022D06: "2022_06",
Y2022D07: "2022_07",
} }
#[derive(Parser)] #[derive(Parser)]
@ -75,6 +76,7 @@ fn main() -> io::Result<()> {
Day::Y2022D04 => y2022::d04::solve(input), Day::Y2022D04 => y2022::d04::solve(input),
Day::Y2022D05 => y2022::d05::solve(input), Day::Y2022D05 => y2022::d05::solve(input),
Day::Y2022D06 => y2022::d06::solve(input), Day::Y2022D06 => y2022::d06::solve(input),
Day::Y2022D07 => y2022::d07::solve(input),
} }
eprintln!() eprintln!()
} }

View file

@ -4,3 +4,4 @@ pub mod d03;
pub mod d04; pub mod d04;
pub mod d05; pub mod d05;
pub mod d06; pub mod d06;
pub mod d07;

123
rs/src/y2022/d07.rs Normal file
View file

@ -0,0 +1,123 @@
use std::collections::HashMap;
enum LsItem {
File(usize, String),
Dir(String),
}
enum Command {
Cd(String),
Ls(Vec<LsItem>),
}
enum Fs {
Dir(HashMap<String, Fs>),
File(usize),
}
impl Fs {
fn as_dir(&mut self) -> &mut HashMap<String, Self> {
match self {
Fs::Dir(map) => map,
Fs::File(_) => panic!("Not a directory"),
}
}
fn at_path(&mut self, path: &[String]) -> &mut Self {
let mut result = self;
for segment in path {
result = result.as_dir().get_mut(segment).unwrap();
}
result
}
fn size(&self) -> usize {
match self {
Fs::Dir(map) => map.values().map(|v| v.size()).sum(),
Fs::File(size) => *size,
}
}
fn dirs(&self) -> Vec<&Self> {
let mut result = vec![];
if let Fs::Dir(map) = self {
result.push(self);
for value in map.values() {
result.extend(value.dirs());
}
}
result
}
}
fn command_chunks(input: &str) -> Vec<(String, Vec<String>)> {
let mut lines = input.lines().peekable();
let mut chunks = vec![];
while let Some(command) = lines.next() {
assert!(command.starts_with("$ "));
let mut items = vec![];
while let Some(item) = lines.peek() {
if item.starts_with("$ ") {
break;
}
items.push(item.to_string());
lines.next();
}
chunks.push((command.to_string(), items));
}
chunks
}
pub fn solve(input: String) {
// Parse commands
let commands = command_chunks(&input)
.into_iter()
.map(|(command, items)| {
if let Some(name) = command.strip_prefix("$ cd ") {
Command::Cd(name.to_string())
} else {
assert_eq!(command, "$ ls");
let ls_items = items
.into_iter()
.map(|item| {
let (left, name) = item.split_once(' ').unwrap();
if left == "dir" {
LsItem::Dir(name.to_string())
} else {
LsItem::File(left.parse::<usize>().unwrap(), name.to_string())
}
})
.collect::<Vec<_>>();
Command::Ls(ls_items)
}
})
.collect::<Vec<_>>();
// Build fs tree
let mut fs = Fs::Dir(HashMap::new());
let mut path = vec![];
for command in commands {
match command {
Command::Cd(to) if to == "/" => path = vec![],
Command::Cd(to) if to == ".." => _ = path.pop(), // Learned a new trick
Command::Cd(to) => path.push(to),
Command::Ls(items) => {
for item in items {
let map = fs.at_path(&path).as_dir();
match item {
LsItem::File(size, name) => map.insert(name, Fs::File(size)),
LsItem::Dir(name) => map.insert(name, Fs::Dir(HashMap::new())),
};
}
}
}
}
let part1 = fs
.dirs()
.into_iter()
.map(|d| d.size())
.filter(|s| *s <= 100000)
.sum::<usize>();
println!("Part 1: {part1}");
}

View file

@ -0,0 +1,23 @@
$ 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

View file

@ -0,0 +1,2 @@
Part 1: 95437
Part 2: ???