main
idylls 1 year ago
parent 129e510c80
commit 5b177f1453
Signed by: idylls
GPG Key ID: 8A7167CBC2CC9F0F

@ -0,0 +1,188 @@
static INPUT: &str = include_str!("inputs/day7.txt");
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
struct FileID(usize);
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
struct DirID(usize);
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
enum DirEntryKind {
File(FileID),
Dir(DirID),
}
#[derive(Debug)]
struct DirEntry {
name: String,
kind: DirEntryKind,
}
#[derive(Debug)]
struct File {
size: usize,
}
#[derive(Debug)]
struct Dir {
parent: DirID,
children: Vec<DirEntry>,
}
#[derive(Debug)]
struct Fs {
files: Vec<File>,
dirs: Vec<Dir>,
}
impl Fs {
fn new() -> Self {
Self {
files: vec![],
dirs: vec![Dir {
parent: DirID(0),
children: vec![],
}],
}
}
fn root(&self) -> DirID {
DirID(0)
}
fn mkdir(&mut self, target: DirID, name: &str) -> DirID {
let new_id = DirID(self.dirs.len());
self.dirs.push(Dir {
parent: target,
children: vec![],
});
self.dirs[target.0].children.push(DirEntry {
name: name.to_string(),
kind: DirEntryKind::Dir(new_id),
});
new_id
}
fn mkfile(&mut self, target: DirID, name: &str, size: usize) -> FileID {
let new_id = FileID(self.files.len());
self.files.push(File { size });
self.dirs[target.0].children.push(DirEntry {
name: name.to_string(),
kind: DirEntryKind::File(new_id),
});
new_id
}
fn entry(&self, target: DirID, name: &str) -> DirEntryKind {
let dir = &self.dirs[target.0];
dir.children
.iter()
.find(|e| e.name == name)
.map(|e| e.kind)
.unwrap()
}
fn parent(&self, target: DirID) -> DirID {
self.dirs[target.0].parent
}
fn dirsz(&self, target: DirID) -> usize {
let dir = &self.dirs[target.0];
dir.children
.iter()
.map(|c| match c.kind {
DirEntryKind::File(fid) => self.files[fid.0].size,
DirEntryKind::Dir(did) => self.dirsz(did),
})
.sum()
}
}
fn make_fs(s: &str) -> Fs {
let mut lines = s.split('\n').filter(|s| !s.is_empty()).peekable();
let mut fs = Fs::new();
let mut current_dir = fs.root();
while let Some(line) = lines.next() {
assert!(line.starts_with('$'));
let mut parts = line.split(' ').skip(1);
match parts.next().unwrap() {
"cd" => {
let arg = parts.next().unwrap();
current_dir = match arg {
"/" => fs.root(),
".." => fs.parent(current_dir),
_ => {
let entry = fs.entry(current_dir, arg);
match entry {
DirEntryKind::Dir(d) => d,
_ => panic!(),
}
}
};
}
"ls" => {
while let Some(data_line) = lines.peek() {
if data_line.starts_with('$') {
break;
}
let mut parts = data_line.split(' ');
let ty = parts.next().unwrap();
let name = parts.next().unwrap();
match ty {
"dir" => {
fs.mkdir(current_dir, name);
}
_ => {
let sz: usize = ty.parse().unwrap();
fs.mkfile(current_dir, name, sz);
}
}
lines.next();
}
}
_ => panic!(),
}
}
fs
}
pub fn part1() {
let fs = make_fs(INPUT);
println!(
"{}",
fs.dirs
.iter()
.enumerate()
.map(|(did, _)| fs.dirsz(DirID(did)))
.filter(|sz| sz <= &100000)
.sum::<usize>()
);
}
pub fn part2() {
let fs = make_fs(INPUT);
let total = 70_000_000;
let needed_free = 30_000_000;
let used = fs.dirsz(fs.root());
let free = total - used;
let diff = needed_free - free;
println!(
"{}",
fs.dirs
.iter()
.enumerate()
.map(|(did, _)| fs.dirsz(DirID(did)))
.filter(|sz| sz >= &diff)
.min()
.unwrap()
);
}

File diff suppressed because it is too large Load Diff

@ -6,8 +6,9 @@ mod day3;
mod day4;
mod day5;
mod day6;
mod day7;
mod util;
fn main() {
day6::part2();
day7::part2();
}

Loading…
Cancel
Save