diff --git a/2022/rust/src/solutions/day07.rs b/2022/rust/src/solutions/day07.rs index e548fda..b07ee2a 100644 --- a/2022/rust/src/solutions/day07.rs +++ b/2022/rust/src/solutions/day07.rs @@ -4,7 +4,7 @@ use crate::utils; pub fn run() -> () { - let data = parse_data(utils::read_lines(utils::Source::Day(7))); + let data = parse_data(&utils::read_lines(utils::Source::Day(7))); println!("Day 7"); println!("Part 1: {}", solve1(&data)); @@ -23,6 +23,7 @@ struct FileNode { size: i32, } +#[derive(Default)] struct Node<'data> { name: &'data str, // Backref pointer @@ -31,14 +32,8 @@ struct Node<'data> { subdirs: Vec>>, } -impl<'data> Node<'data> { - fn new(name: &'data str, parent: Option<*mut Node<'data>>) -> Node<'data> { - Node { name, parent, files: vec![], subdirs: vec![] } - } -} - fn cli_to_tree(data: &[CliEntry]) -> Box { - let mut root = Box::new(Node::new("/", None)); + let mut root = Box::new(Node { name: "/", ..Default::default() }); let mut current: &mut Node = root.as_mut(); for command in data { @@ -59,7 +54,7 @@ fn cli_to_tree(data: &[CliEntry]) -> Box { CliEntry::Ls => {}, CliEntry::Dir(name) => { let current_ptr = current as *mut Node; - current.subdirs.push(Box::new(Node::new(name, Some(current_ptr)))); + current.subdirs.push(Box::new(Node { name, parent: Some(current_ptr), ..Default::default() })); }, CliEntry::File(_, size) => { current.files.push(FileNode { size: *size }) @@ -69,23 +64,24 @@ fn cli_to_tree(data: &[CliEntry]) -> Box { root } -fn find_sizes(root: &Box) -> (i32, BinaryHeap) { - let mut acc: i32 = root.files.iter().map(|f| f.size).sum(); - let mut sizes: BinaryHeap = BinaryHeap::new(); - root.subdirs.iter().for_each(|subdir| { - let (sub_size, sub_sizes) = find_sizes(subdir); - sizes.extend(sub_sizes.iter()); - acc += sub_size; - }); - sizes.push(acc); - (acc, sizes) +fn find_sizes(node: &Box, heap: &mut BinaryHeap) -> i32 { + let mut acc: i32 = 0; + for file in &node.files { + acc += file.size; + } + for subdir in &node.subdirs { + acc += find_sizes(subdir, heap); + } + heap.push(acc); + acc } fn solve1(data: &[CliEntry]) -> i32 { let tree = cli_to_tree(&data[1..]); - let (_, sizes) = find_sizes(&tree); + let mut heap: BinaryHeap = BinaryHeap::new(); + find_sizes(&tree, &mut heap); - sizes.into_iter() + heap.into_iter() .filter_map(|size| size .le(&100000) .then_some(size) @@ -97,10 +93,11 @@ fn solve2(data: &[CliEntry]) -> i32 { static DISK_SPACE: i32 = 70000000; static REQUIRED: i32 = 30000000; let tree = cli_to_tree(&data[1..]); - let (size, sizes) = find_sizes(&tree); + let mut heap: BinaryHeap = BinaryHeap::new(); + let size = find_sizes(&tree, &mut heap); let threshold = REQUIRED - (DISK_SPACE - size); - sizes.into_sorted_vec() + heap.into_sorted_vec() .into_iter() .filter(|&x| x > threshold) .next() @@ -108,9 +105,10 @@ fn solve2(data: &[CliEntry]) -> i32 { } -fn parse_data(data: Vec) -> Vec { +fn parse_data>(data: &[T]) -> Vec { data.into_iter() - .map(|s| { + .map(|str_ref| { + let s = str_ref.as_ref(); let mut parts = s.split_whitespace().into_iter(); if s.starts_with('$') { match parts.nth(1).unwrap() { @@ -134,31 +132,28 @@ fn parse_data(data: Vec) -> Vec { mod tests { use super::*; - fn data() -> Vec { - vec![ - "$ 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", - ] - .into_iter().map(String::from).collect() - } + static DATA: &[&str; 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", + ]; #[test] fn part1() { - let data = parse_data(data()); + let data = parse_data(DATA); assert_eq!(95437, solve1(&data)); } #[test] fn part2() { - let data = parse_data(data()); + let data = parse_data(DATA); assert_eq!(24933642, solve2(&data)); } }