# paulfioravanti's solution

## to Matching Brackets in the Elixir Track

Published at Aug 11 2019 · 0 comments
Instructions
Test suite
Solution

#### Note:

This exercise has changed since this solution was written.

# Bracket Push

Given a string containing brackets [], braces {}, parentheses (), or any combination thereof, verify that any and all pairs are matched and nested correctly.

## Running tests

Execute the tests with:

\$ mix test


### Pending tests

In the test suites, all but the first test have been skipped.

Once you get a test passing, you can unskip the next one by commenting out the relevant @tag :pending with a # symbol.

For example:

# @tag :pending
test "shouting" do
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
end


Or, you can enable all the tests by commenting out the ExUnit.configure line in the test suite.

# ExUnit.configure exclude: :pending, trace: true


If you're stuck on something, it may help to look at some of the available resources out there where answers might be found.

Ginna Baker

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

### bracket_push_test.exs

defmodule BracketPushTest do
use ExUnit.Case

# @tag :pending
test "paired square brackets" do
assert BracketPush.check_brackets("[]")
end

@tag :pending
test "empty string" do
assert BracketPush.check_brackets("")
end

@tag :pending
test "unpaired brackets" do
refute BracketPush.check_brackets("[[")
end

@tag :pending
test "wrong ordered brackets" do
refute BracketPush.check_brackets("}{")
end

@tag :pending
test "wrong closing bracket" do
refute BracketPush.check_brackets("{]")
end

@tag :pending
test "paired with whitespace" do
assert BracketPush.check_brackets("{ }")
end

@tag :pending
test "simple nested brackets" do
assert BracketPush.check_brackets("{[]}")
end

@tag :pending
test "several paired brackets" do
assert BracketPush.check_brackets("{}[]")
end

@tag :pending
test "paired and nested brackets" do
assert BracketPush.check_brackets("([{}({}[])])")
end

@tag :pending
test "unopened closing brackets" do
refute BracketPush.check_brackets("{[)][]}")
end

@tag :pending
test "unpaired and nested brackets" do
refute BracketPush.check_brackets("([{])")
end

@tag :pending
test "paired and wrong nested brackets" do
refute BracketPush.check_brackets("[({]})")
end

@tag :pending
test "math expression" do
assert BracketPush.check_brackets("(((185 + 223.85) * 15) - 543)/2")
end

@tag :pending
test "complex latex expression" do
assert BracketPush.check_brackets(
"\\left(\\begin{array}{cc} \\frac{1}{3} & x\\\\ \\mathrm{e}^{x} &... x^2 \\end{array}\\right)"
)
end
end

### test_helper.exs

ExUnit.start()
ExUnit.configure(exclude: :pending, trace: true)
defmodule BracketPush do
@opening_brackets '([{'
@closing_brackets ')]}'

defguardp opening_bracket?(char) when char in @opening_brackets
defguardp closing_bracket?(char) when char in @closing_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
str
|> String.to_charlist()
|> Enum.reduce([], &check_pair/2)
|> Enum.empty?()
catch
:halt ->
false
end

defp check_pair(char, acc) when opening_bracket?(char), do: [char | acc]

defp check_pair(char, acc) when closing_bracket?(char) do
if matching_opening_bracket?(char, acc) do
tl(acc)
else
throw(:halt)
end
end

defp check_pair(_char, acc), do: acc

defp matching_opening_bracket?(_char, []), do: false

defp matching_opening_bracket?(char, acc) do
opening_bracket =
@closing_brackets
|> Enum.find_index(&(&1 == char))
|> (fn index -> Enum.at(@opening_brackets, index) end).()

hd(acc) == opening_bracket
end
end