Day 7, puzzle 1

This commit is contained in:
jazzpi 2022-12-14 13:26:20 +01:00
parent a446a05c07
commit bedf4a790a
3 changed files with 179 additions and 0 deletions

20
src/bin/d7p1.rs Normal file
View File

@ -0,0 +1,20 @@
use aoc22::{day7, util};
const MAX_SIZE: usize = 100000;
pub fn main() {
let root = day7::parse_cmdline(&util::parse_input());
let mut total_size = 0;
for child in root.borrow().all_children() {
let c = &*child.borrow();
if let day7::Node::Dir { .. } = c {
let size = c.size();
if size <= MAX_SIZE {
total_size += size;
}
}
}
println!("Total size of small directories: {}", total_size);
}

158
src/day7.rs Normal file
View File

@ -0,0 +1,158 @@
use std::{cell::RefCell, collections::HashMap, rc::Rc, vec};
use regex::Regex;
#[derive(Debug)]
pub enum Node {
File {
name: String,
size: usize,
},
Dir {
name: String,
children: HashMap<String, Rc<RefCell<Node>>>,
parent: Option<Rc<RefCell<Node>>>,
},
}
impl Node {
pub fn print(&self, level: usize) {
match self {
Node::File { name, size } => println!("{0:1$}| {2}\t{3}", "", level * 2, name, size),
Node::Dir { name, children, .. } => {
println!("{0:1$}| {2}", "", level * 2, name);
println!("{0:1$} \\", "", level * 2);
for (_, child) in children {
(**child).borrow().print(level + 1);
}
}
}
}
pub fn size(&self) -> usize {
match self {
Node::File { size, .. } => *size,
Node::Dir { children, .. } => children.iter().map(|(_, c)| (**c).borrow().size()).sum(),
}
}
pub fn all_children(&self) -> Vec<Rc<RefCell<Node>>> {
match self {
Node::File { .. } => vec![],
Node::Dir { children, .. } => {
let mut result: Vec<Rc<RefCell<Node>>> = children.values().map(Rc::clone).collect();
for (_, child) in children {
result.append(&mut (**child).borrow().all_children());
}
result
}
}
}
}
enum ParseState {
Command,
ListOutput,
}
pub fn parse_cmdline(input: &String) -> Rc<RefCell<Node>> {
let lines = input.lines();
let mut state = ParseState::Command;
let root = Rc::new(RefCell::new(Node::Dir {
name: "/".to_owned(),
children: HashMap::new(),
parent: None,
}));
let mut current_node = root.clone();
for line in lines {
if line.starts_with("$") {
state = ParseState::Command;
}
match state {
ParseState::Command => {
let cmd = parse_command(line);
match cmd {
Command::ChangeDirRoot => current_node = root.clone(),
Command::ChangeDirParent => {
let next_node = if let Node::Dir { parent, .. } = &*(*current_node).borrow()
{
match parent {
Some(p) => p.clone(),
None => root.clone(),
}
// parent.unwrap_or(root.clone()).clone()
} else {
panic!("Current node is a file!?");
};
current_node = next_node;
}
Command::ChangeDirChild(name) => {
let next_node =
if let Node::Dir { children, .. } = &*(*current_node).borrow() {
children.get(name.as_str()).unwrap().clone()
} else {
panic!("Current node is a file!?");
};
current_node = next_node;
}
Command::List => state = ParseState::ListOutput,
}
}
ParseState::ListOutput => {
let node = parse_list_output(line, &current_node);
if let Node::Dir { children, .. } = &mut *(*current_node).borrow_mut() {
let n = match &node {
Node::File { name, .. } => name,
Node::Dir { name, .. } => name,
};
children.insert(n.clone(), Rc::new(RefCell::new(node)));
}
}
}
}
root
}
enum Command {
ChangeDirRoot,
ChangeDirParent,
ChangeDirChild(String),
List,
}
fn parse_command(line: &str) -> Command {
let re = Regex::new(r"^\$ (cd|ls)(?: (.*))?$").unwrap();
let captures = re.captures(line).unwrap();
if captures.get(1).unwrap().as_str() == "ls" {
assert!(captures.get(2) == None);
Command::List
} else {
let dir = captures.get(2).unwrap().as_str();
if dir == "/" {
Command::ChangeDirRoot
} else if dir == ".." {
Command::ChangeDirParent
} else {
Command::ChangeDirChild(dir.to_owned())
}
}
}
fn parse_list_output(line: &str, parent: &Rc<RefCell<Node>>) -> Node {
let (first, second) = line.split_once(' ').unwrap();
if first == "dir" {
Node::Dir {
name: second.to_owned(),
children: HashMap::new(),
parent: Some(parent.clone()),
}
} else {
Node::File {
name: second.to_owned(),
size: first.parse().unwrap(),
}
}
}

View File

@ -4,4 +4,5 @@ pub mod day3;
pub mod day4;
pub mod day5;
pub mod day6;
pub mod day7;
pub mod util;