defmodule One do
def run() do
IO.inspect {
p1(Input.read("day-01-input-01.txt")),
p2(Input.read("day-01-input-02.txt"))
}
end
def p1(module_masses) do
module_masses
|> Stream.map(&compute_fuel/1)
|> Enum.sum
end
def p2(module_masses) do
module_masses
|> Stream.map(fn fuel -> compute_fuel(fuel, 0) end)
|> Enum.sum
end
defp compute_fuel(mass), do: max(div(mass,3) - 2, 0)
defp compute_fuel(fuel, total) do
case compute_fuel(fuel) do
0 -> total
fuel -> compute_fuel(fuel, total + fuel)
end
end
end
defmodule Input do
def read(file) do
file
|> File.stream!
|> Stream.map(&String.trim/1)
|> Stream.map(&String.to_integer/1)
end
end
One.run()
defmodule Two do
def run() do
IO.inspect {
p1(Input.read("day-02-input-01.txt")),
p2(Input.read("day-02-input-02.txt"))
}
end
def p1(program) do
run(program, {12, 2})
end
def p2(program) do
{noun, verb} = for noun <- 0..99, verb <- 0..99 do {noun, verb} end
|> Enum.find(&run(program, &1) == 19690720)
100 * noun + verb
end
defp run(program, {noun, verb}) do
program
|> arrange(noun, verb)
|> execute
|> Map.fetch!(0)
end
defp arrange(program, noun, verb) do
program
|> Map.put(1, noun)
|> Map.put(2, verb)
end
defp execute(program, address \\ 0) do
case Map.fetch!(program, address) do
1 -> program |> compute(address, &Kernel.+/2) |> execute(address + 4)
2 -> program |> compute(address, &Kernel.*/2) |> execute(address + 4)
99 -> program # HALT!
end
end
defp compute(program, address, operation) do
Map.put(program, Map.fetch!(program, address+3),
operation.(
Map.fetch!(program, Map.fetch!(program, address+1)),
Map.fetch!(program, Map.fetch!(program, address+2))
)
)
end
end
defmodule Input do
def read(file) do
file
|> File.read!
|> String.trim
|> String.split(",")
|> Stream.with_index
|> Stream.map(fn {v,i} -> {i, String.to_integer(v)} end)
|> Map.new
end
end
Two.run()
defmodule Three do
def run() do
IO.inspect {
p1(Input.read("day-03-input-01.txt")),
p2(Input.read("day-03-input-02.txt"))
}
end
def p1({path_1, path_2}) do
run(path_1) ++ run(path_2)
|> Enum.group_by(&(&1))
|> Enum.filter(fn {_, [_,_|_]} -> true; _ -> false end)
|> Enum.map(fn {x, _} -> x end)
|> Enum.map(fn {x, y} -> abs(x) + abs(y) end)
|> Enum.min
end
def p2({path_1, path_2}) do
# FUUUUUUUUUUUUUUUUUUUUU!
end
defp run(path) do
path
|> String.split(",")
|> Enum.reduce([], fn x, acc -> acc ++ move(x, Enum.at(acc, -1)) end)
|> Enum.into(MapSet.new)
|> Enum.to_list
end
defp move(<<operation :: utf8>> <> steps = instruction, nil), do: move(instruction, {0,0})
defp move(<<operation :: utf8>> <> steps = instruction, {x,y}) do
steps = String.to_integer(steps)
case <<operation::utf8>> do
"U" -> for x <- x..x, y <- y+1..(y+steps) do {x, y} end
"D" -> for x <- x..x, y <- y-1..(y-steps) do {x, y} end
"R" -> for x <- x+1..(x+steps), y <- y..y do {x, y} end
"L" -> for x <- x-1..(x-steps), y <- y..y do {x, y} end
end
end
end
defmodule Input do
def read(file) do
paths = file
|> File.stream!
|> Stream.map(&String.trim/1)
|> Enum.to_list
{Enum.fetch!(paths, 0), Enum.fetch!(paths, 1)}
end
end
Three.run()
defmodule Four do
def run() do
IO.inspect {
p1(147981..691423),
p2(147981..691423)
}
end
def p1(range) do
range
|> Stream.map(&Integer.digits/1)
|> Stream.filter(&contains_double?/1)
|> Stream.filter(&always_increasing?/1)
|> Enum.count
end
def p2(range) do
range
|> Stream.map(&Integer.digits/1)
|> Stream.filter(&contains_strict_double?/1)
|> Stream.filter(&always_increasing?/1)
|> Enum.to_list
|> Enum.count
end
defp contains_double?([x, x, _, _, _, _]), do: true
defp contains_double?([_, x, x, _, _, _]), do: true
defp contains_double?([_, _, x, x, _, _]), do: true
defp contains_double?([_, _, _, x, x, _]), do: true
defp contains_double?([_, _, _, _, x, x]), do: true
defp contains_double?(_), do: false
defp contains_strict_double?([x, x, y, _, _, _]) when x != y, do: true
defp contains_strict_double?([z, x, x, y, _, _]) when x != y and x != z, do: true
defp contains_strict_double?([_, z, x, x, y, _]) when x != y and x != z, do: true
defp contains_strict_double?([_, _, z, x, x, y]) when x != y and x != z, do: true
defp contains_strict_double?([_, _, _, y, x, x]) when x != y, do: true
defp contains_strict_double?(_), do: false
defp always_increasing?([a,b,c,d,e,f]) when
b >= a and c >= b and d >= c and e >= d and f >= e, do: true
defp always_increasing?(_), do: false
end
Four.run()