exercism/elixir/matching-brackets/lib/matching_brackets.ex

29 lines
1.3 KiB
Elixir

defmodule MatchingBrackets do
require Logger
@opening_brackets ~w"[ { ("
@closing_brackets ~w"] } )"
@bracket_pairs Enum.zip(@closing_brackets, @opening_brackets)
@doc """
Checks that all the brackets and braces in the string are matched correctly, and nested correctly
"""
@spec check_brackets(String.t()) :: boolean
def check_brackets(str), do: do_check_brackets(str, [])
defguardp is_opening_bracket(char) when char in @opening_brackets
defguardp is_closing_bracket(char) when char in @closing_brackets
defguardp is_pair(closing, opening) when {closing, opening} in @bracket_pairs
# Base cases
defp do_check_brackets("", []), do: true
defp do_check_brackets("", _any), do: false
# Opening bracket
defp do_check_brackets(<<opening::binary-size(1), str::binary>>, acc) when is_opening_bracket(opening), do: do_check_brackets(str, [opening | acc])
# Closing bracket
defp do_check_brackets(<<closing::binary-size(1), str::binary>>, [opening | tail]) when is_pair(closing, opening), do: do_check_brackets(str, tail)
defp do_check_brackets(<<closing::binary-size(1), _str::binary>>, _acc) when is_closing_bracket(closing), do: false
# Not a bracket
defp do_check_brackets(<<_char::binary-size(1), str::binary>>, acc), do: do_check_brackets(str, acc)
end