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(<>, acc) when is_opening_bracket(opening), do: do_check_brackets(str, [opening | acc]) # Closing bracket defp do_check_brackets(<>, [opening | tail]) when is_pair(closing, opening), do: do_check_brackets(str, tail) defp do_check_brackets(<>, _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