Skip to content

Instantly share code, notes, and snippets.

@ram-ai-kumar
Last active January 8, 2024 19:08
Show Gist options
  • Select an option

  • Save ram-ai-kumar/578917d502d997527c60944c83edcfa5 to your computer and use it in GitHub Desktop.

Select an option

Save ram-ai-kumar/578917d502d997527c60944c83edcfa5 to your computer and use it in GitHub Desktop.

Revisions

  1. ram-ai-kumar renamed this gist Jan 8, 2024. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  2. ram-ai-kumar created this gist Jan 3, 2024.
    73 changes: 73 additions & 0 deletions batching_brackets.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,73 @@
    // 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)
    })