How Can I convert infix expression containing ++ or -- to a normal infix expression - expression

Basically, I'm trying to get rid of ++ or -- from an infix expression by incrementing the value that's applied to it, but the code gives a weird output. I also used a shifting function to delete the ++ or --.
for example:
-infix before: 1++-4/5
-infix after: 2-4/5
-my program outputs: ,-4/5/5
Here's my code(contains only functions relevant to the problem):
void shift(int i, int j, char expression[])
{
for (int k = i + 1; k < strlen(expression); k++)
{
expression[j++] = expression[k];
}
}
void unary_to_normal(char expression[])
{
int j = 0;
for (int i = 1; i < strlen(expression); i++)
{
// for ++
if (expression[j] == expression[i] && expression[j] == '+')
{ //char to int
int integer = (expression[j] - '0') + 1;
//int to char
expression[j - 1] = integer + '0';
shift(i, j, expression);
}
// for --
if (expression[j] == expression[i] && expression[j] == '-')
{ //converting char to int
int integer = (expression[j] - '0') + 1;
//int to char
expression[j - 1] = integer + '0';
shift(i, j, expression);
}
j++;
}
}

I get the general idea but I'm not sure I completely understand what's going on in your code. From what you posted I believe I see a few issues:
major: if code blocks
In the code inside the if blocks:
int integer = (expression[j] - '0') + 1;
//int to char
expression[j - 1] = integer + '0';
shift(i, j, expression);
For that code to be reached, expression[j] should be '+' or '-'. What exactly are you trying to achieve with the integer declaration? That'll result in either -4 or -2 (ascii table). In turn, the operand over which it was acting (expression[j - 1]) will be converted into , (44 integer) or . (46 integer).
Based on your initial example (1++-4/5) I'd expect you wanted to do something like the following instead:
expression[j - 1]++;
shift(i, j, expression);
Mind there'll still be pitfalls with that code. It won't cover the "overflow" from 9 to 10.
Given the initial code I'm assuming you were ok with that. If that's not the case you'll need to solve for these issues as well.
major: for -- adding instead of subtracting
In the for -- if block you should be subtracting 1 instead of adding. Considering the previous item it should be something like:
expression[j - 1]--;
shift(i, j, expression);
Mind the "underflow" in case the -- operand is 0 (or any number that ends in 0) won't be covered.
major: shift function loop
The strlen function returns the number of characters in a null-terminated string. It doesn't include the null-terminator itself. That's why you're getting the /5/5 repetition at the end of the final string.
One way of fixing it would be making the for loop run until k <= strlen(expression). That way you'd be copying the null-terminator as well.
unsure: -- and ++ operators logic
This might not be an issue to the logic you're trying to implement but there's a very important difference to where these operators are located in C. If they prepend the operand (e.g. ++x), the operator is first applied and, only after that, the expression is evaluated. The order is reversed if the operator is inserted after the operand (e.g. x++).
For instance, the following expressions evaluate to different values:
int x = 1; x++-4;, in C, will result in -3
int x = 1; ++x-4;, in C, will result in -2
If that's irrelevant to your expression parser you can safely ignore this section.
minor: micro-optimizing the for loop in the unary_to_normal function
Instead of handling the j variable manually you can manage it in the for loop alongside i. The following is perfectly valid:
for (int i = 1, j = 0; i < strlen(expression); i++, j++)
Unless you have a reason not to increase j in every loop iteration you should consider having the for loop handle it instead of doing it manually. That's less likely to lead to errors and it makes your intention clearer to other readers.
A working version (considering the caveats that were previously mentioned) would look something like the following:
void shift(int i, int j, char expression[])
{
for (int k = i + 1; k <= strlen(expression); k++)
{
expression[j++] = expression[k];
}
}
void unary_to_normal(char expression[])
{
for (int i = 1, j = 0; i < strlen(expression); i++, j++)
{
// for ++
if (expression[j] == expression[i] && expression[j] == '+')
{
expression[j - 1]++;
shift(i, j, expression);
}
// for --
if (expression[j] == expression[i] && expression[j] == '-')
{
expression[j - 1]--;
shift(i, j, expression);
}
}
}
For these functions, an input expression 1++-4/5 is converted to 2-4/5. 1---4/5 is converted to 0-4/5.

Related

Trouble understanding a part of an algorithm

The problem is to find special strings
A string is said to be a special string if either of two conditions is met:
All of the characters are the same, e.g. aaa.
All characters except the middle one are the same, e.g. aadaa.
This is the code I got and I understand the two cases.
Case 1: All Palindromic substrings have the same character
Case 2:Count all odd length Special Palindromic substrings with the
the middle character is different.
What I cannot understand is why I have to delete n from the result, I don't see where I am adding the extra 'n' in the algorithm.
int CountSpecialPalindrome(string str)
{
int n = str.length();
int result = 0;
int sameChar[n] = { 0 };
int i = 0;
// traverse string character from left to right
while (i < n) {
// store same character count
int sameCharCount = 1;
int j = i + 1;
// count smiler character
while (str[i] == str[j] && j < n)
sameCharCount++, j++;
// Case : 1
// so total number of substring that we can
// generate are : K *( K + 1 ) / 2
// here K is sameCharCount
result += (sameCharCount * (sameCharCount + 1) / 2);
// store current same char count in sameChar[]
// array
sameChar[i] = sameCharCount;
// increment i
i = j;
}
// Case 2: Count all odd length Special Palindromic
// substring
for (int j = 1; j < n; j++)
{
// if current character is equal to previous
// one then we assign Previous same character
// count to current one
if (str[j] == str[j - 1])
sameChar[j] = sameChar[j - 1];
// case 2: odd length
if (j > 0 && j < (n - 1) &&
(str[j - 1] == str[j + 1] &&
str[j] != str[j - 1]))
result += min(sameChar[j - 1],
sameChar[j + 1]);
}
// subtract all single length substring
return result - n;
}
// driver program to test above fun
int main()
{
string str = "abccba";
cout << CountSpecialPalindrome(str) << endl;
return 0;
}

Time limit exceeded in my code given below

Question:
Lapindrome is defined as a string which when split in the middle, gives two halves having the same characters and same frequency of each character. If there are odd number of characters in the string, we ignore the middle character and check for lapindrome. For example gaga is a lapindrome, since the two halves ga and ga have the same characters with same frequency. Also, abccab, rotor and xyzxy are a few examples of lapindromes. Note that abbaab is NOT a lapindrome. The two halves contain the same characters but their frequencies do not match.
Your task is simple. Given a string, you need to tell if it is a lapindrome.
Input:
First line of input contains a single integer T, the number of test cases.
Each test is a single line containing a string S composed of only lowercase English alphabet.
Output:
For each test case, output on a separate line: "YES" if the string is a lapindrome and "NO" if it is not.
Constraints:
1 ≤ T ≤ 100
2 ≤ |S| ≤ 1000, where |S| denotes the length of S
#include <stdio.h>
#include <string.h>
int found;
int lsearch(char a[], int l, int h, char p) {
int i = l;
for (i = l; i <= h; i++) {
if (a[i] == p) {
found = 0;
return i;
}
}
return -1;
}
int main() {
char s[100];
int q, z, i, T;
scanf("%d", &T);
while (T--) {
q = 0;
scanf("%s", &s);
if (strlen(s) % 2 == 0)
for (i = 0; i < (strlen(s) / 2); i++) {
z = lsearch(s, strlen(s) / 2, strlen(s) - 1, s[i]);
if (found == 0) {
found = -1;
s[z] = -2;
} else
q = 1;
} else
for (i = 0; i < (strlen(s) / 2); i++) {
z = lsearch(s, 1 + (strlen(s) / 2), strlen(s) - 1, s[i]);
if (found == 0) {
found = -1;
s[z] = -2;
} else
q = 1;
}
if (strlen(s) % 2 == 0)
for (i = (strlen(s) / 2); i < strlen(s); i++) {
if (s[i] != -2)
q = 1;
} else
for (i = (strlen(s) / 2) + 1; i < strlen(s); i++) {
if (s[i] != -2)
q = 1;
}
if (q == 1)
printf("NO\n");
else
printf("YES\n");
}
}
I am getting correct output in codeblocks but the codechef compiler says time limit exceeded. Please tell me why it says so
For each of O(n) characters you do a O(n) search leading to a O(n^2) algorithm. Throw a thousand character string at it, and it is too slow.
This is solvable in two standard ways. The first is to sort each half of the string and then compare. The second is to create hash tables for letter frequency and then compare.

