Powered by AppSignal & Oban Pro

AoC 2015 Day 9

2015/day9.livemd

AoC 2015 Day 9

Mix.install([:kino, :combination])

defmodule Utils do
  def split(line, sep \\ "") do
    String.split(line, sep, trim: true)
  end

  def split_all_lines(text, sep \\ "") do
    text
    |> String.split("\n", trim: true)
    |> Enum.map(&split(&1, sep))
  end

  def to_numbers(number) when is_binary(number) do
    String.to_integer(number)
  end

  def to_numbers(numbers) when is_list(numbers) do
    Enum.map(numbers, &to_numbers/1)
  end

  def to_matrix(text, sep \\ "") do
    text
    |> split_all_lines(sep)
    |> then(fn data ->
      for {row, r} <- Enum.with_index(data), {col, c} <- Enum.with_index(row) do
        {{r, c}, col}
      end
    end)
    |> Map.new()
  end
end

Setup

import Utils
input = Kino.Input.textarea("Input:")
text = Kino.Input.read(input)
distances =
  text
  |> split_all_lines(" ")
  |> Enum.flat_map(fn [a, _, b, _, v] ->
    [{{a, b}, String.to_integer(v)}, {{b, a}, String.to_integer(v)}]
  end)
  |> Map.new()

cities = distances |> Map.keys() |> Enum.map(&elem(&1, 1)) |> Enum.uniq()
trips =
  for p <- Combination.permutate(cities) do
    p
    |> Enum.chunk_every(2, 1, :discard)
    |> Enum.reduce(0, fn [a, b], trip ->
      trip + distances[{a, b}]
    end)
  end

P1

Enum.min(trips)

P2

Enum.max(trips)