Question This was a fun day! we finally got something challenging.
We got a device from the elves when trying to update that device we got an error that notifies us that there isn’t enough memory on our device
|
|
To determine what’s going on we start exploring the device file system and record the output (our puzzle input) For example
|
|
represent the following structure
|
|
When I first solved it I iterated over all commands and didn’t create any kind of structure and just kept track of the current dir and update its parent size once we are done with it. I thought about trying something a bit more interesting for this post, let’s create a file system representation from our input and use it later to answer today’s puzzle
First, we need to make sense of each line of our input, for that we are going to create a tokenizer! our tokens
|
|
We have 4 types of tokens, one for each type of output line.
In addition, we also save the raw data in literal
so we can make use of it later on.
Now let’s write our tokenizer, its responsibility is to get our input and transform it into a list of meaningful tokens
|
|
Create a struct to represent our file system
|
|
Now to the fun part, going over our tokens and constructing a tree like structure based on that
|
|
We iterate over our tokens and perform some operations depending on the type of token we got
- file token: add the file size to the current dir
- dir token: create a new directory in the current dir and name it based on the token literal (the dir name)
- ls token: we don’t care about it and just continue our loop
- cd token:
- “..” literal: we change
current
to be `current.parent and add the size of the current dir to the parent - else, its some dir that we have seen before using
ls
and we change the current dir to becurrent.Dirs[dirName]
- “..” literal: we change
There are different kinds of file nodes, they are used to take the token literal and parse it into a meaningful structure. For example, the cd node looks like this
|
|
At the end of the function we backtrack to our root directory and add each directory size in that path to its parent, this is because our output does not contain ..
commands back to the top.
Now that we have got our file system creation process all dialed in we can start implementing the first part solution
Part 1
We are tasked to find all directories with size <= 100,000 To do that we need to have a way to walk over each directory in our file system structure. Let’s add methods to support that capability
|
|
Both FileSystem and FileSystemNode get a
Walk
method
We pass in a function that will be called on each node in our file system. Using the above method our solution is now as simple as
|
|
Part 2
In part 2 we are tasked with increasing the amount of free space to at least 3,000,000 we also know that the total memory on our device is 7,000,000 We need to find the smallest directory that we can delete that will increase the amount of free memory >= 3,000,000
For example (directly from the question)
_In our example, you have the following options:
Delete directory e, which would increase unused space by 584. Delete directory a, which would increase unused space by 94853. Delete directory d, which would increase unused space by 24933642. Delete directory /, which would increase unused space by 48381165. Directories e and a are both too small; deleting them would not free up enough space. However, directories d and / are both big enough! Between these, choose the smallest: d, increasing unused space by 24933642._
The logic to solve part 2 is also fairly straightforward but we do need to expose the size of our fileSystem
first
|
|
Part 2 solution
|
|
For each directory, we check if by deleting it we have enough free memory unusedSpace+t.Size > THRESHOLD
if it does we check to see if it’s less than our current smallest directory.
Pheww…That’s it for day 7! I know this approach is a bit too structured for an AoC problem and initially, I solved it without building the entire structure, tokens etc… For the sake of this blog post, I thought I’ll make things a bit more structured and interesting
You can find the complete code here Thanks for reading!
This post is number 8 of a 13 posts series > Learning Go.