Using too much memory

defmodule Day5 do
  def read_file(path) do
    {:ok, contents} = File.read(path)
    String.split(contents, "\n\n", trim: true)
  end

  def create_almanac(sections) do
    almanac_object = %{
      seed_numbers: nil,
      seed_ranges: [],
      to_soil: nil,
      to_fertilizer: nil,
      to_water: nil,
      to_light: nil,
      to_temperature: nil,
      to_humidity: nil,
      to_location: nil,
    }

    almanac = Enum.with_index(sections)
    |> Enum.reduce(almanac_object, fn section_tuple, updated_almanac ->
      {section, index} = section_tuple

      if index == 0 do
        seed_numbers = Regex.scan(~r/[\d]+/, section)
        |> Enum.map(fn seed_number_list ->
          String.to_integer(Enum.at(seed_number_list, 0))
        end)

        Map.replace(updated_almanac, :seed_numbers, seed_numbers)
      else
        section_name = Enum.at(Enum.at(Regex.scan(~r/to-[\w]+/, section), 0), 0)
        section_name = section_name
        |> String.replace("-", "_")
        section_name = String.to_atom(section_name)

        section_numbers =
          Enum.drop(String.split(section, "\n", trim: true), 1)

        maps =
          section_numbers
          |> Enum.map(fn numbers ->
            numbers =
              String.split(numbers)
              |> Enum.map(&String.to_integer/1)

            {Enum.at(numbers, 0), Enum.at(numbers, 1), Enum.at(numbers, 2)}
          end)

        Map.replace(updated_almanac, section_name, maps)
      end
    end)

    extract_seed_range_info(almanac)
  end

  def get_destination_number(source_number, maps) do
    maps
    |> Enum.reduce_while(source_number, fn map, acc ->
      {dest_range_start, source_range_start, range_length} = map

      if acc >= source_range_start &&
        acc <= source_range_start + range_length do
        {:halt, dest_range_start + acc - source_range_start}
      else
        {:cont, acc}
      end
    end)
  end

  def get_destination(almanac, dest_category, seeds) do
    categories = ["soil", "fertilizer", "water", "light", "temperature", "humidity", "location"]

    Enum.map(seeds, fn seed ->
      Enum.reduce_while(categories, seed, fn category, dest_number ->
        current_map = Map.get(almanac, String.to_atom("to_#{category}"))
        dest_number = get_destination_number(dest_number, current_map)

        if category == dest_category do
          {:halt, dest_number}
        else
          {:cont, dest_number}
        end
      end)
    end)
  end

  def extract_seed_range_info(almanac) do
    Enum.chunk_every(almanac.seed_numbers, 2)
    |> Enum.reduce(almanac, fn range_pair, updated_almanac ->
      Map.put(updated_almanac, :seed_ranges, [{Enum.at(range_pair, 0), Enum.at(range_pair, 1)} | updated_almanac.seed_ranges])
    end)
  end

  def solve_part_2(path) do
    almanac =
      read_file(path)
      |> create_almanac()

    locations = List.flatten(almanac.seed_ranges
    |> Enum.reduce([], fn range_tuple, locations ->
      {range_start, range_length} = range_tuple
      [get_destination(almanac, "location", range_start..(range_length + range_start)) | locations]
    end))

    Enum.min(locations)
  end
end