Longest substring of correct parenthesis - c

I'm running into a bit of a problem. I have to compute the longest substring of correctly closed parenthesis and so far I've managed to do this:
while (work_stack.size != 0){
//I have a working stack in which I have stored the elements
//which in my case are brackets and while I have elements
//i pop the first element and see if it's a left or right
a1 = pop(&work_stack.data);
work_stack.size--;
if ('{' == ((Pair*)a1->info)->type ||
'(' == ((Pair*)a1->info)->type ||
'[' == ((Pair*)a1->info)->type) {
//if it's a left bracket, then I add it to the left stack
//which i'm going to use to compare with the right sided
//brackets i will encounter.
stanga++; //i'm incrementing the no of left brackets
if(ok == 0) //if there wasn't a match, then length is set to 0
length = 0;
if (ok == 1 && stanga > 1)
//if there was a match but then two brackets of left side
//are encountered, then length = 0
/*
Now I figured that here I am wrong. Given the input:
[][()()])())[][)]
The right value should be 8, but my code encounters
two left values and sets the length to 0. I need to
find a way to determine if the substring is worth keeping
*/
length = 0;
push(&left.data, a1);
left.size++;
}
if ('}' == ((Pair*)a1->info)->type ||
')' == ((Pair*)a1->info)->type ||
']' == ((Pair*)a1->info)->type){
//if it's a right bracket and there are elements in the left
//then i pop the first element fro the left stack and compare
//it to my current bracket
if(left.size != 0){
stanga = 0;
a2 = pop(&left.data);
left.size--;
//opposing is a function that returns 1 if
//i encounter something like ( ) or [ ] or { }
//if the brackets are opposed, i increment the length
if (oposing(((Pair*)a2->info)->type, ((Pair*)a1->info)->type) == 1){
length += 2;
ok = 1;
}
//otherwise, it seems that I have run into a stopping
//point, so I'm emptying the left stack because those
//paranthesis are not of use anymore and I'm saving
//the maximum length acquired by now
if (oposing(((Pair*)a2->info)->type, ((Pair*)a1->info)->type) == 0){
ok = 0;
while(left.size > 0){
a2 = pop(&left.data);
left.size--;
}
if(length > max){
max = length;
length = 0;
}
}
//if i haven't encountered a stopping point, i just
//compare the length to my max and save it if it's bigger
if (length > max)
max = length;
}
//this line says that if the size of the left stack is 0 and
//i have encountered a right bracket, then I can't form a
//correct substring, so the length is 0
else length = 0;
}
}
To note that: ((Pair*)a1->info)->type is my character.
Thank you!
Later Edit:
- I'm adding the structures for stack and Pair
typedef struct{
int id;
char type;
}Pair;
typedef struct cel{
void *info;
struct cel *urm;
}Celula, *TLista, **ALista;
typedef struct{
TLista data;
int size;
}stack;
My stack has the data type as a linked list but that shouldn't matter that much as the operations are correct (push and pop).
Edit: Added some new improvements to the code, as well as a new expalanation in comments as to what I'm doing. I identified the bug but I'm failing to find a solution for it.

This problem can be solved using stack. Here is my C++ implementation, hope you will feel no difficulty to understand the syntax and translate it into C.
int longestValidParentheses(string s) {
stack <int> Stack;
int maxLen = 0;
int lastPos = -1;
for(int i = 0; i < s.length(); ++i) {
if(s[i] == '(') {
Stack.push(i);
}
else {
if(Stack.empty()) {
lastPos = i;
}
else {
Stack.pop();
if(Stack.empty()) {
maxLen = max(maxLen, i - lastPos);
} else {
maxLen = max(maxLen, i - Stack.top());
}
}
}
}
return maxLen;
}
Sorry for the code rather than explanation as I am outside right now. I will put clarification if you need explanation on any part. For now, you can check with some input and pen-and-paper.

Related

The scoring site keep saying that my code is exceeded time limit

well, I tried to solve problem Find the Cow! [Brian Dean, 2012]
I find it works well in "visual studio" and other IDE. But in "code up" the site which scores my code... it keeps saying that my code exceeded time limit...
Is there any problem with my code?
The problem is
PROBLEM NAME: cowfind
INPUT FORMAT:
Line 1: A string of parentheses of length N (1 <= N <= 50,000).
SAMPLE INPUT (file cowfind.in):
)((()())())
OUTPUT FORMAT:
Line 1: The number of possible positions at which Bessie can be
standing -- that is, the number of distinct pairs of indices
x < y at which there is the pattern (( at index x and the
pattern )) at index y.
SAMPLE OUTPUT (file cowfind.out):
4
OUTPUT DETAILS:
There are 4 possible locations for Bessie, indicated below:
1.
)((()())())
^^ ^^
2.
)((()())())
^^ ^^
3.
)((()())())
^^ ^^
4.
)((()())())
^^ ^^
The code:
#include <stdio.h>
#pragma warning(disable:4996)
int main() {
char c[50000];
int i = 0;
int j;
int num = 0;
while (scanf("%c", &c[i]) == 1)i++;
c[i] = '\0';
i = 0;
while (c[i + 1] != '\0') {
if ( (c[i] == c[i + 1]) && c[i] == '(') {
j = i + 2;
while (c[j + 1] != '\0') {
if ((c[j] == c[j + 1]) && c[j] == ')') {
num++;
}
j++;
}
}
i++;
}
printf("%d", num);
}
For many of these online judge problems, a key is to think of a better way to calculate the result. They are not challenging you just to write code but to think about how better algorithms can be designed.
#include <stdio.h>
int main(void)
{
long positions = 0; // Count positions where Bessie may be standing.
long opens = 0; // Count number of times "((" has been seen.
char previous = 0; // Remember previous character.
// Loop reading characters.
while (1)
{
// Get next character.
int next = getchar();
// If there was no next character or the line ended, we are done.
if (next == EOF || next == '\n') break;
// Count the number of times "((" has been seen.
if (next == '(' && previous == '(')
++opens;
// When we see "))", add one position for each "((" that precedes it.
if (next == ')' && previous == ')')
positions += opens;
// Remember the character for the next iteration.
previous = next;
}
// Show the result.
printf("%ld\n", positions);
}

Why is this array being initialized in an odd way?

I am reading K&R 2nd Edition and I am having trouble understanding exercise 1-13. The answer is this code
#include <stdio.h>
#define MAXHIST 15
#define MAXWORD 11
#define IN 1
#define OUT 0
main()
{
int c, i, nc, state;
int len;
int maxvalue;
int ovflow;
int wl[MAXWORD];
state = OUT;
nc = 0;
ovflow = 0;
for (i = 0; i < MAXWORD; i++)
wl[i] = 0;
while ((c = getchar()) != EOF)
{
if(c == ' ' || c == '\n' || c == '\t')
{
state = OUT;
if (nc > 0)
{
if (nc < MAXWORD)
++wl[nc];
else
++ovflow;
}
nc = 0;
}
else if (state == OUT)
{
state = IN;
nc = 1;
}
else
++nc;
}
maxvalue = 0;
for (i = 1; i < MAXWORD; ++i)
{
if(wl[i] > maxvalue)
maxvalue = wl[i];
}
for(i = 1; i < MAXWORD; ++i)
{
printf("%5d - %5d : ", i, wl[i]);
if(wl[i] > 0)
{
if((len = wl[i] * MAXHIST / maxvalue) <= 0)
len = 1;
}
else
len = 0;
while(len > 0)
{
putchar('*');
--len;
}
putchar('\n');
}
if (ovflow > 0)
printf("There are %d words >= %d\n", ovflow, MAXWORD);
return 0;
}
At the top, wl is being declared and initialized. What I don't understand is why is it looping through it and setting everything to zero if it just counts the length of words? It doesn't keep track of how many words there are, it just keeps track of the word length so why is everything set to 0?
I know this is unclear it's just been stressing me out for the past 20 minutes and I don't know why.
The ith element of the array wl[] is the number of words of length i that have been found in an input file. The wl[] array needs to be zero-initialized first so that ++wl[nc]; does not cause undefined behavior by attempting to use an uninitialized variable, and so that array elements that represent word lengths that are not present reflect that no such word lengths were found.
Note that ++wl[nc] increments the value wl[nc] when a word of length nc is encountered. If the array were not initialized, the first time the code attempts to increment an array element, it would be attempting to increment an indeterminate value. This attempt would cause undefined behavior.
Further, array indices that represent counts of word lengths that are not found in the input should hold values of zero, but without the zero-initialization, these values would be indeterminate. Even attempting to print these indeterminate values would cause undefined behavior.
The moral: initialize variables to sensible values, or store values in them, before attempting to use them.
It would seem simpler and be more clear to use an array initializer to zero-initialize the wl[] array:
int wl[MAXWORD] = { 0 };
After this, there is no need for the loop that sets the array values to zero (unless the array is used again) for another file. But, the posted code is from The C Answer Book by Tondo and Gimpel. This book provides solutions to the exercises found in the second edition of K&R in the style of K&R, and using only ideas that have been introduced in the book before each exercise. This exercise, 1.13, occurs in "Chapter 1 - A Tutorial Introduction". This is a brief tour of the language lacking many details to be found later in the book. At this point, assignment and arrays have been introduced, but array initializers have not (this has to wait until Chapter 4), and the K&R code that uses arrays has initialized arrays using loops thus far. Don't read too much into code style from the introductory chapter of a book that is 30+ years old.
Much has changed in C since K&R was published, e.g., main() is no longer a valid function signature for the main() function. Note that the function signature must be one of int main(void) or int main(int argc, char *argv[]) (or alternatively int main(int argc, char **argv)), with a caveat for implementation-defined signatures for main().
Everything is set to 0 because if you dont initialize the array, the array will be initialize with random number in it. Random number will cause error in your program. Instead of looping in every position of your array you could do this int wl[MAXWORD] = {0}; at the place of int wl[MAXWORD]; this will put 0 at every position in your array so you dont hava to do the loop.
I edited your code and put some comments in as I was working through it, to explain what's going on. I also changed some of your histogram calculations because they didn't seem to make sense to me.
Bottom line: It's using a primitive "state machine" to count up the letters in each group of characters that isn't white space. It stores this in wl[] such that wl[i] contains an integer that tells you how many groups of characters (sometimes called "tokens") has a word length of i. Because this is done by incrementing the appropriate element of w[], each element must be initialized to zero. Failing to do so would lead to undefined behavior, but probably would result in nonsensical and absurdly large counts in each element of w[].
Additionally, any token with a length that can't be reflected in w[] will be tallied in the ovflow variable, so at the end there will be an accounting of every token.
#include <stdio.h>
#define MAXHIST 15
#define MAXWORD 11
#define IN 1
#define OUT 0
int main(void) {
int c, i, nc, state;
int len;
int maxvalue;
int ovflow;
int wl[MAXWORD];
// Initializations
state = OUT; //Start off not assuming we're IN a word
nc = 0; //Start off with a character count of 0 for current word
ovflow = 0; //Start off not assuming any words > MAXWORD length
// Start off with our counters of words at each length at zero
for (i = 0; i < MAXWORD; i++) {
wl[i] = 0;
}
// Main loop to count characters in each 'word'
// state keeps track of whether we are IN a word or OUTside of one
// For each character in the input stream...
// - If it's whitespace, set our state to being OUTside of a word
// and, if we have a character count in nc (meaning we've just left
// a word), increment the counter in the wl (word length) array.
// For example, if we've just counted five characters, increment
// wl[5], to reflect that we now know there is one more word with
// a length of five. If we've exceeded the maximum word length,
// then increment our overflow counter. Either way, since we're
// currently looking at a whitespace character, reset the character
// counter so that we can start counting characters with our next
// word.
// - If we encounter something other than whitespace, and we were
// until now OUTside of a word, change our state to being IN a word
// and start the character counter off at 1.
// - If we encounter something other than whitespace, and we are
// still in a word (not OUTside of a word), then just increment
// the character counter.
while ((c = getchar()) != EOF) {
if (c == ' ' || c == '\n' || c == '\t') {
state = OUT;
if (nc > 0) {
if (nc < MAXWORD) ++wl[nc];
else ++ovflow;
}
nc = 0;
} else if (state == OUT) {
state = IN;
nc = 1;
} else {
++nc;
}
}
// Find out which length has the most number of words in it by looping
// through the word length array.
maxvalue = 0;
for (i = 1; i < MAXWORD; ++i) {
if(wl[i] > maxvalue) maxvalue = wl[i];
}
// Print out our histogram
for (i = 1; i < MAXWORD; ++i) {
// Print the word length - then the number of words with that length
printf("%5d - %5d : ", i, wl[i]);
if (wl[i] > 0) {
len = wl[i] * MAXHIST / maxvalue;
if (len <= 0) len = 1;
} else {
len = 0;
}
// This is confusing and unnecessary. It's integer division, with no
// negative numbers. What we want to have happen is that the length
// of the bar will be 0 if wl[i] is zero; that the bar will have length
// 1 if the bar is otherwise too small to represent; and that it will be
// expressed as some fraction of MAXHIST otherwise.
//if(wl[i] > 0)
// {
// if((len = wl[i] * MAXHIST / maxvalue) <= 0)
// len = 1;
// }
// else
// len = 0;
// Multiply MAXHIST (our histogram maximum length) times the relative
// fraction, i.e., we're using a histogram bar length of MAXHIST for
// our statistical mode, and interpolating everything else.
len = ((double)wl[i] / maxvalue) * MAXHIST;
// Our one special case might be if maxvalue is huge, a word length
// with just one occurrence might be rounded down to zero. We can fix
// that manually instead of using a weird logic structure.
if ((len == 0) && (wl[i] > 0)) len = 1;
while (len > 0) {
putchar('*');
--len;
}
putchar('\n');
}
// If any words exceeded the maximum word length, say how many there were.
if (ovflow > 0) printf("There are %d words >= %d\n", ovflow, MAXWORD);
return 0;
}

