Skip to content

Instantly share code, notes, and snippets.

@chrismcg
Created December 6, 2018 15:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrismcg/633a69f51f6c9dc044a7e000ec3dafdd to your computer and use it in GitHub Desktop.
Save chrismcg/633a69f51f6c9dc044a7e000ec3dafdd to your computer and use it in GitHub Desktop.
AoC 2018 day 5 in Elixir
defmodule Day5 do
@moduledoc """
Day 5 Elixir solutions for Advent of Code 2018
"""
@doc """
Removes all reacting units from the input and returns the final length
Algorithm from a Haskell implementation in reddit:
https://www.reddit.com/r/adventofcode/comments/a3912m/2018_day_5_solutions/eb4dchg/
## Examples
iex> Day5.react("dabAcCaCBAcCcaDA")
10
"""
def react(input, test_unit \\ nil) do
input
|> do_react(test_unit)
|> length()
end
@doc """
Tests each type of unit to see if removing it reduces the result from react.
Returns the smallest size possible
## Examples
iex> Day5.remove_worst_unit("dabAcCaCBAcCcaDA")
4
"""
def remove_worst_unit(input) do
# we can react first to reduce the input size to the loop
pre_react = do_react(input)
Enum.reduce(?A..?Z, 100000, fn (test_unit, best_score) ->
score = react(pre_react, test_unit)
cond do
score < best_score ->
score
true -> best_score
end
end)
end
defp do_react(input, test_unit \\ nil)
defp do_react(input, test_unit) when is_binary(input) do
input
|> String.to_charlist()
|> do_react(test_unit)
end
defp do_react(input, test_unit) when is_list(input) do
List.foldr(input, [], fn(unit, acc) -> react(unit, acc, test_unit) end)
end
# two units react when the difference in their ASCII code is 32
defguardp reacts(unit, prev_unit) when abs(unit - prev_unit) == 32
# used when testing problem polymers
defguardp is_under_test(unit, test_unit) when test_unit != nil and unit == test_unit or unit == test_unit + 32
# unit is under test so remove
defp react(unit, tail, test_unit) when is_under_test(unit, test_unit), do: tail
# handle the empty case
defp react(unit, [], _test_unit), do: [unit]
# handle when the last two elements in the list react
defp react(unit, [prev_unit], _test_unit) when reacts(unit, prev_unit), do: []
# if there's a reaction just return the tail to remove reacting elements
defp react(unit, [prev_unit | tail], _test_unit) when reacts(unit, prev_unit), do: tail
# all good, just add the unit to the list
defp react(unit, tail, _test_unit), do: [unit | tail]
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment