Created
June 27, 2018 00:34
-
-
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
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
test: paren | |
./paren | |
paren: paren.c | |
gcc -Wall -Werror -o paren paren.c | |
clean: | |
rm -f paren | |
.PHONY: test paren |
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
/* | |
"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