How do I obtain string subsequence indices after counting number of subsequences?

Given the following algorithm to count the number of times a string appears as a subsequence of another and give me the final number, how would I implement a routine to give me the indices of the strings. eg if there are 4 string appearing as a subsequence of another how would I find the indices of each string?
[1][4][9] the first string
From my own attempts to solve the problem there is a pattern on the dp lookup table which I see visually but struggle to implement in code, how would I add a backtracking that would give me the indices of each string subsequence as it appears. In the example I know the number of times the string will appear as a subsequence but I want to know the string indices of each subsequence appearance, as stated I can determine this visually when I look at the lookup table values but struggle to code it? I know the solution lies in the backtracking the tabular lookup container
int count(string a, string b)
{
int m = a.length();
int n = b.length();
int lookup[m + 1][n + 1] = { { 0 } };
// If first string is empty
for (int i = 0; i <= n; ++i)
lookup[0][i] = 0;
// If second string is empty
for (int i = 0; i <= m; ++i)
lookup[i][0] = 1;
// Fill lookup[][] in bottom up
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
// we have two options
//
// 1. consider last characters of both strings
// in solution
// 2. ignore last character of first string
if (a[i - 1] == b[j - 1])
lookup[i][j] = lookup[i - 1][j - 1] +
lookup[i - 1][j];
else
// If last character are different, ignore
// last character of first string
lookup[i][j] = lookup[i - 1][j];
}
}
return lookup[m][n];
}
int main(void){
string a = "ccaccbbbaccccca";
string b = "abc";
cout << count(a, b);
return 0;
}
You can do it recursively (essentially you'll just be doing the same thing in another direction):
def gen(i, j):
// If there's no match, we're done
if lookup[i][j] == 0:
return []
// If one of the indices is 0, the answer is an empty list
// which means an empty sequence
if i == 0 or j == 0:
return [[]]
// Otherwise, we just do all transitions backwards
// combine the results
res = []
if a[i - 1] == b[j - 1]:
res = gen(i - 1, j - 1)
for elem in res:
elem.append(a[i - 1])
return res + gen(i - 1, j)
The idea is to do exactly the same thing we use to compute the answer, but to return a list of indices instead of the number of ways.
I haven't tested the code above, so it may contain minor bugs, but I think the idea is clear.

Nested Loops in C programming

I was wondering how the line "if(!(i%j)) break;" in the code below would be interpreted. Since the "!" symbol is an inverter, does it mean that the bold line in the code below would interpret to saying that "if i mod j is equal to zero, invert and then break out of the loop"
Many thanks
int main ()
{
/* local variable definition */
int i, j;
for (i = 2; i < 100; i++) {
for (j = 2; j <= (i / j); j++)
if (!(i % j))
break;
if (j > (i / j)) printf("%d is prime\n", i);
}
return 0;
}
"if i mod j is equal to zero, invert and then break out of the loop"
Close: if i mod j equals zero then break.
if ( ! (i % j) ) break;
In C, 0 is false and anything else is true. So, when i % j is 0, ! (i % j) is 1, and thus true.
In C, an if (number) always evaluates to true, unless the number is 0. Therefore, that would evaluate to: if i mod j is equal to 0, basically, if i is a multiple of j.

Algorithms: Interesting diffing algorithm

This came up in a real-world situation, and I thought I would share it, as it could lead to some interesting solutions. Essentially, the algorithm needs to diff two lists, but let me give you a more rigorous definition of the problem.
Mathematical Formulation
Suppose you have two lists, L and R each of which contain elements from some underlying alphabet S. Moreover, these lists have the property that the common elements that they have appear in order: that is to say, if L[i] = R[i*] and L[j] = R[j*], and i < j then i* < j*. The lists need not have any common elements at all, and one or both may be empty. [Clarification: You may assume no repetitions of elements.]
The problem is to produce a sort of "diff" of the lists, which may be viewed as new list of ordered pairs (x,y) where x is from L and y is from R, with the following properties:
If x appears in both lists, then (x,x) appears in the result.
If x appears in L, but not in R, then (x,NULL) appears in the result.
If y appears in R, but not in L, then (NULL,y) appears in the result.
and finally
The result list has "the same" ordering as each of the input lists: it shares, roughly speaking, the same ordering property as above with each of the lists individually (see example).
Examples
L = (d)
R = (a,b,c)
Result = ((NULL,d), (a,NULL), (b,NULL), (c,NULL))
L = (a,b,c,d,e)
R = (b,q,c,d,g,e)
Result = ((a,NULL), (b,b), (NULL,q), (c,c), (d,d), (NULL,g), (e,e))
Does anyone have any good algorithms to solve this? What is the complexity?
There is a way to do this in O(n), if you're willing to make a copy of one of the lists in a different data structure. This is a classic time/space tradeoff.
Create a hash map of the list R, with the key being the element and the value being the original index into the array; in C++, you could use unordered_map from tr1 or boost.
Keep an index to the unprocessed portion of list R, initialized to the first element.
For each element in list L, check the hash map for a match in list R. If you do not find one, output (L value, NULL). If there is a match, get the corresponding index from the hash map. For each unprocessed element in list R up to the matching index, output (NULL, R value). For the match, output (value, value).
When you have reached the end of list L, go through the remaining elements of list R and output (NULL, R value).
Edit: Here is the solution in Python. To those who say this solution depends on the existence of a good hashing function - of course it does. The original poster may add additional constraints to the question if this is a problem, but I will take an optimistic stance until then.
def FindMatches(listL, listR):
result=[]
lookupR={}
for i in range(0, len(listR)):
lookupR[listR[i]] = i
unprocessedR = 0
for left in listL:
if left in lookupR:
for right in listR[unprocessedR:lookupR[left]]:
result.append((None,right))
result.append((left,left))
unprocessedR = lookupR[left] + 1
else:
result.append((left,None))
for right in listR[unprocessedR:]:
result.append((None,right))
return result
>>> FindMatches(('d'),('a','b','c'))
[('d', None), (None, 'a'), (None, 'b'), (None, 'c')]
>>> FindMatches(('a','b','c','d','e'),('b','q','c','d','g','e'))
[('a', None), ('b', 'b'), (None, 'q'), ('c', 'c'), ('d', 'd'), (None, 'g'), ('e','e')]
The worst case, as defined and using only equality, must be O(n*m). Consider the following two lists:
A[] = {a,b,c,d,e,f,g}
B[] = {h,i,j,k,l,m,n}
Assume there exists exactly one match between those two "ordered" lists. It will take O(n*m) comparisons since there does not exist a comparison which removes the need for other comparisons later.
So, any algorithm you come up with is going to be O(n*m), or worse.
Diffing ordered lists can be done in linear time by traversing both lists and matching as you go. I will try to post some psuedo Java code in an update.
Since we don't know the ordering algorithm and can't determine any ordering based on less than or greater than operators, we must consider the lists unordered. Also, given how the results are to be formatted you are faced with scanning both lists (at least until you find a match and then you can bookmark and start from there again). It will still be O(n^2) performance, or yes more specifically O(nm).
This is exactly like sequence alignment, you can use the Needleman-Wunsch algorithm to solve it. The link includes the code in Python. Just make sure you set the scoring so that a mismatch is negative and a match is positive and an alignment with a blank is 0 when maximizing. The algorithm runs in O(n * m) time and space, but the space complexity of this can be improved.
Scoring Function
int score(char x, char y){
if ((x == ' ') || (y == ' ')){
return 0;
}
else if (x != y){
return -1;
}
else if (x == y){
return 1;
}
else{
puts("Error!");
exit(2);
}
}
Code
#include <stdio.h>
#include <stdbool.h>
int max(int a, int b, int c){
bool ab, ac, bc;
ab = (a > b);
ac = (a > c);
bc = (b > c);
if (ab && ac){
return a;
}
if (!ab && bc){
return b;
}
if (!ac && !bc){
return c;
}
}
int score(char x, char y){
if ((x == ' ') || (y == ' ')){
return 0;
}
else if (x != y){
return -1;
}
else if (x == y){
return 1;
}
else{
puts("Error!");
exit(2);
}
}
void print_table(int **table, char str1[], char str2[]){
unsigned int i, j, len1, len2;
len1 = strlen(str1) + 1;
len2 = strlen(str2) + 1;
for (j = 0; j < len2; j++){
if (j != 0){
printf("%3c", str2[j - 1]);
}
else{
printf("%3c%3c", ' ', ' ');
}
}
putchar('\n');
for (i = 0; i < len1; i++){
if (i != 0){
printf("%3c", str1[i - 1]);
}
else{
printf("%3c", ' ');
}
for (j = 0; j < len2; j++){
printf("%3d", table[i][j]);
}
putchar('\n');
}
}
int **optimal_global_alignment_table(char str1[], char str2[]){
unsigned int len1, len2, i, j;
int **table;
len1 = strlen(str1) + 1;
len2 = strlen(str2) + 1;
table = malloc(sizeof(int*) * len1);
for (i = 0; i < len1; i++){
table[i] = calloc(len2, sizeof(int));
}
for (i = 0; i < len1; i++){
table[i][0] += i * score(str1[i], ' ');
}
for (j = 0; j < len1; j++){
table[0][j] += j * score(str1[j], ' ');
}
for (i = 1; i < len1; i++){
for (j = 1; j < len2; j++){
table[i][j] = max(
table[i - 1][j - 1] + score(str1[i - 1], str2[j - 1]),
table[i - 1][j] + score(str1[i - 1], ' '),
table[i][j - 1] + score(' ', str2[j - 1])
);
}
}
return table;
}
void prefix_char(char ch, char str[]){
int i;
for (i = strlen(str); i >= 0; i--){
str[i+1] = str[i];
}
str[0] = ch;
}
void optimal_global_alignment(int **table, char str1[], char str2[]){
unsigned int i, j;
char *align1, *align2;
i = strlen(str1);
j = strlen(str2);
align1 = malloc(sizeof(char) * (i * j));
align2 = malloc(sizeof(char) * (i * j));
align1[0] = align2[0] = '\0';
while((i > 0) && (j > 0)){
if (table[i][j] == (table[i - 1][j - 1] + score(str1[i - 1], str2[j - 1]))){
prefix_char(str1[i - 1], align1);
prefix_char(str2[j - 1], align2);
i--;
j--;
}
else if (table[i][j] == (table[i - 1][j] + score(str1[i-1], ' '))){
prefix_char(str1[i - 1], align1);
prefix_char('_', align2);
i--;
}
else if (table[i][j] == (table[i][j - 1] + score(' ', str2[j - 1]))){
prefix_char('_', align1);
prefix_char(str2[j - 1], align2);
j--;
}
}
while (i > 0){
prefix_char(str1[i - 1], align1);
prefix_char('_', align2);
i--;
}
while(j > 0){
prefix_char('_', align1);
prefix_char(str2[j - 1], align2);
j--;
}
puts(align1);
puts(align2);
}
int main(int argc, char * argv[]){
int **table;
if (argc == 3){
table = optimal_global_alignment_table(argv[1], argv[2]);
print_table(table, argv[1], argv[2]);
optimal_global_alignment(table, argv[1], argv[2]);
}
else{
puts("Reqires to string arguments!");
}
return 0;
}
Sample IO
$ cc dynamic_programming.c && ./a.out aab bba
__aab
bb_a_
$ cc dynamic_programming.c && ./a.out d abc
___d
abc_
$ cc dynamic_programming.c && ./a.out abcde bqcdge
ab_cd_e
_bqcdge
No real tangible answer, only vague intuition. Because you don't know the ordering algorithm, only that the data is ordered in each list, it sounds vaguely like the algorithms used to "diff" files (e.g. in Beyond Compare) and match sequences of lines together. Or also vaguely similar to regexp algorithms.
There can also be multiple solutions. (never mind, not if there are not repeated elements that are strictly ordered. I was thinking too much along the lines of file comparisons)
This is a pretty simple problem since you already have an ordered list.
//this is very rough pseudocode
stack aList;
stack bList;
List resultList;
char aVal;
char bVal;
while(aList.Count > 0 || bList.Count > 0)
{
aVal = aList.Peek; //grab the top item in A
bVal = bList.Peek; //grab the top item in B
if(aVal < bVal || bVal == null)
{
resultList.Add(new Tuple(aList.Pop(), null)));
}
if(bVal < aVal || aVal == null)
{
resultList.Add(new Tuple(null, bList.Pop()));
}
else //equal
{
resultList.Add(new Tuple(aList.Pop(), bList.Pop()));
}
}
Note... this code WILL NOT compile. It is just meant as a guide.
EDIT Based on the OP comments
If the ordering algorithm is not exposed, then the lists must be considered unordered.
If the lists are unordered, then the algorithm has a time complexity of O(n^2), specifically O(nm) where n and m are the number of items in each list.
EDIT
Algorithm to solve this
L(a,b,c,d,e)
R(b,q,c,d,g,e)
//pseudo code... will not compile
//Note, this modifies aList and bList, so make copies.
List aList;
List bList;
List resultList;
var aVal;
var bVal;
while(aList.Count > 0)
{
aVal = aList.Pop();
for(int bIndex = 0; bIndex < bList.Count; bIndex++)
{
bVal = bList.Peek();
if(aVal.RelevantlyEquivalentTo(bVal)
{
//The bList items that come BEFORE the match, are definetly not in aList
for(int tempIndex = 0; tempIndex < bIndex; tempIndex++)
{
resultList.Add(new Tuple(null, bList.Pop()));
}
//This 'popped' item is the same as bVal right now
resultList.Add(new Tuple(aVal, bList.Pop()));
//Set aVal to null so it doesn't get added to resultList again
aVal = null;
//Break because it's guaranteed not to be in the rest of the list
break;
}
}
//No Matches
if(aVal != null)
{
resultList.Add(new Tuple(aVal, null));
}
}
//aList is now empty, and all the items left in bList need to be added to result set
while(bList.Count > 0)
{
resultList.Add(new Tuple(null, bList.Pop()));
}
The result set will be
L(a,b,c,d,e)
R(b,q,c,d,g,e)
Result ((a,null),(b,b),(null,q),(c,c),(d,d),(null,g),(e,e))
I don't think you have enough information. All you've asserted is that elements that match match in the same order, but finding the first matching pair is an O(nm) operation unless you have some other ordering that you can determine.
SELECT distinct l.element, r.element
FROM LeftList l
OUTER JOIN RightList r
ON l.element = r.element
ORDER BY l.id, r.id
Assumes the ID of each element is its ordering. And of course, that your lists are contained in a Relational Database :)

Resources