Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@Zyclotrop-j
Created December 7, 2022 09:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Zyclotrop-j/7f83d2310308b46388f230839553e719 to your computer and use it in GitHub Desktop.
Save Zyclotrop-j/7f83d2310308b46388f230839553e719 to your computer and use it in GitHub Desktop.
advent of code 2022, day 7
defmodule Day7 do
@maxsize 100000
@total 70000000
@needspace 30000000
@moduledoc """
Documentation for `Day7`.
"""
@doc """
Hello world.
## Examples
iex> Day7.hello()
{1423358, 545729}
"""
def hello do
{:ok, data} = File.read("./lib/input")
list = String.split(data, "\n", trim: true)
{_, map} = list |> Enum.reduce({[""], %{ "" => 0 }}, &processline/2)
result1 = getsumwherevaluesless(map)
result2 = getminfolderneededspace(map)
{result1, result2}
end
@doc """
task 1
filter as per criteria, then sum the result values
"""
def getsumwherevaluesless(map), do: map |> Map.filter(fn {_key, val} -> @maxsize > val end) |> Map.values() |> Enum.sum()
@doc """
task 2
filter as per criteria, then find the min-value
"""
def getminfolderneededspace(map), do: map |> Map.filter(fn {_key, val} -> val >= (@needspace - (@total - map[""])) end) |> Map.values() |> Enum.min()
defp processline("$ " <> command, acc), do: processcommand(command, acc)
defp processline(statement, acc), do: statement |> String.split() |> processstatement(acc)
def processcommand("ls", {currentdir, map}), do: {currentdir, map}
@doc """
navigate through the folder structure
"""
def processcommand("cd ..", {dir, map}), do: {Enum.drop(dir, -1), map}
def processcommand("cd /", {_, map}), do: {[""], map}
def processcommand("cd " <> dir, {currentdir, map}), do: {currentdir ++ [dir], map}
@doc """
for 'dir instruction', for each directory we're scanning the size of, init it to 0
for all other instructions, for each file we discover update the current and all anchestor directory sizes
"""
def processstatement(["dir", dir], {currentdir, map}) do
updatedmap = Map.put_new(map, Enum.join(currentdir, "/") <> "/" <> dir, 0)
{ currentdir, updatedmap }
end
def processstatement([size, _], {currentdir, map}) do
updatedmap = Enum.scan(currentdir, &(&2 <> "/" <> &1)) |> Enum.reduce(map, String.to_integer(size) |> updatemapentry())
{ currentdir, updatedmap }
end
@doc """
helper function to update the value in map at key 'dir' with (old value + intsize)
"""
def updatemapentry(intsize) do
fn dir, acc ->
Map.get_and_update!(acc, dir, &({ &1, &1 + intsize })) |> elem(1)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment