In this question, firstly, you have to write two functions:
new_array (char** a, int n, int m): create a two-dimension matrix of characters whose size is m*n.
del_array (char** a, int n, int m): delete a two-dimension matrix of characters whose size is m*n.
After that, you use two above functions to perform the following task:
You are given a big image with size M*N and some small images with size m*n. Each image is presented by a matrix of characters with its size. Your task is finding the number of positions which each small image occurs in that big image.
Input file: image.inp.
The first line of the input file contains two positive integers M and N which are respectively the height and the width of the big image.
Each line 2...M+1 consists of N characters (a...z, A...Z) which describe a row of the big image.
Subsequently, there are some small images which you must find the big image. Each small image is written in the formation of the big image. Specially, there is a line having m = 0 and n = 0, you have to end your finding process.
Output file: image.out.
For each small image in the input file, you must write a number which presents the number of positions which that small image occurs in the big image.
image.inp image.out
4 4 3
Aaaa 1
Aaaa
Aaab
Aaaa
2 2
Aa
Aa
2 2
aa
ab
0 0
I did this:
file header: image.h:
#ifndef _IMAGE_H_
#define _IMAGE_H_
using namespace std;
void new_array (char** , int , int );
void del_array (char** , int , );
bool small_image(char**,char**,int,int,int,int)
int count_small_image(char** , char** , int ,int ,int ,int );
#endif
file image.cpp:
#include<iostream>
#include "image.h"
#include <fstream>
using namespace std;
void new_array(char** a, int n,int m)
{
ifstream inStream;
inStream.open("image.inp");
a=new char* [m] ;
for(int i=0; i<m; i++)
{
a[i]=new char[n];
for(int j=0;j<n; j++)
inStream>>a[i][j];
}
}
void del_array(char** a,int m)
{
for(int i=0;i<m ;i++)
{
delete [] a[i];
}
delete [] a;
}
bool small_image(char** a,char** b, int i,int j,int p,int q)
{
for(int u=i;u<i+p;u++ )
{
for(int v=j;v<j+q;v++ )
{
if(a[u][v]!=b[u-i][v-j]) return false;
}
}
return true;
}
int count_small_image(char** a,char** b,int m,int n,int p, int q)
{
int COUNT=0;
for(int i=0;i<m;i++ )
for(int j=0;j<n;j++ )
{
if(a[i][j]==b[0][0])
{
if((m-i+1)>=p && (n-j+1)>=q)
{
if(small_image(a,b,i,j,p,q)==false) break;
else COUNT++;
}
}
}
return COUNT;
}
file main_count_small_image.cpp:
#include <iostream>
#include "image.h"
#include <fstream>
using namespace std;
int main()
{
ifstream inStream;
inStream.open("image.inp");
ofstream outStream;
outStream.open("image.out");
int m,n,p,q;
char** a;
char** b;
inStream>>n>>m;
new_array(a,n,m);
inStream>>q>>p;
new_array(b,q,p);
int c;
c=count_small_image(a,b,m,n,p,q);
outStream<<c;
del_array(a,m);
del_array(b,p);
return 0;
getchar();
}
But, I get:
[error]: has stopped working ...
This is a simple bit of code best stepped through with a debugger. The OP will learn a lot more tracing the execution low than they will from being handed a canned answer.
Brute force works, but a previous question has an answer suggesting better approaches. See How to detect occurrencies of a small image in a larger image? .
The new array method is implemented incorrectly. Its inability to return the built array has been covered already so I'm skipping it. Nowhere in the specification does it say the new_array should read in the data from the file. Further, reopening the file will require the new stream to tart at the beginning and reread m and n before getting to the image data. This is not taken into account.
The lack of descriptive variable names makes this program difficult to read and is a disincentive to assisting the OP. Likewise the lack of rational indentation and braces use. The program by its appearance seems to ask the reader not to render assistance.
In count_small_image given the call
count_small_image(a,b,m,n,p,q);
The two for loops set up small_image for out-of-range array access. I believe that is that this is trying to prevent.
if((m-i+1)>=p && (n-j+1)>=q)
Maybe it does, but it's a convoluted and clumsy way to do it. Remember: Code not written has no bugs. Instead, try something along the lines of
for(int m = 0; m < largeMaxM - smallMaxM; m++)
{
for(int n = 0; n < largeMaxM - smallMaxN; n++)
Where smallMaxM and smallMaxN are the m and n bounds of the small image and largeMaxM and largeMaxN are the m and n bounds of the large image.
Small count is also overly complicated. Sorting it out so that it is based on iterating through the small image eliminates the cruft. descriptive variable names also makes the function much more readable.
bool small_image(char** a,char** b, int offsetM,int offsetN,int maxM,int maxN)
{
for(int m = 0; m < maxM; m++)
{
for(int n = 0; n < maxN; n++)
{
if(a[m+offsetM][n+offsetN]!=b[m][n]) return false;
}
}
return true;
}
I'm operating on tablet without a compiler, so forgive me if I'm off by one.
You've been told wrong (or you've misunderstood what you were told). Rewrite your code like this
char** new_array(int n, int m)
{
char** a;
...
return a;
}
int main()
{
...
char** a = new_array(n, m);
etc.
You should read up how functions can return values (including pointers). And also read up on how pointers can be used to implement arrays.
Related
This question already has answers here:
Declare large array on Stack
(4 answers)
Closed 9 months ago.
I am programming for simple matrices multiplication. However, for large values of matrix size, I faced with matrix overflow error. Could someone help me with this.
here the code!
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int r,c;
cout<<"Rows: ";
cin>>r; // 5000
cout<<"Clumns: ";
cin>>c; // 5000
int m[r][c];
for (int i=0;i<r;i++)
{
for (int j=0;j<c;j++)
{
m[i][j]=i+j;
cout<<setw(4)<<m[i][j];
}
cout<<endl;
}
}
I ran your program with different sizes. And the problem is simply that the array is too big. It works with smaller array sizes, but you can only put so much onto the stack.
So I did this:
#include <iostream>
#include <iomanip>
using namespace std;
class Matrix {
public:
Matrix(int r, int c)
: rows(r), cols(c)
{
m = new int *[rows];
for (int index = 0; index < rows; ++index) {
m[index] = new int[cols];
}
}
int & at(int r, int c) {
return m[r][c];
};
int rows = 0;
int cols = 0;
int ** m = nullptr;
};
int main(int argc, char **argv)
{
int r = atoi(argv[1]);
int c = atoi(argv[2]);
Matrix m(r, c);
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
m.at(i, j) = i+j;
cout << setw(4) << m.at(i, j);
}
cout<<endl;
}
}
And that appears to work. Now, there are some things in here that are bad. I didn't write a destructor, so there's a memory leak. And I didn't do any range checking in the at() method. I was only showing what you could do for very large arrays.
Now, I'm going to beg you... PLEASE put white space in your code. You're going to have no end of errors when you shove everything together the way you do. Notice my for-loops have a lot more space than you do. I didn't fix everywhere, but the coding policy where I work is to include white space for readability. Walls of numbers and operators can be very, very hard to read.
Also, name your variables something longer than a single character.
Both these changes will dramatically reduce future bugs.
I'm dealing with an algorithm homework which need to be executable on linux(I'm using wsl), and this homework need to store the solution and export to the output file.
To store the solution, I need to open an 2D array of "vectors storing pairs", and at the end, I need to sort the pairs by its first component in the ascending order.
I know that for the first requirement, the running time would be O(N^2)(This is also the standard answer for this dynamic programming problem), and for the second one, I've google C++ STL, and it says that the algorithm used by c++ only needs O(NlogN).
(1)It return 'killed' if I use the new to declare 2D array of vector, for the cases that N=10000, but it works fine if N=1000.
[Edited]
(2) I check the comment, and they suggest that I should write the code using vector to store vector instead of new. However, when I change to using vectors storing vectors, now the program cannot run, keep throwing segmentation fault.
I don't know where is happening. Can anybody help?
problem description:
https://drive.google.com/file/d/1m8ISIGlVGXH3oeyechLbBA1QQVSmsw-q/view?usp=sharing
file: https://drive.google.com/file/d/1Ci8MXUsX65oVOxKCD1u3YcWiXsKNYToc/view?usp=sharing
Note:
The .o files are alredy make, finish editing, you need to 'make', and run
./bin/mps [inputfile] [outputfile]
I've modified some code, but it can only run with case N=12, 1000; not for larger N.
chord.h:
#include <vector>
#include <utility>
#include <algorithm>
using namespace std;
class Chord {
public:
Chord(int);
~Chord();
void setEndPoint(int, int);
int getMaximumChords();
void print();
int size;
int* data; //stores the endpoints of the chord
// vector<pair<int,int>>** sol;
//I recently use this(1), works for N=1000, but killed if N larger
vector< vector< vector<pair<int, int>> >>sol;
//suggest to change to this(2), not working even for N=12,
//return segmentation fault
int getEndPoint(int);
};
chord.cpp:
#include "chord.h"
#include <iostream>
Chord::Chord(int tmp){ //initialize all elements 0
size = tmp;
data = new int [size];
};
Chord::~Chord(){
delete[] data;
}
void Chord::setEndPoint(int a, int b){
data[a] = b;
data[b] = a;
return;
}
void Chord::print(){
for(int i=0;i<size; i++){
cout << data[i] << endl;
}
return;
}
int Chord::getEndPoint(int a){
return data[a];
}
int Chord::getMaximumChords(){
for(int j=1; j<size; j++){
for(int i=j-1; i>=0; i--){
int k = getEndPoint(j);
if(k==i){ //case 1: ij is the chord
sol[i][j] = sol[i+1][j-1]; //make a copy
sol[i][j].reserve(1);
sol[i][j].push_back(make_pair(i,j));
}else if(k<i || k>j){ //case 2: k outside interval[i,j]
sol[i][j] = sol[i][j-1];
}else{ //case 3: k inside interval[i,j]
if (sol[i][j-1].size() > sol[i][k-1].size() + sol[k+1][j-1].size() + 1){
sol[i][j] = sol[i][j-1];
}else{
sol[i][j] = sol[i][k-1];
sol[i][j].reserve(sol[k+1][j-1].size()+1);
sol[i][j].push_back(make_pair(k,j));
sol[i][j].insert(sol[i][j].end(),sol[k+1][j-1].begin(), sol[k+1][j-1].end());
}
}
}
}
sort(sol[0][size-1].begin(), sol[0][size-1].end());
return sol[0][size-1].size();
}
main.cpp
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include "chord.h"
using namespace std;
int main(int argc, char* argv[]){
if (argc < 3){
printf("Please enter output file name!");
return 0;
}
//import input
fstream fi(argv[1]);
fstream fo;
fo.open(argv[2], ios::out);
int N=0, a=0, b=0;
char buffer[200];
fi >> N;
Chord chord(N);
while(fi>> a >>b){
chord.setEndPoint(a,b);
}
//chord.print();
int ans= chord.getMaximumChords();
//export output
fo << ans <<endl;
for(int i=0; i<chord.sol[0][chord.size-1].size(); i++){
fo << chord.sol[0][chord.size-1][i].first << " " << chord.sol[0][chord.size-1][i].second << endl;
}
fi.close();
fo.close();
return 0;
}
By default, std::vector is constructed with 0 size, and I see that you don't ever resize the vector, but you access its elements by index [i][j]. You have to resize first two (or maybe three) dimensions of 3-dimensional vector sol to fit necessary size, do following resize inside constructor:
Chord::Chord(int tmp){ //initialize all elements 0
size = tmp;
data = new int [size];
sol.resize(size, vector< vector<pair<int, int>> >(size));
};
After this resize change in constructor your program doesn't crash on 10000 input, at least on my Windows laptop.
Also maybe you need to resize two dimensions to bigger than size, you should know better. Also 3rd dimension might be needed to resize too, if you need this by algorithm, up to you. If you need to resize 3rd dimension, then do following (but if I understand your algorithm correctly you don't need this change, resizing 3rd dimension, you need it to be of size 0):
sol.resize(size1, vector< vector<pair<int, int>> >(size2, vector<pair<int, int>>(size3)));
(here size1/size2/size3 are three sizes of three dimensions, so that your vector gets 3-dimensional shape (size1, size2, size3), decide what these 3 sizes should be at your algorithm start, I think they should be (size, size, 0))
I have got some impossible queries for you! (or are they? ;) )
You have n binary numbers of length m. The ith binary number is Bi. Also, you have to perform q queries on them. The indexing is zero-based and the indexing of bits starts from left.
The queries are of type : a, i, j.
If a is:
0 : perform Logical AND operation between Bi and Bj and output the number of 1s in the result.
1 : perform Logical OR operation between Bi and Bj and output the number of 1s in the result.
2 : perform Logical XOR operation between Bi and Bj and output the number of 1s in the result.
3 : flip the value of the jth bit of Bi (i.e. set the bit to 0 if it equals 1 and vice-versa).
Note: For queries of type 0, 1, and 2, the binary numbers remain unchanged.
It is also recommended to use Fast I/O for C++ and JAVA programmers.
Input Format:
First line contains Integers n and m.
The next n lines contain binary numbers of length m.
The ith line contains binary number Bi.
The next line contains an integer q
The next q lines contain queries of type : a, i, j.
Output Format:
Output number of 1s in the result of type 0, 1 and 2 queries.
Constraints:
1<=n, m<=2500
1<=q<=10^6
I have tried changing the array size, but still the error remains the same!
#include <iostream>
#include <math.h>
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n,m;
cin>>n>>m;
char arr[3000][3000];
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
cin>>arr[i][j];
}
long int q;
cin>>q;
char query[3000][3000];
for(long int k=0;k<q;k++)
for(long int l=0;l<3;l++)
{
cin>>query[k][l];
}
for(long int i=0;i<q;i++)
{
if(int(query[i][0]-48)==3)
{
if(arr[int(query[i][1])-48][int(query[i][2])-48]=='1')
{
arr[int(query[i][1])-48][int(query[i][2])-48]='0';
}
else
{
arr[int(query[i][1])-48][int(query[i][2])-48]='1';
}
}
else if(int(query[i][0]-48)==2)
{
int cntr=0;
int bi=int(query[i][1])-48;
int bj=int(query[i][2])-48;
for(int i=0;i<m;i++)
{
int xorres=arr[bi][i]^arr[bj][i];
if(xorres==1)
cntr++;
}
cout<<cntr<<endl;
}
else if(int(query[i][0]-48)==1)
{
int cntr=0;
int bi=int(query[i][1])-48;
int bj=int(query[i][2])-48;
for(int i=0;i<m;i++)
{
int andres=arr[bi][i]|arr[bj][i];
if(andres-48==1)
cntr++;
}
cout<<cntr<<endl;
}
else if(int(query[i][0]-48)==0)
{
int cntr=0;
int bi=int(query[i][1])-48;
int bj=int(query[i][2])-48;
for(int i=0;i<m;i++)
{
int andres=arr[bi][i]&arr[bj][i];
if(andres-48==1)
cntr++;
}
cout<<cntr<<endl;
}
}
return 0;
}
The two char[3000][3000]'s that you allocate on the stack is the reason for the crash.
Since there's no upper constraint on n you'd better to try to allocate it on the heap and catch the exception if it fails. This can be done by using std::vector<std::vector<char>> instead.
Replace:
int n,m;
cin >> n >> m;
char arr[3000][3000];
With something like this:
#include <vector>
size_t n, m;
std::vector<std::vector<char>> arr;
while(std::cin >> n >> m) {
try {
arr.resize(n, std::vector<char>(m));
break; // success, break out of the while-loop
} catch(const std::exception& ex) {
// exception caught, most probably a bad_alloc
std::cerr << ex.what() << " ... try again\n";
}
}
As proposed in the comments, you probably don't need to store all the queries. Just deal with one query at a time.
Also, never #include <bits/stdc++.h> yourself. It's a non-standard/non-portable header file that includes a lot more than you need, and often not all you need. Instead, only include the headers you actually need.
Similarly, using namespace std; is considered bad practice.
OK, so I think you have complicated some things here.
The size of the queries is 10^6 and you are declaring the array as query[3000][3000].
Now, I don't think you need to store the queries. Consider this-
cin>>q;
while(q--)
{
cin>>a>>i>>j;
/*Your code here*/
}
The question states that the queries are in the form : a i j
So for example if you want to perform operation 0 on first 2 strings, the query will be:
0 1 2
But you are storing the binary numbers from index 0!
So, your code will perform the operation on second and third query. So, what you need to do is just take subtract 1 from values of i and j.
This question already has answers here:
c++ : dynamic number of nested for loops (without recursion)
(3 answers)
Closed 6 years ago.
I have read the following questions but have not found a solution to my problem:
c++ : dynamic number of nested for loops (without recursion)
variable nested for loops
actual problem statement is :-
Job and Jimmy both are playing with numbers. Job gives Jimmy an array of numbers and asks him to tell the minimum possible last number of a non decreasing sequence of length L.
Input Format
First input line consists of a number which is size of array N.
Next line contains N space separated elements of array.
Next line contains length of the non decreasing sequence i.e. L.
Output Format
You have to print the minimum possible last number of a sequence and if their is no non-decreasing sequence of length L, then print -1
Sample Input
7
9 7 2 5 4 11 12
3
Sample Output
11
Explanation
In sample input, possible non-decreasing sequences of length L=3 are (9,11,12) , (7,11,12) , (2,5,11) , (2,4,11) , (2,5,12) , (2,4,12) , (2,11,12) , (5,11,12) , (4,11,12) and the minimum last number is 11 for the sequences (2,5,11) and (2,4,11). Hence, the answer is 11."
my code...
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int fact(int y,int x)
{
static int temp=0;
if(temp==x)
{
temp=0;
return 1;
}
else
{
++temp;
return y*fact((y-1),x);
}
}
int main() {
int num,randmax,n,s,q,w last=-1, minlast=-1;
cin>>n;
vector<int> a(n);
for(int i=0;i<n; i++)
{
cin>>a[i];
}
cin>>s;
vector<vector<int>> c;
q=fact(s);
c.resize(q);
for(int i = 0 ; i < q ; ++i)
{
//Grow Columns by n
a[i].resize(s);
}
w=q;
randmax=n-1;
int k=0;
while(w)
{
for(int i=0 ; i<n ; i++){
}
num=rand()%randmax; // this works perfect as expected
c[][i]=a[num];
}
w--;
}
/*for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
for(int k=j+1;k<n; k++)
{
if((a[i]<=a[j])&&(a[j]<=a[k]))
{
last=a[k];
if(minlast=-1)
{
minlast=a[k];
}
if(last<minlast){
minlast=last;
}
}
}
}
}
*/
cout<<last;
return 0;
}
`
I would tell you what I tried to do... I thought of mapping the data by having them randomly assigned in one of my array and then computing them..
I got lost somewhere in my code...plz gimme an solution to it...and more imp. a good explanation of the same as I got stuck at times when I need a dynamic nested n loop type of thing...
also it would be more helpful if you edit in my code or algo so that I could learn where my mistakes are there...
Thanks in advance for you time...
As the answers your links have pointed out, you can imitate a dynamic amount of for loops by using an array David gives a fine implementation here.
For the actual problem you gave though, I see no need for a dynamic amount of for loops at all. The problem is a standard non-decreasing subsequence problem with a slight variation.
#include <iostream>
#include <fstream>
int N, L;
int arr[100], seq[100];
int bst;
int main() {
std::ifstream file ("c.txt");
file >> N;
for(int n = 0; n < N; ++n)
file >> arr[n];
file >> L;
file.close();
bst = 1e9;
for(int i = 0; i <= N; ++i) seq[i] = 1e9;
for(int i = 0; i < N; ++i)
{
int x = 0;
while(seq[x] < arr[i]) ++x;
seq[x] = arr[i];
if(x + 1 >= L)
bst = std::min(bst, arr[i]);
}
std::cout << bst << std::endl;
return 0;
}
This code should solve your problem. The first part does standard parsing and initialization. The rest is a variation on the LIS problem, which has several standard algorithms that solve it. Here, we just check that whenever we extend an array of length L or longer, we see if the element is smaller than our current.
I'm writing a function that has a 2D array of strings as input parameter. I initialized the string, passed it to the function but when I tried to print the array nothing happened. It says that the length of the array is 0. All my functions are stored in a header file. Here's my code:
#include<iostream>
#include<string>
#include<iomanip>
using namespace std;
int c,i,j,fx,fy;
int color,fields,rows,anim,speed;
string opt[5][50];
string popt[5][50]={
{"caption","asdf","safd","asf"},
{"caption1","dsafa","asdf","asdf"},
{"caption2","asdf","asdf","asdfas"},
{"caption3","sadfa","asdfs","fasdfa"}};
void ini(int focus_text_color, int n_fields,int n_rows, string options[][50], bool animation=false, int animation_speed=10)
{
color=focus_text_color;
fields=n_fields;
for(i=1;i<fields+1;i++)
{
for(j=1;j<rows+1;j++)
{
opt[i][j]=options[i][j];
}
}
}
int drawh()
{
system("cls");
for(i=0;i<fields;i++)
{
for(j=0;j<rows;j++)
{
cout<<opt[i][j]<<setw(opt[i+1][j].length()+5);
}
}
return 0;
}
void main()
{
ini(LIGHTRED,4,4,popt);
drawh();
}
NOTE: This is a part of the code so I haven't tested it, and sorry for my bad English :D
Apart from #Oli's comments. To make it simpler, you can pass an array by reference. See below example:
template<unsigned int ROW, unsigned int COL>
void ini (string (&s)[ROW][COL]) // psuedo code for 'ini'; put extra params to enhance
{
ini(s, ROW, COL);
}
Now, template ini() provides a wrapper to actual ini() which calculates the row/column of an array at compile time. Usage is very simple:
string s[10][5];
ini(s); // calls ini(s,10,5);
Your loop should start from dimension 0 and not 1 for copying. Check my approach and modify your code.
for(int i = 0; i < ROW; i++)
for(int j = 0; j < COL; j++)
s1[i][j] = s2[i][j];
Also there are many problems in your code due to passing wrong dimensions (e.g. passing 4 as dimension while calling ini(), when it should be 5).
The reason why you don't get any output is that you don't initialize the global variable rows, so it stays at 0. Your init function should be:
void ini(int focus_text_color, int n_fields,int n_rows, string options[][50], bool animation=false, int animation_speed=10)
{
color=focus_text_color;
fields=n_fields;
rows = n_rows; //-- ADDED LINE
....