호두나무 공방/Advent of Code

Advent of Code 2022 Day 3 in Elixir - Rucksack Reorganization 풀이

2022. 12. 10. 17:00

문제 보기

가방에 들어갈 여러 종류의 물건이 있고, 가방이 크게 두 칸으로 나뉘어 있을 때, 한 종류의 물건은 한쪽 칸에만 들어가게 하고 싶단다. 첫 번째 문제는 양쪽 칸에 딱 하나씩 들어간 같은 물건을 찾는 문제, 두 번째 문제는 여러 가방 사이에서 공통적으로 등장하는 물건을 찾는 문제였다. 엘릭서의 MapSet이 이럴 때 정말 유용하다.

defmodule Omicron.Day3 do
  @dir "data/day3/"

  def q1(file_name \\ "q.txt") do
    File.read!(@dir <> file_name)
    |> String.split("\n")
    |> Enum.map(fn backpack ->
      part_size = div(String.length(backpack), 2)

      [set1, set2] =
        String.split_at(backpack, part_size)
        |> Tuple.to_list()
        |> Enum.map(fn part ->
          part |> String.graphemes() |> MapSet.new()
        end)

      MapSet.intersection(set1, set2)
      |> single_elem_mapset_to_char()
      |> priority()
    end)
    |> Enum.sum()
  end

  def q2(file_name \\ "q.txt") do
    File.read!(@dir <> file_name)
    |> String.split("\n")
    |> Enum.chunk_every(3)
    |> Enum.map(fn group ->
      group
      |> Enum.map(fn backpack ->
        backpack |> String.graphemes() |> MapSet.new()
      end)
      |> Enum.reduce(&MapSet.intersection/2)
      |> single_elem_mapset_to_char()
      |> priority()
    end)
    |> Enum.sum()
  end

  defp single_elem_mapset_to_char(mapset) do
    mapset
    |> MapSet.to_list()
    |> Enum.join("")
    |> String.to_charlist()
    |> hd()
  end

  defp priority(char) when char in ?A..?Z do
    char - ?A + 27
  end

  defp priority(char) when char in ?a..?z do
    char - ?a + 1
  end
end