From 16877f5f1d8dafd98dd2346875dd6e7abe383a3b Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Thu, 8 Dec 2022 11:27:58 -0600 Subject: [PATCH] Day 7 done... forgot to commit last night --- 2022/rust/src/day7.rs | 166 +++++++++--------------------------------- 1 file changed, 35 insertions(+), 131 deletions(-) diff --git a/2022/rust/src/day7.rs b/2022/rust/src/day7.rs index fb99fff..d4f5aee 100644 --- a/2022/rust/src/day7.rs +++ b/2022/rust/src/day7.rs @@ -1,107 +1,61 @@ mod common; -use std::cell::RefCell; -use std::collections::HashMap; -use std::collections::HashSet; -use std::rc::Rc; +use std::{collections::HashMap, num::Wrapping}; -#[derive(Debug, Clone)] -struct DirTree { - files: HashMap, - subdirectories: HashMap>>, - parent: Option>>, -} - -impl DirTree { - pub fn new(parent: Option>>) -> Self { - Self { - files: HashMap::new(), - subdirectories: HashMap::new(), - parent, - } - } - - pub fn root() -> Self { - Self::new(None) - } -} - -type Input = Rc>; -type Result = usize; +type Result = Wrapping; +type Input = HashMap; fn processed_input(input: &str) -> Input { - let root = Rc::new(RefCell::new(DirTree::root())); - let mut current_dir = Rc::clone(&root); + let mut result: Input = HashMap::from([("/".to_string(), Wrapping(0))]); + let mut current_path = vec![]; + + let vp = |v: &[&str]| format!("/{}", v.join("/")); for l in input.lines() { println!("line: {}", l); if l == "$ cd /" { - current_dir = Rc::clone(&root); + println!("cwd '/'"); + current_path.clear(); } else if l == "$ ls" { continue; } else if l.starts_with("dir ") { - let d = &l[4..]; - current_dir.borrow_mut().subdirectories.insert( - d.to_string(), - Rc::new(RefCell::new(DirTree::new(Some(Rc::clone(¤t_dir))))), - ); + current_path.push(&l[4..]); + let p = vp(¤t_path); + println!("inserting path '{}'", p); + current_path.pop(); + result.insert(p, Wrapping(0)); } else if l.starts_with("$ cd ..") { - let cur = Rc::clone(¤t_dir); - current_dir = Rc::clone(&cur.borrow().parent.as_ref().unwrap()); + current_path.pop(); + println!("cwd '{}'", vp(¤t_path)); } else if l.starts_with("$ cd ") { - let d = &l[5..]; - let cur = Rc::clone(¤t_dir); - current_dir = Rc::clone(&cur.borrow().subdirectories.get(d).unwrap()); + current_path.push(&l[5..]); + println!("cwd '{}'", vp(¤t_path)); } else { - let mut args = l.split(' '); - let size = args.next().unwrap().parse::().unwrap(); - current_dir - .borrow_mut() - .files - .insert(args.next().unwrap().to_string(), size); + let size = l.split(' ').next().unwrap().parse::().unwrap(); + for i in (0..=current_path.len()).rev() { + let p = vp(¤t_path[0..i]); + println!("adding {} to path '{}'", size, p); + *(result.get_mut(&p).unwrap()) += size; + } } } - return root; + + return result; } const PART1_LIMIT: usize = 100_000; -fn dfs1(input: Input, path: String) -> usize { - let dt = input.borrow(); - - let files_size = dt.files.values().map(|r| r.to_owned()).sum::(); - let subdir_sizes: Vec = dt - .subdirectories - .iter() - .map(|(p, sdt)| dfs1(sdt.clone(), format!("{}/{}", path, p))) - .collect(); - let subdirs_size = subdir_sizes.iter().sum::(); - let this_dir_size = subdirs_size + files_size; - - let counted = subdir_sizes.iter().filter(|s| **s < PART1_LIMIT).sum(); - - println!( - "path: {}, files: {:?}, files_size: {}, subdirs_size: {}, counted: {}", - path, dt.files, files_size, subdirs_size, counted - ); - let mut r = counted; - if this_dir_size < PART1_LIMIT { - r = counted + this_dir_size; - } - println!( - "return {}, {}", - counted + this_dir_size, - "hy" // std::backtrace::Backtrace::capture() - ); - return r; -} - fn part1(input: &Input) -> Result { - dfs1(input.clone(), "".to_string()) + let lim = Wrapping(PART1_LIMIT); + input.values().filter(|s| **s < lim).sum() } fn part2(input: &Input) -> Result { - 0 + let to_free = input.get("/").unwrap() - Wrapping(40_000_000); + *input + .values() + .min_by(|a, b| (**a - to_free).cmp(&(**b - to_free))) + .unwrap() } fn main() { @@ -109,13 +63,8 @@ fn main() { eprintln!("{}\n\nAbove is your input file.\n\n", input_text); let input = processed_input(&input_text); common::show_answers(&part1(&input), &part2(&input)) - // common::show_both_answers(&both_parts(&input)) } -// fn both_parts(input: &Input) -> (Result, Result) { -// (0, 0) -// } - #[cfg(test)] mod tests { use super::*; @@ -147,52 +96,7 @@ $ ls #[test] fn test() { let input = processed_input(TEST_INPUT); - assert_eq!(part1(&input), 95437); - assert_eq!(part2(&input), 0); - // assert_eq!(both_parts(&input), (0, 0)); - } - - const TEST_INPUT2: &str = "$ cd / -$ ls -dir a -100 x.txt -$ cd a -$ ls -dir b -100 y.txt -$ cd b -$ ls -100 z.txt"; - const TEST_INPUT3: &str = "$ cd / -$ ls -dir a -100 x.txt -$ cd a -$ ls -dir b -100 y.txt -$ cd b -$ ls -dir c -100 z.txt -$ cd c -$ ls -100 zz.txt"; - // $ cd a - // $ ls - // dir a - // 100 c.txt - // $ cd a - // $ ls - // 100 d.txt - // "; - - #[test] - fn test2() { - let input = processed_input(TEST_INPUT2); - assert_eq!(part1(&input), 600); - let input3 = processed_input(TEST_INPUT2); - assert_eq!(part1(&input), 1000); - // assert_eq!(both_parts(&input), (0, 0)); + assert_eq!(part1(&input), Wrapping(95437)); + assert_eq!(part2(&input), Wrapping(24933642)); } }