The code works, at least against the unit tests. But I would like input on how to refactor it. Or also maybe a way to do this without using temporary lists? I also have some special checks, like if the string is empty or if the brackets are unbalanced; is there a way to incorporate these special checks into the main body? It has been my problem with coding; I cannot refactor special cases into the general algorithm.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public static class MatchingBrackets
{
public static bool IsPaired(string input)
{
string opening = "{[(";
string closing = "}])";
// Temporary lists to hold currently unmatched opening-closing brackets
List<char> opening_brackets = new List<char>{};
List<char> closing_brackets = new List<char>{};
// If input is empty string then return true
if (input.Count() == 0) { return true;}
// Loop through each character
foreach (char i in input)
{
// If the character is in the set of opening and closing brackets
if ((opening + closing).Contains(i))
// If it is an opening bracket, append to opening brackets temp list
if (opening.Contains(i) is true) { opening_brackets.Add(i); }
else
{
// Append closing bracket to closing brackets temp list
closing_brackets.Add(i);
// If there are no (more) temp opening brackets but we are in this else statement,
// then we fail already
if (opening_brackets.Count == 0) { return false;}
// Find the opening bracket that corresponds to the currently closing bracket
char required_prev_opening = opening.ElementAt(closing.LastIndexOf(i));
// If the corresponding opening bracket is not the same to the last
// opening bracket, we fail already
if (required_prev_opening != (char)opening_brackets.Last()) { return false;}
// The current closing bracket has a correct corresponding opening bracket. Remove them from
// their respective temporary list
opening_brackets.RemoveAt(opening_brackets.Count-1);
closing_brackets.RemoveAt(closing_brackets.Count-1);
}
}
// Check if there are still unmatched opening or closing brackets. If so then we fail.
if (opening_brackets.Count != 0 || closing_brackets.Count != 0)
{
return false;
}
return true;
}
}
The unit tests are:
// This file was auto-generated based on version 2.0.0 of the canonical data.
using Xunit;
public class MatchingBracketsTests
{
[Fact]
public void Paired_square_brackets()
{
var value = "[]";
Assert.True(MatchingBrackets.IsPaired(value));
}
[Fact]
public void Empty_string()
{
var value = "";
Assert.True(MatchingBrackets.IsPaired(value));
}
[Fact]
public void Unpaired_brackets()
{
var value = "[[";
Assert.False(MatchingBrackets.IsPaired(value));
}
[Fact]
public void Wrong_ordered_brackets()
{
var value = "}{";
Assert.False(MatchingBrackets.IsPaired(value));
}
[Fact]
public void Wrong_closing_bracket()
{
var value = "{]";
Assert.False(MatchingBrackets.IsPaired(value));
}
[Fact]
public void Paired_with_whitespace()
{
var value = "{ }";
Assert.True(MatchingBrackets.IsPaired(value));
}
[Fact]
public void Partially_paired_brackets()
{
var value = "{[])";
Assert.False(MatchingBrackets.IsPaired(value));
}
[Fact]
public void Simple_nested_brackets()
{
var value = "{[]}";
Assert.True(MatchingBrackets.IsPaired(value));
}
[Fact]
public void Several_paired_brackets()
{
var value = "{}[]";
Assert.True(MatchingBrackets.IsPaired(value));
}
[Fact]
public void Paired_and_nested_brackets()
{
var value = "([{}({}[])])";
Assert.True(MatchingBrackets.IsPaired(value));
}
[Fact]
public void Unopened_closing_brackets()
{
var value = "{[)][]}";
Assert.False(MatchingBrackets.IsPaired(value));
}
[Fact]
public void Unpaired_and_nested_brackets()
{
var value = "([{])";
Assert.False(MatchingBrackets.IsPaired(value));
}
[Fact]
public void Paired_and_wrong_nested_brackets()
{
var value = "[({]})";
Assert.False(MatchingBrackets.IsPaired(value));
}
[Fact]
public void Paired_and_incomplete_brackets()
{
var value = "{}[";
Assert.False(MatchingBrackets.IsPaired(value));
}
[Fact]
public void Too_many_closing_brackets()
{
var value = "[]]";
Assert.False(MatchingBrackets.IsPaired(value));
}
[Fact]
public void Math_expression()
{
var value = "(((185 + 223.85) * 15) - 543)/2";
Assert.True(MatchingBrackets.IsPaired(value));
}
[Fact]
public void Complex_latex_expression()
{
var value = "\\left(\\begin{array}{cc} \\frac{1}{3} & x\\\\ \\mathrm{e}^{x} &... x^2 \\end{array}\\right)";
Assert.True(MatchingBrackets.IsPaired(value));
}
}