Skip to content

Instantly share code, notes, and snippets.

@ordepdev
Last active December 5, 2019 10:21
Show Gist options
  • Save ordepdev/a5647eceb24720ea8d92922e6f81aa09 to your computer and use it in GitHub Desktop.
Save ordepdev/a5647eceb24720ea8d92922e6f81aa09 to your computer and use it in GitHub Desktop.
AOC 2019
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()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment