Skip to content

Instantly share code, notes, and snippets.

@chaws
Last active July 2, 2016 13:51
Show Gist options
  • Save chaws/1f3063360b96fba8c676afe7e955b1a4 to your computer and use it in GitHub Desktop.
Save chaws/1f3063360b96fba8c676afe7e955b1a4 to your computer and use it in GitHub Desktop.
// This was based on problem 1077: infix to postfix form
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PRI(c) (c == '*' ? 1 : (c == '(' ? -1 : 0))
#define push iStack++, opStack[iStack].c = infix[i], opStack[iStack].pri = PRI(infix[i])
// Encapsulate an element
typedef struct
{
char el[300];
int sel;
} elem;
typedef struct
{
char c;
char pri;
} op;
void print(char * e, int s)
{
int i = 0;
for(; i < s; i++) printf("%c", e[i]);
printf("\n");
}
// Add two sets
int sum(char * out, elem * elstack)
{
char *el1, *el2;
int sel1, sel2;
el2 = elstack->el;
sel2 = elstack->sel;
//printf("sum) working with el2: "); print(el2, sel2); // DEBUG1
elstack--;
el1 = elstack->el;
sel1 = elstack->sel;
//printf("sum) working with el1: "); print(el1, sel1); // DEBUG1
// If el1 is zero, just copy el2
if(sel1 == 0)
{
strncpy(out, el2, sel2);
return sel2;
}
// Otherwise, if el2 is zero, just copy el1
else if(sel2 == 0)
{
strncpy(out, el1, sel1);
return sel1;
}
int written = 0;
if(sel1 > sel2)
{
// el1 is guiding
while(sel1--)
{
// Put the smallest char first
if(*el1 < *el2)
*out = *el1, el1++;
else if(*el1 > *el2)
*out = *el2, el2++, sel2--, sel1++;
else
*out = *el1, el1++, el2++, sel2--;
//printf("sum1) writting '%c'\n", *out); // DEBUG1
written++;
out++;
// If el2 is done, just copy the rest of el1
if(!sel2)
{
strncpy(out, el1, sel1);
//printf("sum1) finish writting :"); print(out, sel1); // DEBUG1
return written + sel1;
}
}
// If el2's still kicking, just copy the rest of el2
if(sel2)
{
strncpy(out, el2, sel2);
//printf("sum1) finish writting 2 :"); print(out, sel2); // DEBUG1
return written + sel2;
}
}
else
{
// el2 is guiding
while(sel2--)
{
// Put the smallest char first
if(*el2 < *el1)
*out = *el2, el2++;
else if(*el2 > *el1)
*out = *el1, el1++, sel1--, sel2++;
else
*out = *el2, el2++, el1++, sel1--;
//printf("sum2) writting '%c'\n", *out); // DEBUG1
written++;
out++;
// If el1 is done, just copy the rest of el2
if(!sel1)
{
strncpy(out, el2, sel2);
//printf("sum2) finish writting :"); print(out, sel2); // DEBUG1
return written + sel2;
}
}
// If el2's still kicking, just copy the rest of el2
if(sel1)
{
strncpy(out, el1, sel1);
//printf("sum1) finish writting 2 :"); print(out, sel1); // DEBUG1
return written + sel1;
}
}
return written;
}
// Remove all el2 that is present in el1
int sub(char * out, elem * elstack)
{
char *el1, *el2;
int sel1, sel2;
el2 = elstack->el;
sel2 = elstack->sel;
//printf("sub) working with el2: "); print(el2, sel2); // DEBUG1
elstack--;
el1 = elstack->el;
sel1 = elstack->sel;
//printf("sub) working with el1: "); print(el1, sel1); // DEBUG1
// If el1 is zero, return empty set
if(sel1 == 0)
{
*out = 0;
return 0;
}
// Otherwise, if el2 is zero, just copy el1
else if(sel2 == 0)
{
strncpy(out, el1, sel1);
return sel1;
}
int written = 0, iel1, iel2;
for(iel2 = 0; iel2 < sel2; iel2++)
{
//printf("sub = %c\n", *el2); // DEBUG1
while(sel1 && *el1 < *el2)
{
*out = *el1;
//printf("sub2) writting '%c'\n", *out); // DEBUG1
out++;
written++;
el1++;
sel1--;
}
el2++;
el1++;
sel1--;
}
// Finish copying el1
if(sel1 > 0)
{
strncpy(out, el1, sel1);
//printf("sub) finish writting :"); print(out, sel1); // DEBUG1
return written + sel1;
}
return written;
}
// Intersection between el1 and el2
int mul(char * out, elem * elstack)
{
char *el1, *el2;
int sel1, sel2;
el2 = elstack->el;
sel2 = elstack->sel;
//printf("mul) working with el2: "); print(el2, sel2); // DEBUG1
elstack--;
el1 = elstack->el;
sel1 = elstack->sel;
//printf("mul) working with el1: "); print(el1, sel1); // DEBUG1
// if either el1 or el2 are empty, intersection should also be empty
if(sel1 == 0 || sel2 == 0)
{
*out = 0;
return 0;
}
int written = 0, iel1, iel2;
for(iel2 = 0; sel1 && iel2 < sel2; iel2++, el2++)
{
//printf("mul = %c\n", *el2); // DEBUG1
while(sel1 && *el1 < *el2) el1++, sel1--;
if(*el1 == *el2)
{
*out = *el2;
//printf("mul1) writting '%c'\n", *out); // DEBUG1
out++;
written++;
el1++, sel1--;
}
}
return written;
}
void process(char * postfix)
{
char *el;
int sel;
elem *pelstask, elstack[300];
pelstask = elstack;
// Process postfix string
while(*postfix != '\0')
{
char result[300] = {0};
// Add el to elstack
if(*postfix == '{')
{
// Grow stack
pelstask++;
// Get el
postfix++, el = postfix; // { + 1
sel = 0;
while(*postfix != '}') sel++, postfix++;
strncpy(pelstask->el, el, sel);
pelstask->sel = sel;
//printf("p) pushing to stack: sel = %d, el = ", sel); print(pelstask->el, pelstask->sel); // DEBUG1
}
// It's an operator, evaluate it
else
{
//printf("Processing operator '%c'\n", *postfix); // DEBUG1
switch(*postfix)
{
case '+': sel = sum(result, pelstask); break;
case '-': sel = sub(result, pelstask); break;
case '*': sel = mul(result, pelstask); break;
}
//printf("result = '%s'\n", result); // DEBUG1
// Pop the stack and rewrite the stack - 1th position
pelstask--;
strncpy(pelstask->el, result, sel);
pelstask->sel = sel;
//printf("Saving the result to the stack "); print(result, sel); // DEBUG1
}
postfix++;
}
pelstask->el[pelstask->sel] = '\0';
printf("{%s}\n", pelstask->el);
}
int chrcmp(const void * c1, const void * c2)
{
return *(char *)c1 - *(char *)c2;
}
int main(void)
{
int iPost, iStack, cread, i, pri, start_sort, end_sort;
char infix[301] = {0};
while(scanf("%s%n", infix, &cread) != EOF)
{
char postfix[301] = {0};
op opStack[301];
iPost = iStack = 0;
//printf("Read = %s: ", infix); // DEBUG1
cread--;
for(i = 0; i < cread; i++)
{
if(infix[i] == '{')
{
// Save {...}
start_sort = iPost + 1;
while(infix[i] != '}')
postfix[iPost++] = infix[i], i++;
end_sort = iPost - 1;
postfix[iPost++] = infix[i]; // }
// make sure the letters are sorted
//printf("end_sort= %d, start_sort = %d\n", end_sort, start_sort);
if(end_sort - start_sort > 0)
{
//printf("sorting '%c' to '%c'\n", *(postfix + start_sort), *(postfix + end_sort + 1));
qsort(postfix + start_sort, end_sort - start_sort + 1, sizeof(char), chrcmp);
}
// printf("Found1 %c, postfix = %s\n", infix[i], postfix); printStack(opStack, iStack);
}
else if(infix[i] == '(')
{
push;
// printf("Found2 %c, postfix = %s\n", infix[i], postfix); printStack(opStack, iStack);
}
else if(infix[i] == '+' || infix[i] == '-' || infix[i] == '*')
{
LOOP:
if(iStack == 0) // empty?
{
push;
// printf("Found3 %c, postfix = %s\n", infix[i], postfix); printStack(opStack, iStack);
}
else
{
// Check stack's top pri
pri = PRI(infix[i]) - opStack[iStack].pri;
if(pri > 0)
{
// Just push
push;
// printf("Found4 %c, postfix = %s\n", infix[i], postfix); printStack(opStack, iStack);
}
else
{
// Print top of stack
postfix[iPost++] = opStack[iStack--].c;
// printf("Found5 %c, postfix = %s\n", infix[i], postfix); printStack(opStack, iStack+1);
// Next pos in stack
goto LOOP;
}
}
}
else // Can only be ')'
{
// Go through stack until '('
while(iStack > 0 && opStack[iStack].c != '(')
{
postfix[iPost++] = opStack[iStack--].c;
// printf("Found6 %c, postfix = %s\n", infix[i], postfix); printStack(opStack, iStack+1);
}
iStack--; // Remove '('
}
}
// Clean the stack
while(iStack > 0)
{
postfix[iPost++] = opStack[iStack--].c;
// printf("Found6 postfix = %s\n", postfix); printStack(opStack, iStack+1);
}
postfix[iPost] = '\0';
//printf("before %s\n", postfix); // DEBUG1
process(postfix);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment