aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--2022/nim/day07/src/main.nim68
-rw-r--r--2022/rust/day07/Cargo.lock7
-rw-r--r--2022/rust/day07/Cargo.toml8
-rw-r--r--2022/rust/day07/src/main.rs104
4 files changed, 187 insertions, 0 deletions
diff --git a/2022/nim/day07/src/main.nim b/2022/nim/day07/src/main.nim
new file mode 100644
index 0000000..da3bd90
--- /dev/null
+++ b/2022/nim/day07/src/main.nim
@@ -0,0 +1,68 @@
+# Day 7: No Space Left On Device
+import std/[os, strutils]
+
+let input = paramStr(1).readFile().strip().split("\n")
+
+type File = object
+ id: string
+ size: int
+
+type Dir = ref object
+ id: string
+ files: seq[File]
+ dirs: seq[Dir]
+ parent: Dir
+ size: int
+
+var root = Dir(id: "/")
+var current = root
+for line in input[1..^1]:
+ let output = line.split(" ")
+ if output.len == 2:
+ if output[0] == "$":
+ discard
+ elif output[0] == "dir":
+ current.dirs.add(Dir(id: output[1], parent: current))
+ else:
+ current.files.add(File(id: output[1], size: output[0].parseInt()))
+ else:
+ assert output[1] == "cd"
+ if output[2] == "..":
+ current = current.parent
+ else:
+ for i in current.dirs:
+ if i.id == output[2]:
+ current = i
+ break
+
+proc update_size(a: Dir) =
+ for i in a.files:
+ a.size += i.size
+ for i in a.dirs:
+ i.update_size()
+ a.size += i.size
+root.update_size()
+
+const maximum_size = 100000
+
+var sum = 0
+proc calc_size(a: Dir) =
+ if a.size <= maximum_size:
+ sum += a.size
+ for i in a.dirs:
+ i.calc_size()
+root.calc_size()
+echo sum
+
+const total_space = 70000000
+const update_space = 30000000
+let needed_space = update_space - (total_space - root.size)
+
+var min = update_space
+proc calc_min(a: Dir) =
+ if a.size >= needed_space:
+ min = min(a.size, min)
+ for i in a.dirs:
+ i.calc_min()
+root.calc_min()
+echo min
diff --git a/2022/rust/day07/Cargo.lock b/2022/rust/day07/Cargo.lock
new file mode 100644
index 0000000..cf14c74
--- /dev/null
+++ b/2022/rust/day07/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "day07"
+version = "0.1.0"
diff --git a/2022/rust/day07/Cargo.toml b/2022/rust/day07/Cargo.toml
new file mode 100644
index 0000000..682e4ad
--- /dev/null
+++ b/2022/rust/day07/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "day07"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/2022/rust/day07/src/main.rs b/2022/rust/day07/src/main.rs
new file mode 100644
index 0000000..1ea8840
--- /dev/null
+++ b/2022/rust/day07/src/main.rs
@@ -0,0 +1,104 @@
+use std::cell::{Cell, RefCell};
+use std::cmp;
+use std::env;
+use std::fs;
+use std::rc::Rc;
+
+struct Directory {
+ id: String,
+ size: Cell<i32>,
+ // mmm i'd rather have a plain Directory instead of Rc<Directory>
+ // but i get "cannot move out of x which is behind a shared reference"
+ children: RefCell<Vec<Rc<Directory>>>,
+ parent: Option<Rc<Directory>>
+}
+
+fn main() {
+ let args = env::args().nth(1).expect("missing input");
+ let input = fs::read_to_string(args).unwrap();
+ let history: Vec<&str> = input.trim().split("\n").collect();
+
+ let root = Rc::new(Directory {
+ id: String::from("/"),
+ size: Cell::from(0),
+ children: RefCell::from(Vec::new()),
+ parent: None
+ });
+
+ let mut current = root.clone();
+ for line in &history[1..] {
+ let output = line.split(" ");
+ match output.collect::<Vec<&str>>()[..] {
+ ["$", "ls"] => {
+ // println!("$ ls")
+ },
+ ["$", "cd", ".."] => {
+ current = current.parent.clone().unwrap();
+ // println!("$ cd ..");
+ },
+ ["$", "cd", id] => {
+ let mut next: Option<Rc<Directory>> = None;
+ for i in &*current.children.borrow() {
+ if i.id == id {
+ next = Option::from(i.clone());
+ break;
+ }
+ }
+ current = next.unwrap();
+ // println!("$ cd {}", id);
+ },
+ ["dir", id] => {
+ (current.children.borrow_mut()).push(Rc::from(Directory {
+ id: String::from(id),
+ size: Cell::from(0),
+ children: RefCell::from(Vec::new()),
+ parent: Option::from(current.clone())
+ }));
+ // println!("dir {}", id)
+ },
+ [size, id] => {
+ current.size.replace(current.size.get() + size.parse::<i32>().unwrap());
+ // println!("{} {}", size, id)
+ },
+ _ => panic!("crash and burn"),
+ }
+ }
+
+ // Corrects directory sizes by adding the size of nested directories to the directory
+ fn populate_size(a: &Rc<Directory>) {
+ for i in &*a.children.borrow() {
+ populate_size(&i);
+ a.size.set(a.size.get() + i.size.get());
+ }
+ }
+ populate_size(&root);
+
+ const maximum_space: i32 = 100000;
+ fn calc_size(a: &Rc<Directory>) -> i32 {
+ let mut sum = 0;
+ for i in &*a.children.borrow() {
+ sum += calc_size(&i);
+ }
+ if a.size.get() <= maximum_space {
+ sum += a.size.get();
+ }
+ return sum;
+ }
+ println!("{}", calc_size(&root));
+
+ const total_space: i32 = 70000000;
+ const update_space: i32 = 30000000;
+ // no global variables?? O_O
+ let needed_space = update_space - (total_space - root.size.get());
+ fn calc_min(a: &Rc<Directory>, min: i32, need: i32) -> i32 {
+ let mut min = min;
+ if a.size.get() >= need {
+ min = cmp::min(a.size.get(), min);
+ }
+ for i in &*a.children.borrow() {
+ min = cmp::min(calc_min(&i, min, need), min);
+ }
+ return min;
+ }
+ println!("{}", calc_min(&root, update_space, needed_space));
+}