Skip to content

Commit b126302

Browse files
committed
Add unoptimized, messy solutions for days 7-12 2022
1 parent eff887e commit b126302

16 files changed

+421
-221
lines changed
+70-103
Original file line numberDiff line numberDiff line change
@@ -1,130 +1,97 @@
11
defmodule AdventOfCode.Day07 do
2-
defmodule Folder do
3-
@enforce_keys [:name]
4-
defstruct [:name, files: %{}, folders: %{}, type: :dir]
5-
end
6-
7-
defmodule File do
8-
@enforce_keys [:name, :size]
9-
defstruct [:name, :size, type: :file]
10-
end
11-
12-
@doc"""
13-
defimpl Inspect, for: Folder do
14-
def inspect(folder, _opts) do
15-
folderText = "" # folder.folders.keys()
16-
fileText = "|- a file\n"
17-
"-- {folder.name}\n" <> folderText <> fileText
18-
end
19-
end
20-
21-
defimpl Inspect, for: File do
22-
def inspect(file, _opts) do
23-
"-- {file.size} {file.name}\n"
24-
end
25-
end
26-
"""
27-
defprotocol FileTree do
28-
def size(value)
29-
end
30-
31-
defimpl FileTree, for: Folder do
32-
def size(dir), do:
33-
dir.content
34-
|> Enum.map(&FileTree.size/1)
35-
|> Enum.sum()
36-
end
37-
38-
defimpl FileTree, for: File do
39-
def size(file), do: file.size
40-
end
41-
422
@spec parseCommand(String.t()) :: list()
433
def parseCommand(rawStr) do
444
cond do
45-
String.starts_with?(rawStr, "$ ls") -> [:ls]
46-
String.starts_with?(rawStr, "$ cd") -> [:cd, String.trim_leading(rawStr, "$ cd ")]
47-
String.starts_with?(rawStr, "dir") -> [:dir, String.trim_leading(rawStr, "dir ")]
5+
String.starts_with?(rawStr, "$ ls") ->
6+
[:ls]
7+
8+
String.starts_with?(rawStr, "$ cd") ->
9+
[:cd, String.trim_leading(rawStr, "$ cd ")]
10+
11+
String.starts_with?(rawStr, "dir") ->
12+
[:dir, String.trim_leading(rawStr, "dir ")]
13+
4814
String.match?(rawStr, ~r/^\d+ .+$/) ->
4915
[size, name] = String.split(rawStr, " ")
5016
[:file, String.to_integer(size), name]
51-
true -> [:unknown, rawStr]
17+
18+
true ->
19+
[:unknown, rawStr]
5220
end
5321
end
5422

55-
@spec executeCommand(list(), list()) :: %Folder{}
56-
def executeCommand([:cd, "/"], [_path, rootNode]), do: [["/"], rootNode]
57-
def executeCommand([:cd, ".."], [["/"], rootNode]), do: [["/"], rootNode]
58-
def executeCommand([:cd, ".."], [path, rootNode]), do: [Enum.drop(path, -1), rootNode]
59-
def executeCommand([:cd, folder], [path, rootNode]) do
60-
# nextNode = Enum.find(currentNode.content, fn x -> x.type == :dir && x.name == folder end)
61-
[ path ++ [folder], rootNode]
62-
end
63-
def executeCommand([:ls], [path, rootNode]), do: [path, rootNode]
64-
def executeCommand([:file, size, name], [path, rootNode])
65-
do
66-
newFile = %File{name: name, size: size}
67-
newTree = addItemToContent(path, rootNode, newFile)
68-
[path, newTree]
69-
end
70-
def executeCommand([:dir, name], [path, rootNode])
71-
do
72-
newDir = %Folder{name: name}
73-
newTree = addItemToContent(path, rootNode, newDir)
74-
[path, newTree]
75-
end
23+
def executeCommand([:cd, "/"], [_path, rootNode, folders]),
24+
do: [["/"], rootNode, folders]
7625

77-
@spec addItemToContent(list(), %Folder{}, %Folder{} | %File{}) :: %Folder{}
78-
def addItemToContent(path, root, item) do
79-
access_path = transformToAccessPath(path)
80-
dir = if access_path == [], do: root, else: get_in(root, access_path)
81-
IO.inspect(dir)
82-
if duplicate?(dir, item)
83-
do
84-
root
85-
else
86-
# get_and_update_in(root, [Access.key(:files), Access.key(:abaa), Access.key(:size)], &{&1, &1 + 1000})
87-
#get_and_update_in(root, path, fn currentFolder -> %{currentFolder | content: Map.update(dir.content, item.name, item)} end)
88-
if access_path != []
89-
do
90-
update_in(root, access_path, &(Map.put(&1, item.name, item)))
91-
else
92-
key = if item.type == :dir, do: :folders, else: :files
93-
# update(root, )
94-
end
95-
end
96-
end
26+
def executeCommand([:cd, ".."], [["/"], rootNode, folders]),
27+
do: [["/"], rootNode, folders]
9728

