07 Rust

Part I Assignment

Rust is a compiled language, you first need to compile it with rustc and then run it.

rustc 07.rs && ./07

The code.

use std::fs::File;
use std::io::{BufReader, BufRead, Error};


const THRESHOLD: i32 = 100000;


fn main() -> Result<(), Error> {
    // open file and propagate error
    let file = File::open("07.input")?;
    // buffered reader
    let reader = BufReader::new(file);

    // vector of integers to store stack
    let mut stack: Vec<i32> = Vec::new();
    // cummulative sum of directory sizes
    let mut cum = 0;

    // iterate over lines in the file
    for line in reader.lines() {
        // if the reading fails we panic
        let l = line.unwrap();

        // process commands; slicing the line
        if &l[..1] == "$" {
            // ls
            if &l[2..4] == "ls" {
                // we don't need to process this command
                continue;
            // cd /
            } else if &l[5..6] == "/" {
                // initialize stack with 0 size for /
                stack.push(0);
            }
            // cd ..
            else if &l[5..7] == ".." {
                // going up in the directory tree
                // at the top of stack we have size for the current dir
                let dc = stack.pop().unwrap();
                // if it is below threshold, we should count
                if dc < THRESHOLD {
                    cum += dc;
                }
                // updating the parent with the size
                let old = stack.pop().unwrap();
                stack.push(old + dc);
            }
            // cd <dir>
            else {
                // initialize size for the current directory
                stack.push(0);
            }
        }
        // process dir listing
        else {
            // <num> file
            if &l[..3] != "dir" {
                // split the line and convert string into integer
                let size: i32 = l
                    .split_whitespace()
                    .next()
                    .unwrap_or("")
                    .parse()
                    .unwrap();
                // update the size of the current dir
                let old = stack.pop().unwrap();
                stack.push(old + size);
            }
            // we ignore directory listings, we will process them later anyway
        }
    }

    // process the rest of the stack
    while stack.len() > 0 {
        let pop = stack.pop().unwrap();
        // counting as before
        if pop < THRESHOLD {
            cum += pop
        }
    }

    // print the result
    println!("{}", cum);

    // return unit
    Ok(())
}

Part II

The process is very similar, we just need to store all directory sizes (after all the files in them are counted) and at the end, decide how many bytes to remove and find the smallest directory with its size larger than the “missing” bytes.

use std::fs::File;
use std::io::{BufReader, BufRead, Error};


const REQUIRED: i32 = 40_000_000;


fn main() -> Result<(), Error> {
    let file = File::open("07.input")?;
    let reader = BufReader::new(file);

    let mut stack: Vec<i32> = Vec::new();
    // all sizes to select the ideal directory (size) later
    let mut all: Vec<i32> = Vec::new();

    for line in reader.lines() {
        let l = line.unwrap();
        if &l[..1] == "$" {
            if &l[2..4] == "ls" {
                continue;
            } else if &l[5..6] == "/" {
                stack.push(0);
            }
            else if &l[5..7] == ".." {
                let dc = stack.pop().unwrap();
                let old = stack.pop().unwrap();
                stack.push(old + dc);
                // remember the size of the directory
                all.push(dc);
            }
            else {
                stack.push(0);
            }
        }
        else {
            if &l[..3] != "dir" {
                let size: i32 = l
                    .split_whitespace()
                    .next()
                    .unwrap_or("")
                    .parse()
                    .unwrap();
                let old = stack.pop().unwrap();
                stack.push(old + size);
                // we are updating, no need to remember nothing here
            }
        }
    }

    while stack.len() > 1 {
        let dc = stack.pop().unwrap();
        let old = stack.pop().unwrap();
        stack.push(old + dc);
        // remember the final sizes of directories
        all.push(dc);
    }
    // total size of data
    let total: i32 = stack.pop().unwrap();
    // sort so the search is simple forward pass
    all.sort();

    // if data is small we don't need anything
    if REQUIRED - total >= 0 {
        println!("Nothing to delete...");
    }
    else {
        // we need to remove at least <todelete> bytes
        let todelete: i32 = total - REQUIRED;

        // iter over the remembered directory sizes
        for elem in all.iter() {
            // gotcha!
            if *elem > todelete {
                println!("Delete the directory with size {}", elem);
                break;
            }
        }
    }

    Ok(())
}

What I learned

published: 2022-12-07
last modified: 2023-01-21

https://vit.baisa.cz/notes/code/advent-of-code-2022/07/