Advent of Code (2016) : Day 7

-- Problem --
You can find Part 1 of the problem statement here. Part 2 is unlocked on successful completion of Part 1.

-- Solution in Elixir --

      defmodule Aoc.Day7 do

  require Integer

  def parse_input() do
    {:ok, input} = File.read("day7_input.txt")
    String.split(input)
    |> Stream.map(&(String.split(&1, ["[","]"])))
    |> Enum.map(&Enum.with_index/1)
    |> Enum.map(&(Enum.reduce(&1, {[],[]}, fn({string, index},{outside_brackets, inside_brackets}) ->
              case Integer.is_even(index) do
                true -> {[string | outside_brackets], inside_brackets}
                false -> {outside_brackets, [string | inside_brackets]}
              end
            end)))
  end

  def is_valid_address({outside_brackets, inside_brackets}) do
    bool_result = Enum.any?(outside_brackets, &abba?/1) and Enum.all?(inside_brackets, &(!abba?(&1)))
    if bool_result, do: 1, else: 0
  end

  def abba?(input_string) when byte_size(input_string) < 4, do: false
  def abba?(<< a,b,b,a >> <> _) when a != b, do: true
  def abba?(<< _head >> <> tail), do: abba?(tail)

  def aba(input_string, result) do
    case input_string do
      input_string when byte_size(input_string) < 3 -> result
      << a,b,a >> <> _rest when a != b -> aba(String.slice(input_string, 1..-1), [{a, b}| result])
      << _head >> <> tail -> aba(tail, result)
    end
  end

  def bab?(input_string, {a,b}) do
    case input_string do
      input_string when byte_size(input_string) < 3 -> false
      << ^b,^a,^b >> <> _ -> true
      << _head >> <> tail -> bab?(tail, {a,b})
    end
  end

  def is_ssl_supported({outside_brackets, inside_brackets}) do
    aba = Enum.map(outside_brackets, &(aba(&1, []))) |> List.flatten
    bool_result = Enum.map(aba, fn({a,b}) ->
      Enum.any?(inside_brackets, fn(input_string) -> bab?(input_string, {a,b}) end)
    end)
    |> Enum.any?(&(&1))
    if bool_result, do: 1, else: 0
  end

  def output_1() do
    parse_input()
    |> Stream.map(&is_valid_address/1)
    |> Enum.sum
  end

  def output_2() do
    parse_input()
    |> Stream.map(&is_ssl_supported/1)
    |> Enum.sum
  end

end
    

You can find all my Advent of Code (2016) solutions here.