Interview test: Bracket matching
With test suite
by Jason Green
HTML
<script src="https://searls.github.io/jasmine-all/jasmine-all-min.js"></script>
<div>
<strong>User Logs</strong>
<div id="out">
</div>
</div>
CSS
body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
#HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
#HTMLReporter a { text-decoration: none; }
#HTMLReporter a:hover { text-decoration: underline; }
#HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; }
#HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; }
#HTMLReporter #jasmine_content { position: fixed; right: 100%; }
#HTMLReporter .version { color: #aaaaaa; }
#HTMLReporter .banner { margin-top: 14px; }
#HTMLReporter .duration { color: #aaaaaa; float: right; }
#HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; }
#HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; }
#HTMLReporter .symbolSummary li.passed { font-size: 14px; }
#HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; }
#HTMLReporter .symbolSummary li.failed { line-height: 9px; }
#HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
#HTMLReporter .symbolSummary li.skipped { font-size: 14px; }
#HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; }
#HTMLReporter .symbolSummary li.pending { line-height: 11px; }
#HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; }
#HTMLReporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; }
#HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
#HTMLReporter .runningAlert { background-color: #666666; }
#HTMLReporter .skippedAlert...
JavaScript
const OPENS = "{[(";
const CLOSES = "}])"
const MATCHES = {
"{": "}",
"[": "]",
"(": ")"
}
function isBalanced(str) {
let stack = [];
for (let char of str) {
if (OPENS.includes(char)) {
stack.push(char);
} else if (CLOSES.includes(char)) {
const openingChar = stack.pop();
if (MATCHES[openingChar] !== char) {
return false;
}
}
}
return stack.length === 0;
}
describe("isBalanced", function() {
it("should return true for strings with balanced parenthesis", function() {
expect(isBalanced('(())')).toBe(true, '(())');
expect(isBalanced('()()')).toBe(true, '()()');
expect(isBalanced('(()')).toBe(false, '(()');
expect(isBalanced(')(')).toBe(false, ')(');
expect(isBalanced('(()))(')).toBe(false, '(()))(');
});
it("should support other types of brackets too", function() {
expect(isBalanced('{[()]}')).toBe(true, '{[()]}');
expect(isBalanced('{}()')).toBe(true, '{}()');
expect(isBalanced('{}()}')).toBe(false, '{}()}');
expect(isBalanced('{[}]')).toBe(false, '{[}]');
expect(isBalanced('{[{}}]')).toBe(false, '{[{}}]');
});
});
function log(str) {
var prev = document.getElementById('out').innerHTML;
document.getElementById('out').innerHTML = prev + str + '<br>';
}