Last active
January 8, 2024 19:08
-
-
Save ramonrails/578917d502d997527c60944c83edcfa5 to your computer and use it in GitHub Desktop.
Matching brackets problem - with multiple bracket types
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Goal: find matching enclosures | |
// * opening enclosure must appear before closing | |
// * multiple opening enclosures can appear, but must be closed in proper reverse order | |
// * any other text, character ot symbol should not affect the result | |
// * pre or post padding space or characters should not affect the result | |
const balanced = (string) => { | |
// example: { "{}": 0, "[]": 0, ...} | |
let enclosures = { "{}": 0, "[]": 0, "()": 0, "<>": 0 } | |
// stack of keys must match closing braces in the reverse order | |
let stack = [] | |
// iterate and check each character | |
for (const char of string) { | |
// if we already have -1, skip the loop | |
if (Object.values(enclosures).includes(-1)) continue | |
// iterate for each pair of `enclosures` | |
for (const [key, value] of Object.entries(enclosures)) { | |
// when we have an opening enclosure to match | |
// note the `^` sign in regex | |
// | |
if (key.match(new RegExp("^\\" + char, "g"))) { | |
// remember the enclosure that the next cycle will match now | |
stack.push(key) | |
// because the opening matched, increment the counter | |
enclosures[key] = value + 1; | |
// cut the run short, check next | |
break | |
} else | |
// when we have a closing enclosure to match | |
// note the `$` sign in regex | |
// | |
if (key.match(new RegExp("\\" + char + "$", "g"))) { | |
// we found the closing of the last opening enclosure | |
if (stack.at(-1) === key) { | |
// ready to track any enclosure again | |
stack.pop() | |
// decrease the counter for this enclosure | |
enclosures[key] = value - 1 | |
// cut the run short, check next | |
break | |
} | |
// last key not matched? | |
// this closing is different from the last opening enclosure | |
else { | |
// mark the last key as a mis-match | |
enclosures[stack.at(-1)] = -1 | |
// fail fast | |
break | |
} | |
} | |
} // -- for entries() | |
} // -- for chars array | |
// This is balanced when all values are ZERO | |
// | |
return (Object.values(enclosures) || []).every(value => value === 0) ? "Matching" : "Naa!" | |
} | |
// test cases | |
// | |
[ | |
"()", "([{<>}])", "<>(){}[]", // Balanced | |
")(", "(()", "(])", "{[}]", "( () [{ }] )", // Nah! | |
"no paranthesis", "", // no enclosures? consider Balanced | |
"complex ( set of [paranthesis] <nested> ( at many levels{ here } ))" // nested and balanced | |
].map((arg) => { | |
console.log(balanced(arg) + ' <= ' + arg) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment