defmodule Day09 do def part1(data) do values = data |> String.split("\n", trim: true) |> hd() |> String.codepoints() |> Enum.map(& String.to_integer/1) files = values |> Enum.take_every(2) |> Enum.with_index() |> Enum.flat_map(fn {v, i} -> Stream.cycle([i]) |> Enum.take(v) end) revfiles = files |> Enum.reverse() v2 = values |> Enum.with_index() |> Enum.flat_map(fn {v, i} -> Stream.cycle([i]) |> Enum.take(v) end) |> Enum.with_index() c1 = v2 |> Enum.filter(fn {i, _} -> rem(i, 2) == 0 end) |> Enum.zip(files) c2 = v2 |> Enum.filter(fn {i, _} -> rem(i, 2) == 1 end) |> Enum.zip(revfiles) (c1 ++ c2) |> Enum.sort_by(fn {{_, i}, _} -> i end) |> Enum.take(Enum.count(files)) |> Enum.map(fn {{_, i}, v} -> i*v end) |> Enum.sum() end def part2(data) do values = data |> String.split("\n", trim: true) |> hd() |> String.codepoints() |> Enum.map(& String.to_integer/1) |> Enum.scan({0, 0}, fn v, {o, i} -> {v, o+i} end) spaces = values |> tl() |> Enum.take_every(2) values |> Enum.take_every(2) |> Enum.with_index() |> Enum.reverse() |> locations(spaces) |> Enum.map(fn {a, b, i} -> i*Enum.sum(b..b+a-1) end) |> Enum.sum() end defp locations(acc \\ [], revfiles, spaces) defp locations(acc, [{{a, b}, i} | t], spaces) do spaces = Enum.filter(spaces, fn {_, d} -> d < b end) s = spaces |> Enum.filter(fn {c, _} -> c >= a end) |> Enum.min_by(fn {_, d} -> d end, &<=/2, fn -> nil end) if s == nil do locations([{a, b, i} | acc], t, spaces) else spaces = List.delete(spaces, s) {c, d} = s spaces = if c == a do spaces else [{c-a, d+a} | spaces] end locations([{a, d, i} | acc], t, spaces) end end defp locations(acc, [], _) do acc end end data = IO.read(:stdio, :eof) {time1 , ans1} = :timer.tc(fn -> Day09.part1(data) end) IO.puts("Time : #{time1 / 1000000}") IO.puts("Answer: #{ans1}") {time2 , ans2} = :timer.tc(fn -> Day09.part2(data) end) IO.puts("Time : #{time2 / 1000000}") IO.puts("Answer: #{ans2}")