Created
December 6, 2018 15:21
-
-
Save chrismcg/633a69f51f6c9dc044a7e000ec3dafdd to your computer and use it in GitHub Desktop.
AoC 2018 day 5 in Elixir
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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