Link to AOC: https://adventofcode.com/2022/day/7
I'm doing the aoc in Rust and I am stuck on day 7. The code works on example input but doesn't on normal. For some context, the file tree is:
.
├── example_input.txt
├── input.txt
├── src
├── bin
│ └── part_1.rs
└── lib.rs
input.txt contains this: kfkorulczyk.pl/aoc_d7_input
And example input is this:
$ 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
Output from the normal input should be 1501149 but is 1035695.
Here is the code:
lib.rs
#![allow(unused)]
use std::borrow::{Borrow, BorrowMut};
use std::cell::RefCell;
use std::fmt;
macro_rules! get_part {
($line:expr, $index:expr) => {
$line.split(" ").nth($index).unwrap()
};
}
#[derive(Debug)]
pub struct Dir<'a> {
pub name: &'a str,
pub files: Vec<File<'a>>,
pub dirs: Vec<Dir<'a>>,
}
impl<'a> Dir<'a> {
pub fn add_content_to_subdir(
&mut self,
destination_dir: &str,
new_dir: &'a str,
new_file: Option<File<'a>>,
) -> () {
let destination_dir = self.find_dir(destination_dir).unwrap();
match new_file {
Some(expr) => destination_dir.files.push(expr),
None => destination_dir.dirs.push(Dir {
name: new_dir,
files: Vec::new(),
dirs: Vec::new(),
}),
}
}
pub fn find_dir<'b>(&'b mut self, name: &str) -> Option<&'b mut Dir<'a>> {
if self.name == name {
return Some(self);
}
self.dirs.iter_mut().find_map(|dir| dir.find_dir(name))
}
pub fn find_dir_not_mut<'b>(&'b self, name: &str) -> Option<&'b Dir<'a>> {
if self.name == name {
return Some(self);
}
self.dirs.iter().find_map(|dir| dir.find_dir_not_mut(name))
}
}
fn calculate_size_of_folder<'a>(dir: &'a RefCell<Dir<'a>>, name: &str) -> Option<i64> {
let mut sum = 0;
let search_in = dir.borrow();
let search_in = search_in.find_dir_not_mut(name).unwrap();
for file in &search_in.files {
sum += file.size;
}
if sum > 100000 {
return None;
}
for subdir in &search_in.dirs {
if let Some(size) = calculate_size_of_folder(dir, &subdir.name) {
sum += size;
}
}
if sum > 100000 {
return None;
}
Some(sum)
}
#[derive(Debug)]
pub struct File<'a> {
pub name: &'a str,
pub size: i64,
}
fn read_input<'a>(
input: &'a str,
dir: &'a RefCell<Dir<'a>>,
) -> (&'a RefCell<Dir<'a>>, Vec<String>) {
let mut file = File { name: "", size: 13 };
let mut all_dirs = vec![];
let mut dir_name = "";
let mut found_dir = "";
for line in input.lines() {
match line {
line if line.starts_with("$ ls") => {}
line if line.starts_with("$ cd ..") => {}
line if line.starts_with("$ cd ") => {
dir_name = get_part!(line, 2);
all_dirs.push(dir_name.to_string());
}
line if line.starts_with("dir ") => {
found_dir = get_part!(line, 1);
dir.borrow_mut()
.add_content_to_subdir(dir_name, found_dir, None);
}
_ => {
let size: i64 = get_part!(line, 0).parse::<i64>().unwrap();
let size: i64 = get_part!(line, 0).parse::<i64>().unwrap();
let name = get_part!(line, 1);
dir.borrow_mut().add_content_to_subdir(
dir_name,
"",
Some(File { size, name }),
);
}
}
}
(dir, all_dirs)
}
pub fn part_one(input: &str) {
let mut dir = RefCell::new(Dir {
name: "/",
files: vec![],
dirs: vec![],
});
let (file_tree, mut all_dirs) = read_input(&input, &dir);
let mut sum = 0;
for dir in &all_dirs {
let dir_size = calculate_size_of_folder(file_tree, &dir);
match dir_size {
Some(expr) => sum += expr,
None => (),
}
}
println!("{}", sum);
}
part_one.rs
use d7::*;
use std::fs;
fn main() {
let input = fs::read_to_string("input.txt").unwrap();
part_one(input);
}
You probably know but
cargo install cargo-watch
and cargo watch -x "run --bin part_1"
helps a lot.
I tried redoing the calculate_size_of_folder
function but it didn't work. Also, the return of a calculate_size_of_folder
is an option and I am checking if the size is less than 100000 because if I won't I get a stack overflow error.