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:
A | src/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)