链接到AOC:https://adventofcode.com/2022/day/7
我在Rust中做AOC,我被困在第7天。代码可以在示例输入上工作,但不能在普通输入上工作。对于某些上下文,文件树是:
.
├── example_input.txt
├── input.txt
├── src
├── bin
│ └── part_1.rs
└── lib.rs
input.txt包含以下内容:kfkorulczyk.pl/aoc_d7_input
示例输入如下:
$ 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
正常输入的输出应为1501149,但为1035695。
下面是代码:
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);
}
第一部分
use d7::*;
use std::fs;
fn main() {
let input = fs::read_to_string("input.txt").unwrap();
part_one(input);
}
你可能知道,但cargo install cargo-watch
和cargo watch -x "run --bin part_1"
帮助很大。
我试着重做calculate_size_of_folder
函数,但它没有工作。此外,返回calculate_size_of_folder
是一个选项,我正在检查大小是否小于100000,因为如果我不这样做,我会得到堆栈溢出错误。
1条答案
按热度按时间juzqafwq1#
我在代码中看到的主要bug是忽略了
cd ..
。这个问题要求你通过一个目录树来建模 * 导航 *;在模拟中的所有点,您的系统都有一个它所占用的“当前目录”。当您看到命令cd ..
时,您的系统应该向上移动一级,到父目录,然后从那里继续。