98-
def transformToAccessPath(path) do
99-
path |> Enum.map(&Access.key/1) |> Enum.intersperse(Access.key(:folders)) |> Enum.drop(1)
100-
end
29+
def executeCommand([:cd, ".."], [path, rootNode, folders]),
30+
do: [Enum.drop(path, -1), rootNode, folders]
10131

102-
@spec duplicate?(%Folder{}, %Folder{} | %File{}) :: boolean()
103-
def duplicate?(folder, item) do
104-
key = if item.type == :dir, do: :folders, else: :files
105-
get_in(folder, [Access.key(key)]) |> Map.keys() |> Enum.member?(item.name)
106-
end
32+
def executeCommand([:cd, folder], [path, rootNode, folders]),
33+
do: [path ++ [folder], rootNode, MapSet.put(folders, path ++ [folder])]
34+
35+
def executeCommand([:ls], [path, rootNode, folders]),
36+
do: [path, rootNode, folders]
37+
38+
def executeCommand([:file, size, name], [path, rootNode, folders]),
39+
do: [path, update_in(rootNode, path, &Map.put(&1, name, size)), folders]
40+
41+
def executeCommand([:dir, name], [path, rootNode, folders]),
42+
do: [path, update_in(rootNode, path, &Map.put(&1, name, %{})), folders]
10743

10844
def part1(args) do
109-
root = %Folder{name: "/"}
45+
root = %{"/" => %{}}
11046

111-
tree = args
112-
|> String.trim()
113-
|> String.split("\n")
114-
|> Enum.map(&parseCommand/1)
115-
|> Enum.reduce(["/", root], fn x, acc -> executeCommand(x, acc) end)
47+
[_, tree, visitedPaths] =
48+
args
49+
|> String.trim()
50+
|> String.split("\n")
51+
|> Enum.map(&parseCommand/1)
52+
|> Enum.reduce(["/", root, MapSet.new([["/"]])], fn x, acc -> executeCommand(x, acc) end)
11653

117-
IO.inspect(tree)
54+
visitedPaths
55+
|> Enum.map(&(get_in(tree, &1) |> getSize()))
56+
|> Enum.filter(&(&1 <= 100_000))
57+
|> Enum.sum()
11858
end
11959

120-
def part2(_args) do
60+
def part2(args) do
61+
root = %{"/" => %{}}
62+
63+
[_, tree, visitedPaths] =
64+
args
65+
|> String.trim()
66+
|> String.split("\n")
67+
|> Enum.map(&parseCommand/1)
68+
|> Enum.reduce(["/", root, MapSet.new([["/"]])], fn x, acc -> executeCommand(x, acc) end)
69+
70+
otherDirectories = MapSet.delete(visitedPaths, [["/"]])
71+
72+
space_available = 70_000_000 - getSize(get_in(tree, ["/"]))
73+
additional_space_needed = 30_000_000 - space_available
74+
75+
directorySizes =
76+
otherDirectories
77+
|> Enum.map(&(get_in(tree, &1) |> getSize()))
78+
|> Enum.sort()
79+
|> Enum.filter(&(&1 >= additional_space_needed))
80+
|> hd
12181
end
12282

12383
@spec getSize(list) :: number
12484
@doc """
12585
Returns the size of a filetree in form of a Map.
12686
"""
127-
def getSize(tree) do
128-
tree |> Map.to_list() |> List.flatten() |> Enum.map(&getSize/1) |> Enum.sum()
87+
def getSize(element) when is_integer(element), do: element
88+
89+
def getSize(tuple) when is_tuple(tuple) and tuple_size(tuple) == 2 do
90+
{_, map} = tuple
91+
getSize(map)
92+
end
93+
94+
def getSize(map) when is_map(map) do
95+
map |> Map.to_list() |> List.flatten() |> Enum.map(&getSize/1) |> Enum.sum()
12996
end
13097
end
+58-53
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
defmodule AdventOfCode.Day08 do
2-
def part1(_args) do
2+
import AdventOfCode.Util
3+
4+
def part1(args) do
5+
args |> inputToNumGrid() |> countVisibilityOnGrid()
36
end
47

5-
def part2(_args) do
8+
def part2(args) do
9+
args |> inputToNumGrid() |> getMaxScenicScoreOnGrid()
610
end
711

