Skip to content

Instantly share code, notes, and snippets.

@pepasflo
Created June 27, 2018 00:34
Show Gist options
  • Save pepasflo/e604276a5e4eb8387257b99e63d505b8 to your computer and use it in GitHub Desktop.
Save pepasflo/e604276a5e4eb8387257b99e63d505b8 to your computer and use it in GitHub Desktop.
"Matching parens" problem from interview cake, see https://www.interviewcake.com/question/python/matching-parens
test: paren
./paren
paren: paren.c
gcc -Wall -Werror -o paren paren.c
clean:
rm -f paren
.PHONY: test paren
/*
"Sometimes (when I nest them (my parentheticals) too much (like this (and this))) they get confusing."
Write a function that, given a sentence like the one above, along with the
position of an opening parenthesis, finds the corresponding closing parenthesis.
Example: if the example string above is input with the number 10 (position of the
first parenthesis), the output should be 79 (position of the last parenthesis).
*/
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <stdbool.h>
#define ERROR UINT32_MAX
// returns UINT32_MAX on error
uint32_t cpareni(char *str, uint32_t opareni) {
if (str == NULL) {
// passing in a NULL string is an error
return ERROR;
}
int32_t depth = 0;
int32_t target_depth = 0;
uint32_t i = 0;
while (true) {
char ch = str[i];
if (ch == '\0') {
// if we reached end-of-string before finding the closing paren, return an error.
return ERROR;
}
if (i == opareni) {
if (ch != '(') {
// if the passed index isn't an opening paren, that's an error;
return ERROR;
}
target_depth = depth;
if (target_depth < 0) {
// if the parens are unbalanced, that's an error.
return ERROR;
}
}
if (ch == '(') {
depth += 1;
} else if (ch == ')') {
depth -= 1;
if (i > opareni && depth == target_depth) {
return i;
}
}
i += 1;
}
}
void test() {
// passing in a NULL string should return an error.
assert(cpareni(NULL, 0) == ERROR);
// passing in an empty string should return an error.
assert(cpareni("", 0) == ERROR);
// if the passed index is out of bounds, that's an error.
assert(cpareni("(foo)", 42) == ERROR);
// if end-of-string is reached before finding the closing paren, that's an error.
assert(cpareni("(aaa", 0) == ERROR);
// if the passed index isn't an opening paren, that should be an error.
assert(cpareni(")", 0) == ERROR);
// if the parens are unbalanced, that's an error.
assert(cpareni(")()", 1) == ERROR);
// happy-path tests:
// basic:
assert(cpareni("()", 0) == 1);
assert(cpareni("(foo)", 0) == 4);
// nested:
assert(cpareni("(())", 0) == 3);
assert(cpareni("(())", 1) == 2);
// non-paren chars:
assert(cpareni("(a())", 2) == 3);
assert(cpareni("((a))", 1) == 3);
assert(cpareni("(()a)", 1) == 2);
// peer-parens:
assert(cpareni("()()", 2) == 3);
// nesting and peering:
assert(cpareni("(()())", 1) == 2);
assert(cpareni("(()())", 3) == 4);
}
int main(int argc, char **argv) {
test();
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment