wu :: forums
« wu :: forums - Parentheses Matching »

Welcome, Guest. Please Login or Register.
Dec 23rd, 2024, 10:46am

RIDDLES SITE WRITE MATH! Home Home Help Help Search Search Members Members Login Login Register Register
   wu :: forums
   riddles
   cs
(Moderators: Icarus, Grimbal, towr, SMQ, Eigenray, ThudnBlunder, william wu)
   Parentheses Matching
« Previous topic | Next topic »
Pages: 1  Reply Reply Notify of replies Notify of replies Send Topic Send Topic Print Print
   Author  Topic: Parentheses Matching  (Read 7050 times)
Barukh
Uberpuzzler
*****






   


Gender: male
Posts: 2276
Parentheses Matching  
« on: May 25th, 2005, 11:00am »
Quote Quote Modify Modify

You are given a string of open/closed parenetheses of a single type. It's fairly easy to implement the parentheses matching (PM) procedure using a single counter with the set of operations (reset, ++, --).
 
Is it possible to implement PM given 2 different types of parentheses and using 2 counters?
 
What about general case of n different types of parentheses?
IP Logged
VincentLascaux
Guest

Email

Re: Parentheses Matching  
« Reply #1 on: May 25th, 2005, 11:41am »
Quote Quote Modify Modify Remove Remove

Quote:
Is it possible to implement PM given 2 different types of parentheses and using 2 counters?

 
No, if you have [ ( ] ), the basic counter algorithm will return that it's ok when it's not. You need a stack of counters.
 
Quote:
What about general case of n different types of parentheses?

 
Same thing... you need to store the type of parenthesis in the stack.
 
As usual, following code was not tested Smiley
 
hidden:

std::vector< std::pair<int, int> > stack;
 
/* I assume there is a "read parenthesis" function called read that sets these variable */
bool opened;
int type;
 
while(read())
{
  if(stack.empty())
  {
    if(!opened) return false;
    stack.push_back(std::make_pair(type, 1));
  } else {
    if(stack.back().first == type)
    {
 if(opened)  
   ++stack.back().second;
 else if(--stack.back().first == 0)
    stack.pop_back();
    } else {
 if(!opened) return false;
 stack.push_back(std::make_pair(type, 1));
    }
  }
}
return stack.empty();
IP Logged
Deedlit
Senior Riddler
****





   


Posts: 476
Re: Parentheses Matching  
« Reply #2 on: May 25th, 2005, 11:51am »
Quote Quote Modify Modify

Can you describe what the PM procedure is specifically?
IP Logged
Barukh
Uberpuzzler
*****






   


Gender: male
Posts: 2276
Re: Parentheses Matching  
« Reply #3 on: May 26th, 2005, 2:17am »
Quote Quote Modify Modify

on May 25th, 2005, 11:51am, Deedlit wrote:
Can you describe what the PM procedure is specifically?

Parentheses Matching is a standard procedure in parsing the formal languages. Given a sequence of open/closed parentheses of n types (for instance, (), [], {}) PM checks whether the parentheses are properly nested, that is:
 
1. No subsequence has more closed parentheses that open parentheses of a specific type.
 
2.  Any pair of open/closed parentheses of a specific type encloses the same number of open/closed parentheses of any type.
 
3. The whole sequence has the same number of open/closed parentheses of any type.
 
Hope I defined it correctly  Wink
IP Logged
VincentLascaux
Guest

Email

Re: Parentheses Matching  
« Reply #4 on: May 26th, 2005, 6:30am »
Quote Quote Modify Modify Remove Remove

I'd rather define it like that:
empty is correct
If E and F are correct, EF (concatenation) is correct
If E is correct (E), {E}, [E]... are correct
 
In you definition "No subsequence has more closed parentheses than open parentheses of a specific type" looks wrong: ) is a subsequence of () isn't it? Where you speaking of prefixes instead of subsequence?
IP Logged
Deedlit
Senior Riddler
****





   


Posts: 476
Re: Parentheses Matching  
« Reply #5 on: May 26th, 2005, 7:25am »
Quote Quote Modify Modify

I agree that Vincent's makes more sense as an operational definition;  Barukh's characterization should be a theorem to be proven.  (Not hard, with the fix that Vincent mentioned.)  
 
There certainly is an algorithm that only uses two counters for writing;  it turns out that a finite automaton equipped with two counters is a Turing-complete computing model.  That means we can implement the parentheses matching procedure by simply reading the string from left to right, and at each step, we transition between a finite number of states, and possibly increment or decrement the two counters.
 
Of course, I'm sure you're talking about a natural algorithm for implementing the procedure.  This does put the kibosh on actually proving that it is impossible, though, unless you come up with other restrictions.
IP Logged
towr
wu::riddles Moderator
Uberpuzzler
*****



Some people are average, some are just mean.

   


Gender: male
Posts: 13730
Re: Parentheses Matching  
« Reply #6 on: May 26th, 2005, 8:22am »
Quote Quote Modify Modify

If you use a turing machine, you don't need any counters, I think..
Just keep eliminating inner pairs of parenthesis
[()({}{})]
->
[({}{})]
->
[({})]
->
[()]
->
[]
->  
all matched up
 
If however you can only move the tape one way, I'm not sure if it works anymore..
It's not very efficient anyway.
And oh yeah, you're destroying the input, probably not something you want Tongue
« Last Edit: May 26th, 2005, 8:24am by towr » IP Logged

Wikipedia, Google, Mathworld, Integer sequence DB
Deedlit
Senior Riddler
****





   


Posts: 476
Re: Parentheses Matching  
« Reply #7 on: May 26th, 2005, 8:33am »
Quote Quote Modify Modify

Good point! Yes, it does work just going one way.  Why do you say it isn't very efficient?  It's O(n), without a large constant I think.
 
If you don't want to destroy the input, just write the each left parenthesis as you encounter it; for each right parenthesis, erase the last parenthesis if it matches, otherwise return false.  This is what I assumed vincent wrote, although I haven't checked his code.
 
As far as using a counter goes, you can of course implement a stack as a counter in base-b notation.  This requires multiplication by a constant;  if you wish to disallow that explicitly, a second counter will let you implement it with just incrementing.  But the "idea behind it" is a stack.
« Last Edit: May 26th, 2005, 8:39am by Deedlit » IP Logged
Grimbal
wu::riddles Moderator
Uberpuzzler
*****






   


Gender: male
Posts: 7527
Re: Parentheses Matching  
« Reply #8 on: May 26th, 2005, 9:41am »
Quote Quote Modify Modify

It could be simpler if you could save some temporary variables.  Here, the original string and 2 variables i and j are all I am using.
 
 
<script language="javaScript">
 
function get(name)
{
 if( document.all )
  return document.all[name];
 else
  return document.getElementById(name);
}
 
function leftpar(ch){
 return ch=='(' || ch=='[' || ch=='{';
}
 
function rightpar(ch){
 return ch==')' || ch==']' || ch=='}';
}
 
function findMatch(str, i){
 var j;
 if( leftpar(str.charAt(i)) ){
  j = 0;
  while( i<str.length ){
   if( leftpar(str.charAt(i)) ) j++;
   if( rightpar(str.charAt(i)) ) j--;
   if( j==0 ) break;
   i++;
  }
 } else
 if( rightpar(str.charAt(i)) ){
  j = 0;
  while( i>=0 ){
   if( leftpar(str.charAt(i)) ) j++;
   if( rightpar(str.charAt(i)) ) j--;
   if( j==0 ) break;
   i--;
  }
 }
 return i;
}
 
function testValid(str){
 var i;
 i = 0;
 while( i<str.length ){
  if( str.charAt(i)=='(' ){
   i = findMatch(str,i);
   if( i<0 || i>str.length || str.charAt(i)!=')' )
    return false;
   i = findMatch(str,i);
  }
  if( str.charAt(i)=='[' ){
   i = findMatch(str,i);
   if( i<0 || i>str.length || str.charAt(i)!=']' )
    return false;
   i = findMatch(str,i);
  }
  if( str.charAt(i)=='{' ){
   i = findMatch(str,i);
   if( i<0 || i>str.length || str.charAt(i)!='}' )
    return false;
   i = findMatch(str,i);
  }
  if( str.charAt(i)==')' ){
   i = findMatch(str,i);
   if( i<0 || i>str.length || str.charAt(i)!='(' )
    return false;
   i = findMatch(str,i);
  }
  if( str.charAt(i)==']' ){
   i = findMatch(str,i);
   if( i<0 || i>str.length || str.charAt(i)!='[' )
    return false;
   i = findMatch(str,i);
  }
  if( str.charAt(i)=='}' ){
   i = findMatch(str,i);
   if( i<0 || i>str.length || str.charAt(i)!='{' )
    return false;
   i = findMatch(str,i);
  }
  i++;
 }
 return true;
}
 
function check()
{
 var exp = get("exp").value;
 if( testValid(exp) ){
  get("reply").value = "Expression is valid";
 } else {
  get("reply").value = "Expression is NOT valid";
 }
}
</script>
« Last Edit: May 26th, 2005, 9:43am by Grimbal » IP Logged
Barukh
Uberpuzzler
*****






   


Gender: male
Posts: 2276
Re: Parentheses Matching  
« Reply #9 on: May 26th, 2005, 9:41am »
Quote Quote Modify Modify

on May 26th, 2005, 6:30am, VincentLascaux wrote:
I'd rather define it like that:
empty is correct
If E and F are correct, EF (concatenation) is correct
If E is correct (E), {E}, [E]... are correct

Yes, this is much better!
 
Quote:
In you definition "No subsequence has more closed parentheses than open parentheses of a specific type" looks wrong: ) is a subsequence of () isn't it? Where you speaking of prefixes instead of subsequence?

Yes. I am kind of fuzzy these days.
IP Logged
Grimbal
wu::riddles Moderator
Uberpuzzler
*****






   


Gender: male
Posts: 7527
Re: Parentheses Matching  
« Reply #10 on: May 26th, 2005, 9:58am »
Quote Quote Modify Modify

PS: the idea is to find for each parenthesis the matching one (counting just lefts and rights) and to see if the type matches.  Test the code at
http://www.florian.net/puzzle/parens.html
« Last Edit: May 26th, 2005, 10:01am by Grimbal » IP Logged
towr
wu::riddles Moderator
Uberpuzzler
*****



Some people are average, some are just mean.

   


Gender: male
Posts: 13730
Re: Parentheses Matching  
« Reply #11 on: May 26th, 2005, 12:29pm »
Quote Quote Modify Modify

on May 26th, 2005, 8:33am, Deedlit wrote:
Good point! Yes, it does work just going one way.  Why do you say it isn't very efficient?  It's O(n), without a large constant I think.
Well, the way I described it, for a turing machine, as I understand it, it's o(n^2), because you keep moving the tape back and forwards.
Of course if you have random access memory, then it could be O(n); as long as you don't have to search to and fro each time. Which requires at least two pointers. (Which are just as 'bad' as counters)
 
It really just depends on how you look at it..
IP Logged

Wikipedia, Google, Mathworld, Integer sequence DB
Grimbal
wu::riddles Moderator
Uberpuzzler
*****






   


Gender: male
Posts: 7527
Re: Parentheses Matching  
« Reply #12 on: May 27th, 2005, 8:04am »
Quote Quote Modify Modify

Tonight I realized that the single parentheses problem can be solved with a single counter plus an index to scan the string.
My solution also uses a single index and a single counter.  So I am over target.   Cool
IP Logged
TenaliRaman
Uberpuzzler
*****



I am no special. I am only passionately curious.

   


Gender: male
Posts: 1001
Re: Parentheses Matching  
« Reply #13 on: May 27th, 2005, 9:52am »
Quote Quote Modify Modify

I am not sure if this is of any relevance to the current discussion. Just thought it would add something to the discussion.
 
I had written the following code for a module i was working on. This one is a bit incomplete, in the sense, it wont take mixture of expression and brackets as inputs. However, completing it wont take much time.  
 
Code:

#include<stdio.h>
#include<string.h>
int parantheses[256];
void set_parantheses(char *par)
{
    for(int i=0;i<256;i++)
   parantheses[i]=0;
    int len = strlen(par);
    int count = 1;
    for(i=0;i<len;i++)
    {
   if(i%2 == 0)
  parantheses[par[i]]=count;
   else
   {
  parantheses[par[i]]=-count;
  count++;
   }
    }
}
int parantheses_check(char c,char *a)
{
    static int next=0;
    static int flag=1;
    static char startsymbol=c;
    while(a[next]!='\0')
    {
   if(parantheses[a[next]]>0)
  flag = parantheses_check(a[next++],a);
   if(parantheses[a[next]]<0)  
   {
  if(parantheses[c] == -parantheses[a[next]])
      next++;
  else
      flag=0;
  return flag;
  }
   }
   if(c != startsymbol)
  flag = 0;
   return flag;
}
int main()
{
    char par[] = "(){}[]";
    set_parantheses(par);
    char test[]="[({({})})]";
    if(parantheses_check('0',test))
   printf("Correct");
    else
   printf("Error");
    return 0;
}

 
-- AI
« Last Edit: May 27th, 2005, 9:56am by TenaliRaman » IP Logged

Self discovery comes when a man measures himself against an obstacle - Antoine de Saint Exupery
Pages: 1  Reply Reply Notify of replies Notify of replies Send Topic Send Topic Print Print

« Previous topic | Next topic »

Powered by YaBB 1 Gold - SP 1.4!
Forum software copyright © 2000-2004 Yet another Bulletin Board