defmodule Day6 do def part1 do File.read!("lib/day6/input.txt") |> parse_orbits() |> total_orbits() end def part2 do # orbits = parse_orbits("COM)B\nB)C\nC)D\nD)E\nE)F\nB)G\nG)H\nD)I\nE)J\nJ)K\nK)L\nK)YOU\nI)SAN") orbits = File.read!("lib/day6/input.txt") |> parse_orbits() you_path = path_to_root(orbits, "YOU") |> Enum.reverse() san_path = path_to_root(orbits, "SAN") |> Enum.reverse() {rem1, rem2} = remaining_after_lowest_common_element(you_path, san_path) length(rem1) - 1 + (length(rem2) - 1) end def parse_orbits(str) do str |> String.split("\n") |> Enum.map(fn line -> String.split(line, ")") end) |> Enum.reduce(%{}, fn [orbitted, object], orbits -> Map.put(orbits, object, orbitted) end) end def total_orbits(orbits) do orbits |> Map.keys() |> Enum.reduce(0, fn object, acc -> acc + orbit_count(orbits, object) end) end def orbit_count(orbits, object) do case Map.get(orbits, object) do nil -> 0 orbitted -> 1 + orbit_count(orbits, orbitted) end end def path_to_root(graph, start) do case Map.get(graph, start) do nil -> [] parent -> [parent | path_to_root(graph, parent)] end end def remaining_after_lowest_common_element([_, one | _] = list1, [_, two | _] = list2) when one != two do {list1, list2} end def remaining_after_lowest_common_element([_ | rest1], [_ | rest2]) do remaining_after_lowest_common_element(rest1, rest2) end end