Out of bounds 2D array error in C

Im stuck on this one part and I was hoping to get some help. I have a project that is basically a word search. The program reads in a file that contains the Rows and columns followed by the word search puzzle itself. You are required to create possible combinations of strings from the word search and check those combinations with a dictionary that is provided as another text document.
Here's an example of the file read in 1st is Rows and 2nd is Cols followed by the word search puzzle:
4 4
syrt
gtrp
faaq
pmrc
So I have been able to get most of the code to work except for the function that creates strings for the above file. Basically It needs to search the wordsearch and create strings, each created string gets passed on to another function to check if it's in the dictionary. However my code keeps going out of bounds when creating the strings, and it's continuing to cause Seg faults which is really frustrating.
Theses are the constants that are declared, its every possible direction to go while searching the word search puzzle for possible string combinations
const int DX_SIZE = 8;
const int DX[] = {-1,-1,-1,0,0,1,1,1};
const int DY[] = {-1,0,1,-1,1,-1,0,1};
This is the function I have to create the strings:
int strCreate(char** puzzle, char** dictionary, int n, int rows, int col){
int x, y;
int nextX, nextY, i;
char str[20] = {0};
int length = 1;
for(x = 0; x < rows; x++)
{
for(y = 0; y < col; y++)
{
//Grabs the base letter
str[0] = puzzle[x][y];
length = 1;
for(i = 0; i < DX_SIZE; i++)
{
while(length < MAX_WORD_SIZE)
{
nextX = x + DX[i]*length;
nextY = y + DY[i]*length;
// Checking bounds of next array
//This is where I'm having trouble.
if((x + nextX) < 0 || (nextX + x) > (col-1)){
printf("Out of bounds\n");
break;
}
if((y + nextY) < 0 || (nextY + y) > (rows-1)){
printf("Out of bounds\n");
break;
}
str[length] = puzzle[nextX][nextY];
//search for str in dictionary
checkStr(str, dictionary, n);
length++;
}
memset(&str[1], '\0', 19);
}
}
}
return 0;
}
I know i'm not checking the bounds properly I just can't figure out how to. When X = 1 and nextX = -1, that passes the bounds check, however say the array is at puzzle[0][0] nextX would put puzzle[-1][0] which is out of bounds causing the seg fault.
Thank you for taking the time to read, and I appreciate any help at all.
nextX and nextY are the indices used to access the array puzzle. Then the array bound check should also include the same. But the array bound check includes for example x+nextX.
// Checking bounds of next array
//This is where I'm having trouble.
if((x + nextX) < 0 || (nextX + x) > (col-1)){
printf("Out of bounds\n");
break;
}
Example:
if( nextX < 0)
printf("Out of bounds...\n");

