finish day7
This commit is contained in:
parent
393db1d3bf
commit
6abb28f96f
122
2022/src/day7.rs
122
2022/src/day7.rs
@ -24,10 +24,10 @@ enum Node {
|
|||||||
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref CMD_CD: Regex = Regex::new(r"^\$ cd (\w+)$").unwrap();
|
static ref CMD_CD: Regex = Regex::new(r"^\$ cd (\S+)$").unwrap();
|
||||||
static ref CMD_LS: Regex = Regex::new(r"^\$ ls$").unwrap();
|
static ref CMD_LS: Regex = Regex::new(r"^\$ ls$").unwrap();
|
||||||
static ref DIR_LISTING: Regex = Regex::new(r"^dir (\w+)$").unwrap();
|
static ref DIR_LISTING: Regex = Regex::new(r"^dir (\S+)$").unwrap();
|
||||||
static ref FILE_LISTING: Regex = Regex::new(r"^(\d+) (\w+)$").unwrap();
|
static ref FILE_LISTING: Regex = Regex::new(r"^(\d+) (\S+)$").unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -58,8 +58,13 @@ fn build_map(data: &str) -> Result<HashMap<usize, NodeListing>, String> {
|
|||||||
'lines: for line in data.trim().lines() {
|
'lines: for line in data.trim().lines() {
|
||||||
if CMD_LS.is_match(line) {continue;}
|
if CMD_LS.is_match(line) {continue;}
|
||||||
|
|
||||||
if let Some(m) = CMD_CD.find_iter(line).next() {
|
if let Some(c) = CMD_CD.captures(line) {
|
||||||
let name = m.as_str();
|
let name = c.get(1).unwrap().as_str();
|
||||||
|
if name == "/" {
|
||||||
|
stack.truncate(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if name == ".." {
|
if name == ".." {
|
||||||
stack.pop();
|
stack.pop();
|
||||||
continue;
|
continue;
|
||||||
@ -69,13 +74,13 @@ fn build_map(data: &str) -> Result<HashMap<usize, NodeListing>, String> {
|
|||||||
NodeListing::Branch(dir) => dir,
|
NodeListing::Branch(dir) => dir,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
for id in current_dir.children {
|
for id in ¤t_dir.children {
|
||||||
let child_name = match map.get(&id).unwrap() {
|
let child_name = match map.get(&id).unwrap() {
|
||||||
NodeListing::Branch(dir) => dir.name,
|
NodeListing::Branch(dir) => &dir.name,
|
||||||
NodeListing::Leaf(file) => file.name,
|
NodeListing::Leaf(file) => &file.name,
|
||||||
};
|
};
|
||||||
if child_name == name {
|
if child_name == name {
|
||||||
stack.push(id);
|
stack.push(*id);
|
||||||
continue 'lines;
|
continue 'lines;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,28 +88,27 @@ fn build_map(data: &str) -> Result<HashMap<usize, NodeListing>, String> {
|
|||||||
return Err(format!("Attempted to cd into directory before ls-ing it: {}", line.to_string()));
|
return Err(format!("Attempted to cd into directory before ls-ing it: {}", line.to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(m) = DIR_LISTING.find_iter(line).next() {
|
if let Some(c) = DIR_LISTING.captures(line) {
|
||||||
let parent_id = stack.last().unwrap();
|
let parent_id = stack.last().unwrap();
|
||||||
|
let child_id = map.len();
|
||||||
let parent = match map.get_mut(parent_id).unwrap() {
|
let parent = match map.get_mut(parent_id).unwrap() {
|
||||||
NodeListing::Branch(dir) => dir,
|
NodeListing::Branch(dir) => dir,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
parent.children.push(child_id);
|
||||||
|
|
||||||
let dir = DirListing {
|
let dir = DirListing {
|
||||||
name: m.as_str().to_string(),
|
name: c.get(1).unwrap().as_str().to_string(),
|
||||||
children: vec![],
|
children: vec![],
|
||||||
parent: Some(*parent_id),
|
parent: Some(*parent_id),
|
||||||
};
|
};
|
||||||
// this is safe as long as we never remove anything from the map while we're building it
|
map.insert(child_id, NodeListing::Branch(dir));
|
||||||
let dir_id = map.len();
|
|
||||||
map.insert(dir_id, NodeListing::Branch(dir));
|
|
||||||
parent.children.push(dir_id);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let matches = FILE_LISTING.find_iter(line);
|
if let Some(c) = FILE_LISTING.captures(line) {
|
||||||
if let (Some(s), Some(n)) = (matches.next(), matches.next()) {
|
let name = c.get(2).unwrap().as_str().to_string();
|
||||||
let name = n.as_str().to_string();
|
let size = c.get(1).unwrap().as_str().parse::<usize>()
|
||||||
let size = s.as_str().parse::<usize>()
|
|
||||||
.map_err(|_e| format!("Invalid file size: {}", line.to_string()))?;
|
.map_err(|_e| format!("Invalid file size: {}", line.to_string()))?;
|
||||||
|
|
||||||
let file_id = map.len();
|
let file_id = map.len();
|
||||||
@ -126,16 +130,15 @@ fn build_map(data: &str) -> Result<HashMap<usize, NodeListing>, String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn build_tree(map: &HashMap<usize, NodeListing>, root:&DirListing) -> Directory {
|
fn build_tree(map: &mut HashMap<usize, NodeListing>, root_listing: &DirListing) -> Directory {
|
||||||
let root_listing = map.get(&root_id).unwrap();
|
let mut root_children = Vec::new();
|
||||||
let root_children = Vec::new();
|
for child_id in &root_listing.children {
|
||||||
for child_id in root_listing.children {
|
match map.remove(&child_id).unwrap() {
|
||||||
match map.get(&child_id).unwrap() {
|
|
||||||
NodeListing::Leaf(file) => {
|
NodeListing::Leaf(file) => {
|
||||||
root_children.push(Node::Leaf(file));
|
root_children.push(Node::Leaf(file));
|
||||||
},
|
},
|
||||||
NodeListing::Branch(dir_listing) => {
|
NodeListing::Branch(dir_listing) => {
|
||||||
let dir = build_tree(map, child_id);
|
let dir = build_tree(map, &dir_listing);
|
||||||
root_children.push(Node::Branch(dir))
|
root_children.push(Node::Branch(dir))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -149,33 +152,78 @@ fn build_tree(map: &HashMap<usize, NodeListing>, root:&DirListing) -> Directory
|
|||||||
|
|
||||||
|
|
||||||
fn get_sizes(root: &Directory, mut sizes: Vec<usize>) -> (usize, Vec<usize>) {
|
fn get_sizes(root: &Directory, mut sizes: Vec<usize>) -> (usize, Vec<usize>) {
|
||||||
let dir_size = 0;
|
let mut dir_size = 0;
|
||||||
|
|
||||||
let mut returned_sizes;
|
for child in &root.children {
|
||||||
for child in root.children {
|
|
||||||
match child {
|
match child {
|
||||||
Node::Leaf(file) => dir_size += file.size,
|
Node::Leaf(file) => dir_size += file.size,
|
||||||
Node::Branch(dir) => {
|
Node::Branch(dir) => {
|
||||||
let (child_size, rs) = get_sizes(dir, sizes);
|
let (child_size, rs) = get_sizes(dir, sizes);
|
||||||
returned_sizes = rs;
|
sizes = rs;
|
||||||
dir_size += child_size;
|
dir_size += child_size;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
returned_sizes.push(dir_size);
|
sizes.push(dir_size);
|
||||||
returned_sizes
|
(dir_size, sizes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn main() -> Result<(), String> {
|
fn main() -> Result<(), String> {
|
||||||
let map = build_map(data);
|
let mut map = build_map(DATA)?;
|
||||||
let tree = build_tree(map, 0);
|
let root = match map.remove(&0).unwrap() {
|
||||||
let (_total_size, dir_sizes) = get_sizes(&tree, vec![]);
|
NodeListing::Branch(dir) => dir,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
let part1_sizes = dir_sizes.iter()
|
let tree = build_tree(&mut map, &root);
|
||||||
.filter(|s| s <= 100000)
|
let (total_size, dir_sizes) = get_sizes(&tree, vec![]);
|
||||||
|
|
||||||
|
let part1_sizes: usize = dir_sizes.iter()
|
||||||
|
.filter(|&&s| s <= 100000)
|
||||||
.sum();
|
.sum();
|
||||||
|
|
||||||
println!("Part 1: {part1_sizes}");
|
println!("Part 1: {part1_sizes}");
|
||||||
|
|
||||||
|
let available = 70_000_000 - total_size;
|
||||||
|
if available >= 30_000_000 {
|
||||||
|
return Err("Weird, there's already enough space available".to_string());
|
||||||
|
}
|
||||||
|
let target_size = 30_000_000 - available;
|
||||||
|
|
||||||
|
let delete_size = dir_sizes.iter()
|
||||||
|
.filter(|&&s| s >= target_size)
|
||||||
|
.min()
|
||||||
|
.unwrap();
|
||||||
|
println!("Part 2: {delete_size}");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const DATA: &'static str = include_str!("../data/day7.txt");
|
||||||
|
// const DATA: &'static str = "
|
||||||
|
// $ 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
|
||||||
|
// ";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user