Implementation Working in Python But Not in C++ - c++

So I made a program that takes in three strings, A, B, and C and determines whether or not C is a merge of A and B. A merge is defined as combination of the letters in A and B such that the ordering of the letters of A and B in relation to one another are preserved. So if A = "ab", B = "ba", and C = "abab", C is a valid merge of A and B since the first and last letters of C can be thought of as "from A" and the middle two from B. This combination of letters preserves their order in A and B and so C is a valid merge.
My program also capitalizes the letters in C that are "from A" meaning it outputs "AbaB".
I'm more comfortable with Python so I wrote out my implementation there first and then translated it to C++. But the really weird thing is that it works perfectly in Python but not in C++. I checked line by line and everything matches up perfectly but it's still giving the wrong output.
So for an example, for the input A == "ab", B = "ba", and C = "abab", my Python implementation correctly outputs "AbaB". But, my C++ implementation outputs "ABba".
The problem only seems to be with this part of the output. The C++ program seems to be able to correctly identify whether or not C is a valid merge of A and B.
Here's my Python program:
def findPath(array, A, B):
output = ""
M = len(A)
N = len(B)
i = M
j = N
while(j > 0):
print(i,j)
if(array[i][j-1]):
output = B[j-1] + output
j -= 1
else:
output = A[i-1].upper() + output
i -= 1
while(i > 0):
output = A[i-1].upper() + output
i -= 1
return output
def isInterleaved(A,B,C):
M = len(A)
N = len(B)
output = ""
array = [[False] * (N + 1) for i in range(M + 1)]
if(M +N != len(C)):
return False
for i in range(M+1):
for j in range(N+1):
if (i== 0 and j == 0):
array[i][j] = True
elif (i == 0):
if (B[j-1] == C[j-1]):
array[i][j] = array[i][j-1]
elif (j == 0):
if (A[i-1] == C[i-1]):
array[i][j] = array[i-1][j]
elif (A[i - 1] == C[i + j - 1] and B[j - 1] != C[i + j - 1]):
array[i][j] = array[i-1][j]
elif (A[i - 1] != C[i + j - 1] and B[j - 1] == C[i + j - 1]):
array[i][j] = array[i][j-1]
elif (A[i - 1] == C[i + j - 1] and B[j - 1] == C[i + j - 1]):
array[i][j] = (array[i - 1][j] or array[i][j - 1])
print(findPath(array, A,B))
return array[M][N]
print(isInterleaved("ab", "ba",
"abab"))
And here's my C++ program:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
bool graph[1001][1001];
bool isInterleaved(string A, string B, string C)
{
int M = A.size();
int N = B.size();
if(M + N != C.size())
{
return false;
}
for (int i = 0; i < M + 1; i++)
{
for(int j = 0; j < N + 1; j++)
{
if (i == 0 and j == 0) { graph[i][j] = true; }
else if(i == 0)
{
if (B[j-1] == C[j-1])
{
graph[i][j] = graph[i][j-1];
}
}
else if(j == 0)
{
if (A[i-1] == C[i-1]) { graph[i][j] = graph[i-1][j];}
}
else if (A[i - 1] == C[i + j - 1] and B[j - 1] != C[i + j - 1])
{
graph[i][j] = graph[i-1][j];
}
else if (A[i - 1] != C[i + j - 1] and B[j - 1] == C[i + j - 1])
{
graph[i][j] = graph[i][j-1];
}
else if (A[i - 1] == C[i + j - 1] and B[j - 1] == C[i + j - 1])
{
graph[i][j] = (graph[i - 1][j] or graph[i][j - 1]);
}
}
}
return graph[M][N];
}
string findPath(string A, string B)
{
string output = "";
int M = A.size();
int N = B.size();
int i = M;
int j = N;
for(int k = 0; k < M; k++)
{
A[k] = toupper(A[k]);
}
while(j > 0)
{
if(graph[i][j-1])
{
output = B[j - 1] + output;
j -= 1;
}
else
{
output = A[i-1]+ output;
i -= 1;
}
}
cout << output << endl;
while(i > 0)
{
output = A[i-1] + output;
i -= 1;
}
return output;
}
int main()
{
string in;
string out;
cout << "Enter the name of input file: ";
cin >> in;
cout << "Enter the name of output file: ";
cin >> out;
ifstream myfile;
myfile.open(in);
ofstream outfile;
outfile.open(out);
string line;
vector<string> arguments;
int count = 0;
while(getline(myfile, line))
{
arguments.push_back(line);
count ++;
if(count == 3)
{
count = 0;
if(isInterleaved(arguments[0], arguments[1], arguments[2]))
{
outfile << findPath(arguments[0], arguments[1]) << "\n";
}
else
{
outfile << "*** NOT A MERGE ***" << "\n";
}
arguments.clear();
}
}
myfile.close();
outfile.close();
return 0;
}
For the C implementation, it takes in a list of test cases so that every block of three lines gives the parameters for a different test case. The first line gives the string A, the second, the string B, and the third, is C. It outputs the results into a text file giving the capitalized-A version of C when it's a valid merge and the string "*** NOT A MERGE ***" when it's not.
Any help with this would be greatly appreciated. I'm pretty sure it has to be something small like a method that's not giving me what I expect it to.

This is not really an answer, but sometimes when things don’t work it’s better to start over from an easily testable MWE. I’d suggest keeping it trivial, without file I/O clutter, focused only on the merger detection and without an arbitrary hard limit of 1000:
#include <iostream>
#include <set>
#include <string_view>
#include <tuple>
int main(int argc, const char *const *argv) {
if (argc != 4) return 3;
const std::string_view a{argv[1]}, b{argv[2]}, c{argv[3]};
const auto report{[a, b, c](bool result) {
std::cout << '\'' << c << "' is " << (result ? "" : "NOT ")
<< "a merger of '" << a << "' and '" << b << "'\n";
}};
std::set<std::tuple<size_t, size_t>> state{{0, 0}};
do {
const auto s{state.begin()};
const auto [pc, pa] = *s;
const size_t pb = pc - pa;
state.erase(s);
if (pc < c.size()) {
if (pa < a.size() && c[pc] == a[pa])
state.emplace_hint(state.end(), pc + 1, pa + 1);
if (pb < b.size() && c[pc] == b[pb])
state.emplace_hint(state.end(), pc + 1, pa);
} else if (pa == a.size() && pb == b.size()) {
report(true);
return 0;
}
} while (!state.empty());
report(false);
return 1;
}
What it does is (indeed) trivial: It records combinations of (position in merger candidate C, position in merger input A [explicit], position in merger input B [implicit]) achieved thus far. Obviously, (0, 0, 0) is a trivially satisfied starting point. Then it keeps trying to advance each already achieved position by one character. Ultimately it either reaches the ends of all of A, B and C at once, at which point C is confirmed to be a merger of A and B, or it exhausts all achieved positions recorded for future consideration, which means that one cannot merge A and B into C in any way.
(Presumably, you need to add an extra piece of data into the state if you want to also report a “merger recipe” together with a positive answer. It could also use an early check whether the string lengths add up.)
Now we can test that a bit (assuming that the binary is called merger):
#!/bin/bash
abc012=(abc012 ab0c12 ab01c2 ab012c a0bc12 a0b1c2 a0b12c a01bc2 a01b2c a012bc
0abc12 0ab1c2 0ab12c 0a1bc2 0a1b2c 0a12bc 01abc2 01ab2c 01a2bc 012abc)
acb012=(acb012 ac0b12 ac01b2 ac012b a0cb12 a0c1b2 a0c12b a01cb2 a01c2b a012cb
0acb12 0ac1b2 0ac12b 0a1cb2 0a1c2b 0a12cb 01acb2 01ac2b 01a2cb 012acb)
for m in "${abc012[#]}"; do
./merger abc 012 "$m" # …is a merger…
done
for m in "${acb012[#]}"; do
./merger abc 012 "$m" # …is NOT a merger…
done

Related

Coursera DSA Algorithmic toolbox week 4 2nd question- Partitioning Souvenirs

Problem Statement-
You and two of your friends have just returned back home after visiting various countries. Now you would
like to evenly split all the souvenirs that all three of you bought.
Problem Description
Input Format- The first line contains an integer ... The second line contains integers v1, v2, . . . ,vn separated by spaces.
Constraints- 1 . .. . 20, 1 . .... . 30 for all ...
Output Format- Output 1, if it possible to partition 𝑣1, 𝑣2, . . . , 𝑣𝑛 into three subsets with equal sums, and
0 otherwise.
What's Wrong with this solution? I am getting wrong answer when I submit(#12/75) I am solving it using Knapsack without repetition taking SUm/3 as my Weight. I back track my solution to replace them with 0. Test cases run correctly on my PC.
Although I did it using OR logic, taking a boolean array but IDK whats wrong with this one??
Example- 11
17 59 34 57 17 23 67 1 18 2 59
(67 34 17)are replaced with 0s. So that they dont interfare in the next sum of elements (18 1 23 17 59). Coz both of them equal to 118(sum/3) Print 1.
#include <iostream>
#include <vector>
using namespace std;
int partition3(vector<int> &w, int W)
{
int N = w.size();
//using DP to find out the sum/3 that acts as the Weight for a Knapsack problem
vector<vector<int>> arr(N + 1, vector<int>(W + 1));
for (int k = 0; k <= 1; k++)
{
//This loop runs twice coz if 2x I get sum/3 then that ensures that left elements will make up sum/3 too
for (int i = 0; i < N + 1; i++)
{
for (int j = 0; j < W + 1; j++)
{
if (i == 0 || j == 0)
arr[i][j] = 0;
else if (w[i - 1] <= j)
{
arr[i][j] = ((arr[i - 1][j] > (arr[i - 1][j - w[i - 1]] + w[i - 1])) ? arr[i - 1][j] : (arr[i - 1][j - w[i - 1]] + w[i - 1]));
}
else
{
arr[i][j] = arr[i - 1][j];
}
}
}
if (arr[N][W] != W)
return 0;
else
{
//backtrack the elements that make the sum/3 and = them to 0 so that they don't contribute to the next //elements that make sum/3
int res = arr[N][W];
int wt = W;
for (int i = N; i > 0 && res > 0; i--)
{
if (res == arr[i - 1][wt])
continue;
else
{
std::cout << w[i - 1] << " ";
res = res - w[i - 1];
wt = wt - w[i - 1];
w[i - 1] = 0;
}
}
}
}
if (arr[N][W] == W)
{
return 1;
}
else
{
return 0;
}
}
int main()
{
int n;
std::cin >> n;
vector<int> A(n);
int sum = 0;
for (size_t i = 0; i < A.size(); ++i)
{
int k;
std::cin >> k;
A[i] = k;
sum += k;
}
if (sum % 3 == 0)
std::cout << partition3(A, sum / 3) << '\n';
else
std::cout << 0;
}
Sum/3 can be achieved by multiple ways!!!! So backtracking might remove a subset that has an element that should have been a part of some other subset
8 1 6 is 15 as well as 8 2 5 makes 15 so better is u check this
if(partition3(A, sum / 3) == sum / 3 && partition3(A, 2 * (sum / 3)) == 2 * sum / 3 && sum == partition3(A, sum))

Sparse matrix compressed on rows in C++

I have to implement the CSR matrix data structure in C++ using 3 dynamic arrays (indexing starts at 0) and I've got stuck. So I have to implement 2 functions:
1) modify(int i, int j, TElem e) - modifies the value of (i,j) to e or adds if (if it does not exist) or deletes it if e is null.
2) element(int i, int j) const - returns the value found on (i,j)
I wanted to test my code in the next way:
Matrix m(4,4); m.print(); It will print:
Lines: 0 0 0 0 0
Columns:
Values:
(And this is fine)
Now if I want to modify: m.modify(1,1,5); //The element (1,1) will be set to 5
The output of m.print(); will be:
Lines: 0 1 1 1 1
Columns: 1
Values: 5 (which again is fine)
And now if I want to print m.element(1, 1) it will return 0 and m.element(0, 1) will return 5.
This is my implementation of element(int i, int j) :
int currCol;
for (int pos = this->lines[i]; pos < this->lines[i+1]; pos++) {
currCol = this->columns[pos];
if (currCol == j)
return this->values[pos];
else if (currCol > j)
break;
}
return NULL_TELEM;
The constructor looks like this:
Matrix::Matrix(int nrLines, int nrCols) {
if (nrLines <= 0 || nrCols <= 0)
throw exception();
this->nr_lines = nrLines;
this->nr_columns = nrCols;
this->values = new TElem[100];
this->values_capacity = 1;
this->values_size = 0;
this->lines = new int[nrLines + 1];
this->columns = new TElem[100];
this->columns_capacity = 1;
this->columns_size = 0;
for (int i = 0; i <= nrLines; i++)
this->lines[i] = NULL_TELEM;
}
This is the "modify" method:
TElem Matrix::modify(int i, int j, TElem e) {
if (i < 0 || j < 0 || i >= this->nr_lines || j >= nr_columns)
throw exception();
int pos = this->lines[i];
int currCol = 0;
for (; pos < this->lines[i + 1]; i++) {
currCol = this->columns[pos];
if (currCol >= j)
break;
}
if (currCol != j) {
if (!(e == 0))
add(pos, i, j, e);
}
else if (e == 0)
remove(pos, i);
else
this->values[pos] = e;
return NULL_TELEM;
}
And this is the inserting method:
void Matrix::add(int index, int line, int column, TElem value)
{
this->columns_size++;
this->values_size++;
for (int i = this->columns_size; i >= index + 1; i--) {
this->columns[i] = this->columns[i - 1];
this->values[i] = this->values[i - 1];
}
this->columns[index] = column;
this->values[index] = value;
for (int i = line; i <= this->nr_lines; i++) //changed to i = line + 1;
this->lines[i]++;
}
Can somebody help me, please? I can't figure out why this happens and I really need to finish this implementation these days.
It just can't pass the next test. And if I want to print the elements i have (4,0)=0 (4,1)=0 ... (4,8)=0 and (4,9)=3. Now this looks pretty weird why it happens.
void testModify() {
cout << "Test modify" << endl;
Matrix m(10, 10);
for (int j = 0; j < m.nrColumns(); j++)
m.modify(4, j, 3);
for (int i = 0; i < m.nrLines(); i++)
for (int j = 0; j < m.nrColumns(); j++)
if (i == 4)
assert(m.element(i, j) == 3);
//cout << i << " " << j << ":" << m.element(i, j)<<'\n';
else
assert(m.element(i, j) == NULL_TELEM);
}
When you call modify(1, 1, 5) with an empty matrix (all zeros), that results in a call to add(0, 1, 1, 5). That increments columns_size and values_size (both to 1), the for loop body will not execute, you update columns[0] to 1 and values[0] to 5, then increment all the lines values starting at element lines[1], setting them all to 1 (lines[0] will still be 0). But lines[1] should indicate the element we just added, so it should be 0, since the value is found using columns[0].
The for loop at the end of add should start at element line + 1.

Adding terminal gap scores in C++ code for optimal sequence alignment score

