advent_of_code_2022

My (attempted) solutions to the 2022 Advent of Code
git clone https://git.eamoncaddigan.net/advent_of_code_2022.git
Log | Files | Refs | README

commit fcb6488ab7d307a0b9316ee8c7fbfc61b17a3687
parent d72cd3ad8036ada77c2b7ddc3fa76d9da2dc855a
Author: Eamon Caddigan <eamon.caddigan@gmail.com>
Date:   Wed,  7 Dec 2022 19:03:12 -0800

Solution to day 7, part 1.

Diffstat:
Asrc/day_7.jl | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 126 insertions(+), 0 deletions(-)

diff --git a/src/day_7.jl b/src/day_7.jl @@ -0,0 +1,126 @@ +#!/usr/bin/env julia +# https://adventofcode.com/2022/day/7 +using AdventOfCode + +example = readlines(IOBuffer(""" + \$ 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""")) +input = readlines("data/day_7.txt") + +# Finally diving into Julia's object orientation. I could do this without OO, +# and if I was using R I definitely would, but since this is a learning +# exercise I figured it was a good time to learn this. Cool stuff! I like how +# methods aren't object members, they're just rely on polymorphism like +# everything else. I like inner and outer constructors too. I don't really need +# to save object names (at least not for part 1), but I'm just doing OOP over +# here. +# +# One thing I didn't like: I'm developing in a REPL, and updating my code with +# `include` doesn't work if you don't wrap structs in a module. That's really +# the only reason to use a module here. + +module FileSystem + struct File + name::AbstractString + size::Int + end + + struct Directory + parent::Union{Nothing, Directory} + name::AbstractString + contents::Dict{AbstractString, Union{File, Directory}} + end + Directory(parent, name) = Directory(parent, name, Dict()) +end + +function build_directory(input::Vector{<:AbstractString})::FileSystem.Directory + fs = FileSystem.Directory(nothing, "/") + currdir::FileSystem.Directory = fs + @assert input[1] == "\$ cd /" + + for line = input[2:end] + if line == "\$ ls" + # No need to do anything, the next line(s) will list directory + # contents + nothing + elseif line == "\$ cd .." + # Change to the parent directory + currdir = currdir.parent + elseif line[1:5] == "\$ cd " + # Change to specified subdirectry + currdir = currdir.contents[line[6:end]] + else + # Receive directory contents + sizeortype, name = split(line, " ") + if sizeortype == "dir" + # A directory! + currdir.contents[name] = FileSystem.Directory(currdir, name) + else + # A file! + currdir.contents[name] = FileSystem.File(name, + parse(Int, sizeortype)) + end + end + end + + fs +end + +# Create a dictionary with the size of the given directory and every directory +# it contains +function size_directories(fs::FileSystem.Directory)::Dict{FileSystem.Directory, Int} + dirsizes = Dict() + + # Recursively calculate the size of a directory, filling dirsizes[] as a + # side effect (I know, I know). We get memoization though! + function size_directory(d::FileSystem.Directory)::Int + if !haskey(dirsizes, d) + dirsizes[d] = 0 + for item = values(d.contents) + if typeof(item) == FileSystem.File + dirsizes[d] += item.size + else + dirsizes[d] += size_directory(item) + end + end + end + dirsizes[d] + end + + size_directory(fs) + dirsizes +end + +function part_1(input) + sum([x for x in values(size_directories(build_directory(input))) + if x < 100000]) +end +@assert part_1(example) == 95437 +@info part_1(input) + +function part_2(input) + nothing +end +@assert part_2(example) == nothing +@info part_2(input)