812
def inputToNumGrid(input) do
@@ -15,69 +19,70 @@ defmodule AdventOfCode.Day08 do
1519
)
1620
end
1721

18-
def setAllToUnknown(numgrid) do
19-
numgrid |> Enum.map(&Enum.map(&1, fn x -> [x, :unknown] end))
22+
@spec getScenicScore([list], integer, integer) :: number
23+
def getScenicScore(grid, x, y) do
24+
height = grid |> Enum.at(y) |> Enum.at(x)
25+
allWest = getAllWest(grid, x, y) |> countVisibleTrees(height)
26+
allEast = getAllEast(grid, x, y) |> countVisibleTrees(height)
27+
allSouth = getAllSouth(grid, x, y) |> countVisibleTrees(height)
28+
allNorth = getAllNorth(grid, x, y) |> countVisibleTrees(height)
29+
30+
Enum.product([allWest, allEast, allSouth, allNorth])
2031
end
2132

22-
def initializeBoarders(tagGrid) do
23-
tagGrid
24-
|> List.update_at(-1, &Enum.map(&1, fn [x, _] -> [x, :visible] end))
25-
|> List.update_at(0, &Enum.map(&1, fn [x, _] -> [x, :visible] end))
26-
|> Enum.map(fn [[x, _] | rest] -> [[x, :visible] | rest] end)
27-
|> Enum.map(&List.update_at(&1, -1, fn [x, _] -> [x, :visible] end))
33+
def countVisibleTrees(list, height) do
34+
cansee = Enum.take_while(list, &(&1 < height)) |> length()
35+
if cansee < length(list), do: cansee + 1, else: cansee
2836
end
2937

30-
def updateStatus(_, _, _, :visible, _), do: :visible
31-
def updateStatus(_, _, _, :invisible, _), do: :invisible
38+
def getMaxScenicScoreOnGrid(grid) do
39+
yMax = length(grid) - 1
40+
xMax = length(Enum.at(grid, 0)) - 1
41+
42+
0..yMax
43+
|> Enum.map(fn y -> Enum.map(0..xMax, &[&1, y]) end)
44+
|> Enum.map(&Enum.map(&1, fn [x, y] -> AdventOfCode.Day08.getScenicScore(grid, x, y) end))
45+
|> List.flatten()
46+
|> Enum.max()
47+
end
3248

33-
def updateStatus(rix, cix, height, :unknown, grid) do
34-
# [[hup, sup], [hdown, sdown], [hleft, sleft], [hright, sright]] = getEnvironment(grid, rix, cix)
35-
getEnvironment(grid, rix, cix) |> Enum.any?()
49+
def countVisibilityOnGrid(grid) do
50+
yMax = length(grid) - 1
51+
xMax = length(Enum.at(grid, 0)) - 1
3652

37-
# cases for: all blocking -> invis
38-
# any is smaller and vis? -> vis
39-
# else -> unknown
53+
0..yMax
54+
|> Enum.map(fn y -> Enum.map(0..xMax, &[y, &1]) end)
55+
|> Enum.map(&Enum.map(&1, fn [x, y] -> AdventOfCode.Day08.isVisible?(grid, x, y) end))
56+
|> List.flatten()
57+
|> Enum.count(&(&1 == true))
4058
end
4159

42-
def updateStatus(_, _, _, _, _), do: :error
43-
44-
def updateGrid(tagGrid) do
45-
newStatus = fn _, _, _, _ -> :test end
46-
47-
workList =
48-
tagGrid
49-
|> Enum.with_index()
50-
|> Enum.map(fn {row, rix} ->
51-
Enum.with_index(row, fn element, cix -> [rix, cix, element] end)
52-
end)
53-
|> List.flatten()
54-
|> Enum.chunk_every(4)
55-
56-
workList
57-
|> Enum.reduce(tagGrid, fn [rix, cix, height, status], accgrid ->
58-
List.update_at(
59-
accgrid,
60-
rix,
61-
&List.update_at(&1, cix, fn [x, status] ->
62-
[x, updateStatus(rix, cix, height, status, accgrid)]
63-
end)
64-
)
65-
end)
60+
def isVisible?(grid, x, y) do
61+
height = grid |> Enum.at(y) |> Enum.at(x)
62+
allWest = getAllWest(grid, x, y) |> Enum.all?(&(&1 < height))
63+
allEast = getAllEast(grid, x, y) |> Enum.all?(&(&1 < height))
64+
allSouth = getAllSouth(grid, x, y) |> Enum.all?(&(&1 < height))
65+
allNorth = getAllNorth(grid, x, y) |> Enum.all?(&(&1 < height))
66+
67+
Enum.any?([allWest, allEast, allSouth, allNorth])
6668
end
6769

