Improved readability by using unsafe rust

This commit is contained in:
Dreaded_X 2022-12-07 22:29:20 +01:00
parent a4da36a23b
commit dc44463638
Signed by: Dreaded_X
GPG Key ID: 76BDEC4E165D8AD9

View File

@ -1,9 +1,7 @@
#![feature(test)] #![feature(test)]
use core::fmt;
use std::{collections::HashMap, rc::Rc, cell::RefCell};
use anyhow::Result; use anyhow::Result;
use aoc::Solver; use aoc::Solver;
use implementation::Node;
// -- Runners -- // -- Runners --
fn main() -> Result<()> { fn main() -> Result<()> {
@ -45,74 +43,27 @@ mod tests {
} }
} }
// -- Implentation -- mod implementation {
#[derive(Default)] use std::collections::HashMap;
struct Node {
// Size of all files in this directory pub struct Node {
file_size: u32, size: u32,
nodes: HashMap<String, Rc<RefCell<Node>>>, children: HashMap<String, Self>,
parent: Option<Rc<RefCell<Node>>>, parent: *mut Self,
} }
impl Node { impl Node {
fn add_file(&mut self, size: u32) { pub fn default() -> Self {
self.file_size += size Self {
} size: 0,
children: HashMap::new(),
fn add_directory(&mut self, name: String, node: Rc<RefCell<Node>>) { parent: std::ptr::null_mut(),
self.nodes.insert(name, node);
}
fn get_directory(&self, name: &str) -> Option<Rc<RefCell<Node>>> {
match self.nodes.get(name) {
Some(node) => Some(Rc::clone(node)),
None => None,
} }
} }
fn get_parent(&mut self) -> Option<Rc<RefCell<Node>>> { pub fn new(input: &str) -> Self {
match &self.parent { let mut root = Node::default();
Some(parent) => Some(Rc::clone(parent)), let mut current = &mut root as *mut Node;
None => None
}
}
fn get_size(&self) -> u32 {
let mut size = self.file_size;
for (_, node) in &self.nodes {
size += node.borrow_mut().get_size()
}
size
}
fn get_sizes_flat(&self) -> Vec<u32> {
let mut dirs = vec![self.get_size()];
for (_, node) in &self.nodes {
dirs.extend(node.borrow_mut().get_sizes_flat())
}
dirs
}
}
impl fmt::Display for Node {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}\n", self.get_size())?;
for (name, node) in &self.nodes {
write!(f, "{}: {}", name, node.borrow_mut())?;
}
Ok(())
}
}
// -- Helpers --
fn parse(input: &str) -> Rc<RefCell<Node>> {
let root = Rc::new(RefCell::new(Node::default()));
let mut current = Rc::clone(&root);
input input
.lines() .lines()
@ -123,27 +74,33 @@ fn parse(input: &str) -> Rc<RefCell<Node>> {
// There are two cmds: ls, cd ${dir}, we only care about dir // There are two cmds: ls, cd ${dir}, we only care about dir
if let Some((_, dir)) = rest.split_once(" ") { if let Some((_, dir)) = rest.split_once(" ") {
match dir { match dir {
"/" => current = { "/" => current = &mut root as *mut Node,
Rc::clone(&root)
},
".." => { ".." => {
let parent = current.borrow_mut().get_parent().unwrap(); unsafe {
let parent = (*current).parent;
if parent == std::ptr::null_mut() {
panic!("Node has no parent")
}
current = parent; current = parent;
} }
}
name => { name => {
let dir = current.borrow_mut().get_directory(name).unwrap(); unsafe {
current = dir; current = (*current).get_directory(name).unwrap();
}
}, },
}; };
} }
}, },
"dir" => { "dir" => {
let dir = Rc::new(RefCell::new(Node::default())); unsafe {
dir.borrow_mut().parent = Some(Rc::clone(&current)); (*current).add_directory(rest.to_owned())
current.borrow_mut().add_directory(rest.to_owned(), Rc::clone(&dir)); }
}, },
size => { size => {
current.borrow_mut().add_file(size.parse().unwrap()) unsafe {
(*current).add_file(size.parse().unwrap())
}
}, },
} }
@ -152,6 +109,42 @@ fn parse(input: &str) -> Rc<RefCell<Node>> {
root root
} }
fn add_file(&mut self, size: u32) {
self.size += size;
}
fn add_directory(&mut self, name: String) {
let mut child = Self::default();
child.parent = self as *mut Self;
self.children.insert(name, child);
}
fn get_directory(&mut self, name: &str) -> Option<&mut Self> {
self.children.get_mut(name)
}
pub fn get_size(&self) -> u32 {
let mut size = self.size;
for (_, node) in &self.children {
size += node.get_size();
}
size
}
pub fn flatten_sizes(&self) -> Vec<u32> {
let mut dirs = vec![self.get_size()];
for (_, node) in &self.children {
dirs.extend(node.flatten_sizes())
}
dirs
}
}
}
// -- Solution -- // -- Solution --
pub struct Day; pub struct Day;
impl aoc::Solver for Day { impl aoc::Solver for Day {
@ -161,21 +154,18 @@ impl aoc::Solver for Day {
} }
fn part1(input: &str) -> Self::Output { fn part1(input: &str) -> Self::Output {
let root = parse(input); Node::new(input)
.flatten_sizes()
let sizes = root.borrow_mut().get_sizes_flat(); .iter()
sizes.iter()
.filter(|&&size| size < 100000) .filter(|&&size| size < 100000)
.sum() .sum()
} }
fn part2(input: &str) -> Self::Output { fn part2(input: &str) -> Self::Output {
let root = parse(input); let root = Node::new(input);
let need_to_free = root.get_size() - 40000000;
let mut sizes = root.borrow_mut().get_sizes_flat();
let need_to_free = sizes[0] - 40000000;
let mut sizes = root.flatten_sizes();
sizes.sort(); sizes.sort();
sizes.iter() sizes.iter()
.find_map(|&size| { .find_map(|&size| {