how to initialize array of unknown size in c

I am doing a homework assignment for an intro to programming class in c.
I need to write a program that looks at an int array of unknown size (we are given a initializer list as the test case to use), and determine all the duplicates in the array.
To make sure that an element that was already found to be a duplicate doesn't get tested, I want to use a parallel array to the original that would hold the numbers of all the elements that were duplicates.
I need this array to be the same size as the original array, which of course we don't really know till the initializer list is given to us.
I tried using sizeof() to achieve this, but visual studio says that is an error due to the variable size (const int size = sizeof(array1);) not being constant. Am I not using sizeof correctly? Or is this logic flawed?
Perhaps there is another way to approach this, but I have yet to come up with one.
Here is the code included below, hope the comments don't make it too hard to read.
// Dean Davis
// Cs 1325
// Dr. Paulk
// Duplicates hw
#include <stdio.h>
int main()
{
int array1[] = { 0,0,0,0,123,124,125,3000,3000,82,876,986,345,1990,2367,98,2,444,993,635,283,544, 923,18,543,777,234,549,864,39,97,986,986,1,2999,473,776,9,23,397,15,822,1927,1438,1937,1956,7, 29,- 1 };
const int size = sizeof(array1);
int holdelements[size];
int a = 0; // counter for the loop to initialize the hold elements array
int b = 0; // counter used to move through array1 and be the element number of the element being tested
int c = 0; // counter used to move through holdelements and check to see if the element b has already been tested or found as duplicates
int d = 0; // counter used to move through array1 and check to see if there are any duplicates
int e = 0; // counter used to hold place in hold element at the next element where a new element number would go. sorry if that makes no sense
int flag = 0; // used as a boolian to make sure then large while loop ends when we reach a negative one value.
int flag2 = 0; // used as a boolian to stop the second while loop from being infinite. stops the loop when the end of hold elements has been reached
int flag3 = 0; // used to close the third while loop; is a boolian
int numberofduplicates=0;// keeps track of the number of duplicates found
for (a; a < size; a++)
{
if (a == (size - 1))
holdelements[a] = -1;
else
holdelements[a] = -2;
}
while (!flag)
{
flag2 = 0;
flag3 = 0;
if (array1[b] == -1)
flag = 1;
else
{
while ((!flag) && (!flag2))
{
if (holdelements[c] == -1)
flag2 = 1;
else if (array1[b] == holdelements[c])
{
b++;
c = 0;
if (array1[b] == -1)
flag = 1;
}
}
while (!flag3)
{
if (array1[d] == -1)
flag3 = 1;
else if (array1[b] == array1[d] && b != d)
{
printf("Duplicate of %d, index %d, was found at index %d.\n", array1[b], b, d);
holdelements[e] = d;
d++;
e++;
numberofduplicates++;
}
}
}
b++;
}
printf("Total Duplicates Found: %d\n", numberofduplicates);
return 0;
}
redo to the following:
const int size = sizeof(array1)/sizeof(int);