68-
def getVisibleTrees(grid), do: grid |> List.flatten() |> Enum.count(&(&1 == :visible))
70+
@doc """
71+
Zero based access. Map origin is upper left corner at 0,0
72+
"""
73+
def getAllWest(grid, x, y) do
74+
grid |> Enum.fetch!(y) |> Enum.take(x) |> Enum.reverse()
75+
end
6976

70-
def updateStatusByCoordinate(grid, rix, cix, newStatus),
71-
do: grid |> List.update_at(rix, &List.update_at(&1, cix, fn [x, _] -> [x, newStatus] end))
77+
def getAllEast(grid, x, y) do
78+
grid |> Enum.fetch!(y) |> Enum.drop(x + 1)
79+
end
7280

73-
def getElement(grid, rix, cix),
74-
do: grid |> Enum.fetch(rix) |> then(fn {_, row} -> Enum.fetch!(row, cix) end)
81+
def getAllSouth(grid, x, y) do
82+
grid |> transpose() |> Enum.fetch!(x) |> Enum.drop(y + 1)
83+
end
7584

76-
def(getEnvironment(grid, rix, cix)) do
77-
up = getElement(grid, rix - 1, cix)
78-
down = getElement(grid, rix + 1, cix)
79-
left = getElement(grid, rix, cix - 1)
80-
right = getElement(grid, rix, cix + 1)
81-
[up, down, left, right]
85+
def getAllNorth(grid, x, y) do
86+
grid |> transpose() |> Enum.fetch!(x) |> Enum.take(y) |> Enum.reverse()
8287
end
8388
end

2022/Elixir/lib/advent_of_code/day_09.ex

+3-41
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
11
defmodule AdventOfCode.Day09 do
2-
@moduledoc """
3-
This module is using named directions in a 2D Space.
4-
The center X be [0,0]. eg. NN is [0,2].
5-
| | | | | |
6-
|:----:|:---:|:---:|:---:|:----:|
7-
| NWNW | NNW | NN | NNE | NENE |
8-
| NWW | NW | N | NE | NEE |
9-
| WW | W | X | E | EE |
10-
| SWW | SW | S | SE | SEE |
11-
| SWSW | SSW | SS | SSE | SESE |
12-
"""
2+
import AdventOfCode.Util
3+
134
def part1(args) do
145
args
156
|> parseInput()
@@ -65,7 +56,7 @@ defmodule AdventOfCode.Day09 do
6556
&(String.split(&1, " ")
6657
|> then(fn [dir, num] -> String.duplicate(dir, String.to_integer(num)) end))
6758
)
68-
|> Enum.reduce("", &(&2 <> &1))
59+
|> Enum.join()
6960
end
7061

7162
def updateHead(h, "R"), do: getE(h)
@@ -103,33 +94,4 @@ defmodule AdventOfCode.Day09 do
10394
true -> raise "unknown skip"
10495
end
10596
end
106-
107-
def getN([x, y]), do: [x, y + 1]
108-
def getNN([x, y]), do: [x, y + 2]
109-
def getS([x, y]), do: [x, y - 1]
110-
def getSS([x, y]), do: [x, y - 2]
111-
def getW([x, y]), do: [x - 1, y]
112-
def getWW([x, y]), do: [x - 2, y]
113-
def getE([x, y]), do: [x + 1, y]
114-
def getEE([x, y]), do: [x + 2, y]
115-
116-
def getSE([x, y]), do: [x + 1, y - 1]
117-
def getSSE([x, y]), do: [x + 1, y - 2]
118-
def getSEE([x, y]), do: [x + 2, y - 1]
119-
def getSESE([x, y]), do: [x + 2, y - 2]
120-
121-
def getNE([x, y]), do: [x + 1, y + 1]
122-
def getNNE([x, y]), do: [x + 1, y + 2]
123-
def getNEE([x, y]), do: [x + 2, y + 1]
124-
def getNENE([x, y]), do: [x + 2, y + 2]
125-
126-
def getSW([x, y]), do: [x - 1, y - 1]
127-
def getSSW([x, y]), do: [x - 1, y - 2]
128-
def getSWW([x, y]), do: [x - 2, y - 1]
129-
def getSWSW([x, y]), do: [x - 2, y - 2]
130-
131-
def getNW([x, y]), do: [x - 1, y + 1]
132-
def getNNW([x, y]), do: [x - 1, y + 2]
133-
def getNWW([x, y]), do: [x - 2, y + 1]
134-
def getNWNW([x, y]), do: [x - 2, y + 2]
13597
end

0 commit comments

Comments
 (0)