Hello I have been attempting to add a scoring scheme which is 11 for internal gaps, 8 for terminal gaps on the 5 prime end, 7 for gaps on the 3' end, 4 for mismatches, 0 for matches. Currently the code only accounts for internal gap (= 11), mismatches(= 4) and matches (=0) but not for terminal gaps. Im fairly new to coding so I apologise in advance if my code is messy, any guidance is appreciated. I should be getting a score of 275.
The two sequences I used are included in the code.
#include <iostream>
#include <fstream>
#include <bits/stdc++.h>
using namespace std;
void getscore(string x, string y, int pxy, int pgap)
{
int i, j;
int m = x.length();
int n = y.length();
int dp[n+m+1][n+m+1] = {0};
for (i = 0; i <= (n+m); i++)
{
dp[i][0] = i * pgap;
dp[0][i] = i * pgap;
}
for (i = 1; i <= m; i++)
{
for (j = 1; j <= n; j++)
{
if (x[i - 1] == y[j - 1])
{
dp[i][j] = dp[i - 1][j - 1];
}
else
{
dp[i][j] = min({dp[i - 1][j - 1] + pxy ,
dp[i - 1][j] + pgap ,
dp[i][j - 1] + pgap });
}
}
}
int l = n + m;
i = m; j = n;
int xpos = l;
int ypos = l;
int xans[l+1], yans[l+1];
while ( !(i == 0 || j == 0))
{
if (x[i - 1] == y[j - 1])
{
xans[xpos--] = (int)x[i - 1];
yans[ypos--] = (int)y[j - 1];
i--; j--;
}
else if (dp[i - 1][j - 1] + pxy == dp[i][j])
{
xans[xpos--] = (int)x[i - 1];
yans[ypos--] = (int)y[j - 1];
i--; j--;
}
else if (dp[i - 1][j] + pgap == dp[i][j])
{
xans[xpos--] = (int)x[i - 1];
yans[ypos--] = (int)'_';
i--;
}
else if (dp[i][j - 1] + pgap == dp[i][j])
{
xans[xpos--] = (int)'_';
yans[ypos--] = (int)y[j - 1];
j--;
}
}
while (xpos > 0)
{
if (i > 0) xans[xpos--] = (int)x[--i];
else xans[xpos--] = (int)'_';
}
while (ypos > 0)
{
if (j > 0) yans[ypos--] = (int)y[--j];
else yans[ypos--] = (int)'_';
}
int id = 1;
for (i = l; i >= 1; i--)
{
if ((char)yans[i] == '_' && (char)xans[i] == '_')
{
id = i + 1;
break;
}
}
// Printing the final answer
cout << "Optimal score = ";
cout << dp[m][n] << "\n";
cout << "Optimal alignment :\n";
for (i = id; i <= l; i++)
{
cout<<(char)xans[i];
}
cout << "\n";
for (i = id; i <= l; i++)
{
cout << (char)yans[i];
}
return;
}
int main(){
string geneA = "TCTGGTGTCCTAGGCGTAGAGGAACCACACCAATCCATCCCGAACTCTGGTGGTTAAACTCTACTGCGGTGACGATACT ";
string geneB = "TGGTGCGGTCATACCAGCGCTAATGCACCGGATCCCATCAGAACTCCGCAGTTAAGCGCGCTTGGGCCAGAACAGTACTGGGATGGGTGTCC ";
int misMatchPenalty = 4;
int gapPenalty = 11;
int tPenalty=7;
int fPenalty=8;
getscore(geneA, geneB,
misMatchPenalty, gapPenalty);
return 0;
}

Print path with minimum sum among all the possible paths in matrix using dynamic programming

I want to print the minimum sum of the matrix where you are allowed to move either right or down. I'm able to get cost but I'm not sure how can I print path with the minimum sum among all the possible paths.
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
#define M 3
#define N 3
int findMinCost(int cost[M][N])
{
int T[M][N];
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
{
T[i][j] = cost[i][j];
if (i == 0 && j > 0)
T[0][j] += T[0][j - 1];
else if (j == 0 && i > 0)
T[i][0] += T[i - 1][0];
else if (i > 0 && j > 0)
T[i][j] += min(T[i - 1][j], T[i][j - 1]);
}
}
return T[M - 1][N - 1];
}
int main()
{
int cost[M][N] =
{
{ 9,-2,10 },
{ 15,23,-10 },
{ 40,16,2 },
};
cout << "The minimum cost is " << findMinCost(cost);
return 0;
}
You can use another 2-d array of std::pair to store the indexes of the path taken to reach the optimal solution.
Reconstructing the solution
For reconstructing the solution, declare path to store the last path taken to arrive at the optimal solution.
std::pair<int,int> path[M][N]
In your inner loop, everytime T[i][j] is computed, also compute path[i][j]
if (i == 0 && j > 0) {
T[0][j] += T[0][j - 1];
path[0][j] = std::make_pair(0, j - 1);
}
else if (j == 0 && i > 0) {
T[i][0] += T[i - 1][0];
path[i][0] = std::make_pair(i - 1, 0);
}
else if (i > 0 && j > 0) {
if (T[i - 1][j] < T[i][j - 1]) {
T[i][j] += T[i - 1][j];
path[i][j] = std::make_pair(i - 1, j);
} else {
T[i][j] += T[i][j - 1];
path[i][j] = std::make_pair(i, j - 1);
}
}
Finally, using the path array reconstruct the solution using a recursive function as follows (it can also be converted to an iterative solution)
void printPath(int i, int j, std::pair<int,int> path[M][N], int cost[M][N])
{
if (!i && !j) {
cout << cost[i][j] << ' ';
return;
}
printPath(path[i][j].first, path[i][j].second, path, cost);
cout << cost[i][j] << ' ';
}
Demo: here

Runtime Error signal 11 on simple C++ code

I am getting a runtime error with this code and I have no idea why.
I am creating a grid and then running a BFS over it. The objective here is to read in the rows and columns of the grid, then determine the maximum number of stars you can pass over before reaching the end.
The start is the top left corner and the end is the bottom right corner.
You can only move down and right. Any ideas?
#include <iostream>
#include <queue>
using namespace std;
int main() {
int r, c, stars[1001][1001], grid[1001][1001], ns[1001][1001];
pair<int, int> cr, nx;
char tmp;
queue<pair<int, int> > q;
cin >> r >> c;
for(int i = 0; i < r; i++) {
for(int j = 0; j < c; j++) {
cin >> tmp;
if(tmp == '.') {
grid[i][j] = 1000000000;
ns[i][j] = 0;
stars[i][j] = 0;
}
else if(tmp == '*') {
grid[i][j] = 1000000000;
ns[i][j] = 1;
stars[i][j] = 1;
}
else
grid[i][j] = -1;
}
}
grid[0][0] = 0;
cr.first = 0;
cr.second = 0;
q.push(cr);
while(!q.empty()) {
cr = q.front();
q.pop();
if(cr.first < r - 1 && grid[cr.first + 1][cr.second] != -1 && ns[cr.first][cr.second] + stars[cr.first + 1][cr.second] > ns[cr.first + 1][cr.second]) {
nx.first = cr.first + 1; nx.second = cr.second;
grid[nx.first][nx.second] = grid[cr.first][cr.second] + 1;
ns[nx.first][nx.second] = ns[cr.first][cr.second] + stars[cr.first + 1][cr.second];
q.push(nx);
}
if(cr.second < c - 1 && grid[cr.first][cr.second + 1] != -1 && ns[cr.first][cr.second] + stars[cr.first][cr.second + 1] > ns[cr.first][cr.second + 1]) {
nx.first = cr.first; nx.second = cr.second + 1;
grid[nx.first][nx.second] = grid[cr.first][cr.second] + 1;
ns[nx.first][nx.second] = ns[cr.first][cr.second] + stars[cr.first][cr.second + 1];
q.push(nx);
}
}
if(grid[r - 1][c - 1] == 1000000000)
cout << "Impossible" << endl;
else
cout << ns[r - 1][c - 1] << endl;
}
Sample input :
6 7
.#*..#.
..*#...
#.....#
..###..
..##..*
*#.....
I'm guessing your stack is not big enough for
int stars[1001][1001], grid[1001][1001], ns[1001][1001];
which is 3 * 1001 * 1001 * sizeof(int) bytes. That's ~12MB if the size of int is 4 bytes.
Either increase the stack size with a compiler option, or go with dynamic allocation i.e. std::vector.
To avoid the large stack you should allocate on the heap
Since you seem to have three parallel 2 - dimension arrays you could
maybe create struct that contains all three values for a x,y position.
That would make it easier to maintain:
struct Area
{
int grid;
int ns;
int stars;
};
std::vector<std::array<Area,1001>> dim2(1001);
dim2[x][y].grid = 100001;
...