Parsing character array to words held in pointer array (C-programming)

I am trying to separate each word from a character array and put them into a pointer array, one word for each slot. Also, I am supposed to use isspace() to detect blanks. But if there is a better way, I am all ears. At the end of the code I want to print out the content of the parameter array.
Let's say the line is: "this is a sentence". What happens is that it prints out "sentence" (the last word in the line, and usually followed by some random character) 4 times (the number of words). Then I get "Segmentation fault (core dumped)".
Where am I going wrong?
int split_line(char line[120])
{
char *param[21]; // Here I want to put one word for each slot
char buffer[120]; // Word buffer
int i; // For characters in line
int j = 0; // For param words
int k = 0; // For buffer chars
for(i = 0; i < 120; i++)
{
if(line[i] == '\0')
break;
else if(!isspace(line[i]))
{
buffer[k] = line[i];
k++;
}
else if(isspace(line[i]))
{
buffer[k+1] = '\0';
param[j] = buffer; // Puts word into pointer array
j++;
k = 0;
}
else if(j == 21)
{
param[j] = NULL;
break;
}
}
i = 0;
while(param[i] != NULL)
{
printf("%s\n", param[i]);
i++;
}
return 0;
}
There are many little problems in this code :
param[j] = buffer; k = 0; : you rewrite at the beginning of buffer erasing previous words
if(!isspace(line[i])) ... else if(isspace(line[i])) ... else ... : isspace(line[i]) is either true of false, and you always use the 2 first choices and never the third.
if (line[i] == '\0') : you forget to terminate current word by a '\0'
if there are multiple white spaces, you currently (try to) add empty words in param
Here is a working version :
int split_line(char line[120])
{
char *param[21]; // Here I want to put one word for each slot
char buffer[120]; // Word buffer
int i; // For characters in line
int j = 0; // For param words
int k = 0; // For buffer chars
int inspace = 0;
param[j] = buffer;
for(i = 0; i < 120; i++) {
if(line[i] == '\0') {
param[j++][k] = '\0';
param[j] = NULL;
break;
}
else if(!isspace(line[i])) {
inspace = 0;
param[j][k++] = line[i];
}
else if (! inspace) {
inspace = 1;
param[j++][k] = '\0';
param[j] = &(param[j-1][k+1]);
k = 0;
if(j == 21) {
param[j] = NULL;
break;
}
}
}
i = 0;
while(param[i] != NULL)
{
printf("%s\n", param[i]);
i++;
}
return 0;
}
I only fixed the errors. I leave for you as an exercise the following improvements :
the split_line routine should not print itself but rather return an array of words - beware you cannot return an automatic array, but it would be another question
you should not have magic constants in you code (120), you should at least have a #define and use symbolic constants, or better accept a line of any size - here again it is not simple because you will have to malloc and free at appropriate places, and again would be a different question
Anyway good luck in learning that good old C :-)
This line does not seems right to me
param[j] = buffer;
because you keep assigning the same value buffer to different param[j] s .
I would suggest you copy all the char s from line[120] to buffer[120], then point param[j] to location of buffer + Next_Word_Postition.
You may want to look at strtok in string.h. It sounds like this is what you are looking for, as it will separate words/tokens based on the delimiter you choose. To separate by spaces, simply use:
dest = strtok(src, " ");
Where src is the source string and dest is the destination for the first token on the source string. Looping through until dest == NULL will give you all of the separated words, and all you have to do is change dest each time based on your pointer array. It is also nice to note that passing NULL for the src argument will continue parsing from where strtok left off, so after an initial strtok outside of your loop, just use src = NULL inside. I hope that helps. Good luck!

Resources