I am looking for the best algorithm to do a rotation of a row in a 2D array / matrix. Let's say we have
mat[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
I want to shift the element to the left by one, the first row 1 2 3 will then become 2 3 1. The function realizes this by copying each element to the left via dynamical memory allocation.
void rotate_row(const int& row) {
int *temp_row = (int *) (malloc(3));
for (int i = 0; i < 3; ++i) {
temp_row[i % 3] = mat[row][(i + 1) % 3];
}
memcpy(mat[row], temp_row, 3);
free(temp_row);
}
To manipulate any specific row, we simple call the function rotate_row(row).
I don't quite understand malloc thing in C, since I grow up learning a completely new way of dynamical allocation, so I first change it to:
void rotate_rows(const int& row) {
//int *temp_row = (int *) (malloc(3));
int *temp_row = new int[3];
for (int i = 0; i < 3; ++i) {
temp_row[i % 3] = mat[row][(i + 1) % 3];
}
memcpy( mat[row], temp_row, 3);
//free(temp_row);
delete [] temp_row;
temp_row = NULL;
}
My question first is, will simply changing the way of dynamical memory allocation accelerates the code?
Also, I don't think it is necessary to use dynamical memory allocation for my purpose(rotate the row). Is their any better (not necessary the best) algorithm available?
Rotating will not change array size, hence doing it in-place sounds much more performant to me, no need for dynamic memory allocation and freeing previous pointer.
void rotate(int * array, size_t n) {
if (n <= 1)
return;
const int head = array[0];
for (size_t i = 1; i < n; ++i)
array[i - 1] = array[i];
array[n - 1] = head;
}
You can avoid all the dynamic memory allocation, and use the std::rotate algorithm:
#include <algorithm>
#include <iostream>
int main()
{
int mat[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
// rotate left each row by 1
for (int i = 0; i < 3; ++i)
std::rotate(&mat[i][0], &mat[i][1], &mat[i][3]);
for (int i = 0; i < 3; ++i)
std::cout << mat[i][0] << " " << mat[i][1] << " " << mat[i][2] << "\n";
}
Output:
2 3 1
5 6 4
8 9 7
Edit:
Here is a sample of rotating each row by it's row index + 1:
#include <algorithm>
#include <iostream>
int main()
{
int mat[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
// rotate left each row by 1
for (int i = 0; i < 3; ++i)
std::rotate(&mat[i][0], &mat[i][i+1], &mat[i][3]);
for (int i = 0; i < 3; ++i)
std::cout << mat[i][0] << " " << mat[i][1] << " " << mat[i][2] << "\n";
}
Output:
2 3 1
6 4 5
7 8 9
Yes there's a better way and no need to use dynamic memory allocation. You actually don't need another array to solve this.
Here's a sample code:
for(int i = 0; i < n/2; i++){
for(int j = i; j < n-i-1; j++){
int tmp = matrix[i][j];
matrix[i][j] = matrix[n-j-1][i];
matrix[n-j-1][i] = matrix[n-i-1][n-j-1];
matrix[n-i-1][n-j-1] = matrix[j][n-i-1];
matrix[j][n-i-1] = tmp;
}
}
This is pretty straight forward so I think you'll understand the code easily without explanation.
Related
So recently I ran into a problem that I thought was interesting and I couldn't fully explain. I've highlighted the nature of the problem in the following code:
#include <cstring>
#include <chrono>
#include <iostream>
#define NLOOPS 10
void doWorkFast(int total, int *write, int *read)
{
for (int j = 0; j < NLOOPS; j++) {
for (int i = 0; i < total; i++) {
write[i] = read[i] + i;
}
}
}
void doWorkSlow(int total, int *write, int *read, int innerLoopSize)
{
for (int i = 0; i < NLOOPS; i++) {
for (int j = 0; j < total/innerLoopSize; j++) {
for (int k = 0; k < innerLoopSize; k++) {
write[j*k + k] = read[j*k + k] + j*k + k;
}
}
}
}
int main(int argc, char *argv[])
{
int n = 1000000000;
int *heapMemoryWrite = new int[n];
int *heapMemoryRead = new int[n];
for (int i = 0; i < n; i++)
{
heapMemoryRead[i] = 1;
}
std::memset(heapMemoryWrite, 0, n * sizeof(int));
auto start1 = std::chrono::high_resolution_clock::now();
doWorkFast(n,heapMemoryWrite, heapMemoryRead);
auto finish1 = std::chrono::high_resolution_clock::now();
auto duration1 = std::chrono::duration_cast<std::chrono::microseconds>(finish1 - start1);
for (int i = 0; i < n; i++)
{
heapMemoryRead[i] = 1;
}
std::memset(heapMemoryWrite, 0, n * sizeof(int));
auto start2 = std::chrono::high_resolution_clock::now();
doWorkSlow(n,heapMemoryWrite, heapMemoryRead, 10);
auto finish2 = std::chrono::high_resolution_clock::now();
auto duration2 = std::chrono::duration_cast<std::chrono::microseconds>(finish2 - start2);
std::cout << "Small inner loop:" << duration1.count() << " microseconds.\n" <<
"Large inner loop:" << duration2.count() << " microseconds." << std::endl;
delete[] heapMemoryWrite;
delete[] heapMemoryRead;
}
Looking at the two doWork* functions, for every iteration, we are reading the same addresses adding the same value and writing to the same addresses. I understand that in the doWorkSlow implementation, we are doing one or two more operations to resolve j*k + k, however, I think it's reasonably safe to assume that relative to the time it takes to do the load/stores for memory read and write, the time contribution of these operations is negligible.
Nevertheless, doWorkSlow takes about twice as long (46.8s) compared to doWorkFast (25.5s) on my i7-3700 using g++ --version 7.5.0. While things like cache prefetching and branch prediction come to mind, I don't have a great explanation as to why doWorkFast is much faster than doWorkSlow. Does anyone have insight?
Thanks
Looking at the two doWork* functions, for every iteration, we are reading the same addresses adding the same value and writing to the same addresses.
This is not true!
In doWorkFast, you index each integer incrementally, as array[i].
array[0]
array[1]
array[2]
array[3]
In doWorkSlow, you index each integer as array[j*k + k], which jumps around and repeats.
When j is 10, for example, and you iterate k from 0 onwards, you are accessing
array[0] // 10*0+0
array[11] // 10*1+1
array[22] // 10*2+2
array[33] // 10*3+3
This will prevent your optimizer from using instructions that can operate on many adjacent integers at once.
I'm trying to make a simple battle ship game. I'm stuck on trying to randomly place the ships on my board.I have a feeling it is because I should be using a vector instead of an array. but I'm not sure how to create a 2d vector.
Here's what I have so far:
using namespace std;
void clearBoard(const int row, const int col)
{
int grid[row][col];
for (int i = 0; i < row; i++) {
for (int j = 0; j < col;j++) {
grid[i][j] = 0;
cout << grid[i][j] << " ";
}
cout << endl;
}
}
void setShips(int max_ships1, int row, int col)
{
int ship_counter = 0;
while(ship_counter < max_ships1) {
int x = rand() % row;
int y = rand() % col;
int matrix[x][y]
if (matrix[x][y] != 1) {
ship_counter++;
matrix[x][y] = 1;
cout << matrix[x][y] << " ";
}
cout << endl;
}
}
int main(int argc, char* argv[])
{
int _row = atoi(argv[0]);
int _col = atoi(argv[2]);
int max_ships;
if (_row > _col) {
max_ships = _row;
}
else if (_col > _row) {
max_ships = _col;
}
else {
max_ships = _row;
}
cout << "enter the size of the board:";
cin >> _row >> _col;
clearBoard(_row, _col);
setShips(_row,_col,max_ships);
return 0;
}
If the user decides on a 3x3 board, the first function returns:
0 0 0
0 0 0
0 0 0
I'm hoping to randomly generate 1's to represent a battleship's position.
Here's an example on a 3x3 board:
1 0 0
0 1 0
1 0 0
Thanks.
Your main problem is that grid goes out of scope (and is effectively deleted) when clearBoard returns, and matrix (a completely unrelated array to grid) goes out of scope each time through your while loop. That means that you're filling grid with zeroes, then creating a bunch of other arrays with random data and sometimes setting one element to 1. You need to either make grid global, or return it from clearBoard and pass it to setShips as an argument.
Passing around multidimensional raw arrays is kind of complicated, so using a vector might make this a bit easier for you if you don't want to make the array global. To create a two-dimensional vector, you might think that std::vector<std::vector<int>> will work, but that's not quite right. You can do it that way, as mentioned in the comments, but technically, std::vector<std::vector<int>> is what's called a jagged array, meaning that you can have each row be a different length - unlike your raw 2D array, where you know that each row must always be the same length.
The proper way to make a two-dimensional array with a vector is this:
std::vector<int> grid(row * col);
grid[i * row + j] = 1; // Or i * col + j will also work.
As you can see, it's a bit more complicated to get an element out by its (x,y) coordinates. It doesn't matter which of the two calculation methods you use, but in one version i is x and j is y, while in the other, the reverse is true (i is y, etc).
You can also set up a 2D vector like this :
#include<vector>
#include<iostream>
using namespace std;
int main()
{
std::vector< std::vector<int> > grid2D;
//m * n is the size of the grid
int m = 10;
int n = 10;
//Grow rows by m
grid2D.resize(m);
//Grow Columns by n
for(int i = 0 ; i < m ; ++i) grid2D[i].resize(n);
// print out 2D grid on screen
for(i = 0 ; i < m ; ++i){
for(int j = 0 ; j < n ; ++j){
grid2D[i][j]=0;
cout<<""<<grid2D[i][j]<<" ";
}
cout<<"\n";
}
cout<<"\n";
return 0;
}
I have written a piece of code in C++. I took the first part from search engine results.
1) What is the meaning of defining a function using double **filter_2d? Can we define a function using a pointer?
2) I am confused about the following line:
double **filt_out = filter_2d(A, 3, 3, B, 2, 1);
It is not working properly, and I do not understand why.
#include <iostream>
#include <stddef.h>
#include <cmath>
#include <fftw3.h>
using namespace std;
void filter_2d(double** image, int width_image, int height_image, double** kernel, int width_kernel, int height_kernel, double *** OutImg)
{
double **output = *OutImg;
int i, j, p, q;
//this is the case of 'full' option selected in matlab
//double **output = (double **)malloc(sizeof(double *)*(width_image + width_kernel - 1));
for (i = 0; i<width_image + width_kernel - 1; i++)
{
output[i] = (double *)malloc(sizeof(double)*(height_image + height_kernel - 1));
}
//for each point in the output
for (i = 0; i<width_image + width_kernel - 1; i++)
{
for (j = 0; j<height_image + height_kernel - 1; j++)
{
output[i][j] = 0;
//kernel(p,q)*image(i-p, j-q)
for (p = 0; p<width_kernel; p++)
{
//avoid unnecessary comparisons
if (i - p < 0)
{
break;
}
else if (i - p < width_image)
{
for (q = 0; q<height_kernel; q++)
{
//idem as above
if (j - q < 0)
{
break;
}
else if (j - q < width_image)
{
output[i][j] += kernel[p][q] * image[i - p][j - q];
}
}
}
}
}
}
}
int main()
{
double ** OutImage = 0;
OutImage = (double **)malloc(sizeof(double *)*(3 * 3));
double A[3][3] = { { 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 } };
double *A_ptr[9];
for (int i = 0; i < 10; i++)
{
A_ptr[i] = A[i];
}
double B[1][2] = { 1, 2 };
double *B_ptr[2];
for (int i = 0; i < 2; i++)
{
B_ptr[i] = B[i];
}
//Error in the below line
filter_2d(A_ptr, 3, 3, B_ptr, 2, 1, &OutImage); //unable to understand
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 4; j++)
cout << *OutImage << endl;
}
system("PAUSE");
return 0;
}
Pointer Declaration
General Format:
data_type *pointer_name;
A pointer declaration such as,
int *numberPtr;
declares numberPtr as a variable that points to an integer variable. Its content is a memory address.
The * indicates that the variable being declared is a pointer variable instead of a normal variable.
Consider the following declaration :
int *numberPtr, number = 20;
In this case, two memory address have been reserved, associated with the names numberPtr and number.
The value in variable number is of type integer, and the value in variable numberPtr is an address for another memory location.
Example
// create a 2D array dynamically
int rows, columns, i, j;
int **matrix;
cin >> rows >> columns;
matrix = new int*[rows];
for(i=0; i<rows; i++)
matrix[i] = new int[columns];
Your function expects double** and your are passing double [3][3]. There is no implicit cast for these types.
You need to create you array in the main() as double ** and use it as the argument in the function call.
The question - conversion of 2D array to pointer-to-pointer should help you in achieving what you are trying to do.
Your cout does not seem correct as well. You are considering filt_out as a 2D array instead of pointer.
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 4; j++)
cout << **(filt_out + i + j) << endl; //changed here
}
I have analysed your code and I think I have found some issues in it.
Here is the new code:
#include <iostream>
#include <stdlib.h>
using namespace std;
double** filter_2d(double** image, int width_image, int height_image, double** kernel, int width_kernel, int height_kernel)
{
int i, j, p, q;
//this is the case of 'full' option selected in matlab
double **output = (double **)malloc(sizeof(double *) * (width_image + width_kernel - 1));
for (i = 0; i<width_image + width_kernel - 1; i++)
output[i] = (double *)malloc(sizeof(double) * (height_image + height_kernel - 1));
//for each point in the output
for (i = 0; i<width_image + width_kernel - 1; i++)
for (j = 0; j<height_image + height_kernel - 1; j++)
{
output[i][j] = 0;
//kernel(p,q)*image(i-p, j-q)
for (p = 0; p<width_kernel; p++)
{
//avoid unnecessary comparisons
if (i - p < 0)
{
break;
}
else if (i - p < width_image)
{
for (q = 0; q<height_kernel; q++)
{
//idem as above
if (j - q < 0)
break;
else if (j - q < width_image)
output[i][j] += kernel[p][q] * image[i - p][j - q];
}
}
}
}
return output;
}
int main()
{
double A[3][3] = { { 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 } };
double *A_ptr[9];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j ++)
A_ptr[i * 3 + j] = &(A[i][j]);
double B[1][2] = { 1, 2 };
double *B_ptr[2];
for (int i = 0; i < 1; i++)
for (int j = 0; j < 2; j ++)
B_ptr[i * 1 + j] = &(B[i][j]);
//no more errors in the function call
double **OutImage = filter_2d(A_ptr, 3, 3, B_ptr, 2, 1);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 3; j++)
cout << OutImage[i][j] << " ";
cout << endl;
}
return 0;
}
I thought a better idea would be that function filter_2d returns a pointer to the output matrix. The output matrix is dynamically allocated with malloc inside the function, so it will not be lost (and you can get the computed values in the matrix) if you return the address to it and store it back in main.
You can see here a comparison between stack memory and variables local to a function vs heap memory and variables allocated with malloc stack vs heap
Now I will talk about some problems I found in the main function. The first problem was at the initialization of the arrays of pointers A_ptr and B_ptr.
double *A_ptr[9];
for (int i = 0; i < 10; i++)
{
A_ptr[i] = A[i];
}
and
double *B_ptr[2];
for (int i = 0; i < 2; i++)
{
B_ptr[i] = B[i];
}
From what I understood in your code the elements of A_ptr and B_ptr were pointers to each element of the arrays A and B.
So, as A_ptr and B_ptr are linearized matrices, you have to be careful as to give the correct addresses of the corresponding elements from arrays A and B.
If you take a matrix M and linearize it into a matrix N, then element M[i][j] will go to N[i * number_of_columns_from_M + j].
Another problem was the limits of i and j in the for cycles where you were printing the results.
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 4; j++)
cout << *OutImage << endl;
}
From what I calculated, in filter_2d function you allocate a matrix of 4 lines and 3 columns. In those cycles you were assuming that OutImage has 5 lines and 4 columns.
The last problem was the printing of the elements from OutImage.
cout << *OutImage << endl;
OutImage as you declared in your code was an array of 9 pointers (don't understand why you did that). With the above instruction you are repeatedly printing the first element of OutImage array (which is an address as OutImage is an array of 9 pointers), so that is why you were seeing only addresses printed.
I am not sure if the numbers printing now on the screen are correct, as I don't know what mathematical computation is done in filter_2d.
It can help to read * in C++ pointer-contexts as pointer to.
int* a;
a is a pointer to int.
int** b;
b is a pointer to pointer to int.
b = &a;
a is a pointer to int. &a is the address of a pointer to int. b is a pointer to a pointer to int.
*a = 10;
store 10 in the memory pointed to by a.
**b = 20;
store 20 in the memory pointed to by the int* that b points to.
#include <iostream>
int main()
{
int i = 1234;
int* a;
int** b;
std::cout << "i is " << i << ", it's address is " << i << "\n";
a = &i;
std::cout << "a = " << a << ", *a = " << *a << ", its address is " << &a << "\n";
b = &a;
std::cout << "b = " << b << ", *b = " << *b << ", **b = " << **b << ", its address is " << &b << "\n";
}
Live demo: http://ideone.com/OpCro4
Your function "filter_2d" returns the address of a pointer. It also expects the first parameter to be the address of a pointer.
This is often used as a way to allow functions to say "give me the address of a pointer and I will populate it for you" but C++ also uses pointers to pass arrays.
int a[100];
f(a);
The program could pass all 100 addresses to f() which would either require 100 ints on the stack or 100 registers.
Or alternatively, it could pass the address of the first int in a. And in C and C++ that's generally how arrays work - they are operated on as an array and an offset.
int a[100];
int* b = a; // b points to the first element in a
// these two mean the same thing
a[90];
*(b + 90);
// undefined behavior
*(b + 100); // the 101st element of a, i.e. invalid
The downside: Pointers only know about the element they point to, they don't intrinsically know anything about array lengths.
Lastly, instead of SYSTEM("PAUSE") either use 'Ctrl+F5' to start without debugging (which will automatically prompt you to hit return after execution) or use 'F11' to step into your program.
Your code has 2 problems:
First, I'm assuming the output image will have the same size as an input image so it must be allocated like this:
(double **)malloc(sizeof(double *)*(width_image * height_image));
Second, you define a function that will return a 2D pointer, but unfortunately, you declare this 2D pointer inside the function itself which means that you define a local variable pointer, In most cases once you return this value it will be totally wrong and it's not the one which is allocated inside the function itself.
To solve the problem you can choose one of these two solutions:
You can define a global 2D pointer, and inside your function it can be allocated, so you don't need to define your function to return 2D pointer.
The second solution is to define the 2D pointer that will store the result in the caller function, the caller function will allocate the required size for that pointer and pass it to the callee function (i.e filter_2d), when it pass it, it will be passed by its address, so in the filter_2d definition we will add an extra argument as a 3D POINTER to store the result as the following:
//Define these 2 lines in the main function.
double ** OutImage = null;
OutImage = (double **)malloc(sizeof(double *)*(width_image * height_image));
To pass the OutImage to the filter_2d function:
filter_2d(A_ptr, 3, 3, B_ptr, 2, 1, &OutImage);
The definition of the filter_2d function should be:
void filter_2d(double** image, int width_image, int height_image, double** kernel, int width_kernel, int height_kernel, double *** OutImg)
Inside filter_2d you can define your local variable as the following:
double **output = *OutImg;
Hope this calrrification will help you.
I have written a piece of code in C++. I took the first part from
search engine results.
Are you serious? Not sure how to understand that. It's not a debugging site. You're supposed to do the effort first.
Anyway, your code is mostly C. The only piece of code reminding me of C++ is the console output. So let me try if I can help... because I like.
1) What is the meaning of defining a function using double **filter_2d? Can we define a function using a pointer?
This means that the result of the function is a pointer to a pointer of type double. Break it down like this:
**filt_out is of type double - used to access a double value; popular use in 2D arrays to access the 2nd dimension, i.e. the row and the column of a 2D array.
*filt_out is of type double * - used to access a pointer to a double value; popular use in 2D arrays to access the 1st dimension, i.e. the row of a 2D array.
filt_out is of type double ** - used to access a pointer to a pointer to a double value; popular use in 2D arrays to access the array, i.e. the allocated memory address for the 2D array.
You can define a function using a simple pointer, but it is not suitable for 2D arrays. Read the items above.
2) I am confused about the following line:
double **filt_out = filter_2d(A, 3, 3, B, 2, 1); It is not working
properly, and I do not understand why.
Does not make sense to me. filter_2d's return type is voidand thus I don't see why would want to assign the returned value to a pointer to a pointer to a double
It is not working properly, and I do not understand why.
Me neither, yet. But to be honest, it sounds more like a debugging request than a question that merits votes. In particular you give us the impression that you did not do your homework learning C/C++ first of all, and secondly copied code from a search engine and ask the community to solve that for you.
Some flaws I believe you want to have a closer look at:
(I'll use mostly C syntax)
OutImage = (double **)malloc(sizeof(double *)*(3 * 3));
It does not look right to me. Please verify.
I think OutImage is supposed to be a 2D array (the image) and thus **OutImage points to an element (2nd dimension, you want to access row and column) of the 2D array.
Also since it is a 2D array, you need to initialize the 1st dimension first (i.e. the rows) and then the 2nd dimension (i.e. the columns).
So I would suggest something like this:
//three rows of size for type double*
OutImage = (double **) malloc(sizeof(double *) * 3);
//three columns of size of type double
for (int i=0; i<3; i++)
OutImage[i] = (double *) malloc(sizeof(double) * 4);
This way you can access using OutImage[row][column]. I believe it's less error prone. I put the size of the columns to 4 according to the calculation in the function filter_2d which calculates the widths and the heights (The width remains the same with parameters given, the height increases by one dimension).
Also (see below) later in the function filter_2d I'd remove the memory allocation, since it is already done here.
Not sure what you want to achieve with this, but I think that...
double *A_ptr[9];
for (int i = 0; i < 10; i++)
{
A_ptr[i] = A[i];
}
is just wrong on so many levels.
10 does not make sense; indices go from 0 to 8
A[i] has size 3 while A_ptr[i] has size 9
what were you thinking Sam?
Considering the use of A_ptr (and the way you access it) in the function filter_2d above I would think you want to do something analogue to above 2D array.
double ** A_ptr = (double **) malloc(sizeof (double *) * 3);
for (int i = 0; i < 3; i++)
A_ptr[i] = (double *) malloc(sizeof (double) * 3);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
A_ptr[i][j] = A[i][j];
}
}
double B[1][2] = { 1, 2 };
double *B_ptr[2];
for (int i = 0; i < 2; i++)
{
B_ptr[i] = B[i];
}
Similar to above.
B[i] is of size 1, so only index 0 makes sense
Damn Sam, what were you thinking again?
You call filter with following parameters:
A_ptr: a 2D array copy of A (image)
3: size of 1st dimension of image
3: size of 2nd dimension of image
B_ptr: a 2D array copy of B (kernel)
2: size of 1st dimension of kernel - Should be switched with the next one
1: size of 2nd dimension of kernel - Should be switched with the previous one
&OutImage: address of the pointer to the resulting filtered image (the parameter is a pointer to **OutImage actually)? I think you want to preserve the pointer after the function call, isn't it? Sounds OK to me.
filter_2d(A_ptr, 3, 3, B_ptr, 2, 1, &OutImage);
You defined B_ptr as a copy of B which has dimensions [1][2], but you pass 2 as 1st dimension and 1 as 2nd dimension to the function. Either switch the dimensions of B/B_ptr or switch the two parameters.
In that function I would remove the following code
for (i = 0; i<width_image + width_kernel - 1; i++)
{
output[i] = (double *)malloc(sizeof(double)*(height_image + height_kernel - 1));
}
(See last remark in first bug above when allocating memory for OutImage).
Replace the loop to print the result. Make it look like that:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++)
cout << OutImage[i][j] << endl;
}
I kept the C++ style printing, but actually you could do it simply with C's printf function as well. No need to include iostream really.
So that's it. I compiled your code and run it. Not sure what to expect, but according to your comment it should be
2 5 8 3 8 14 17 6 14 23 26 9
Guess what? I got
1 4 7 6 4 13 16 12 7 22 25 18
Well, I guess at this point, it's your turn now.
Please remember, check where you want to do the memory allocation in
order to have it take into account the new dimensions. I hard
coded it in your example to make it work, more or less.
I would probably allocate a dummy address and then use realloc to increase the size to whatever is needed depending on the parameters.
Remember that in general you would want to free the allocated memory.
I skip it here, since it is a short program.
The program could look like so:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
void filter_2d(double** image, int width_image, int height_image, double** kernel, int width_kernel, int height_kernel, double *** OutImg) {
double **output = *OutImg;
int i, j, p, q;
int rows = width_image + width_kernel - 1;
int cols = height_image + height_kernel - 1;
//rows of size for type double*
output = (double **) realloc(output, sizeof (double *) * rows);
//columns of size of type double
for (int i = 0; i < rows; i++)
output[i] = (double *) malloc(sizeof (double) * cols);
//for each point in the output
for (i = 0; i < width_image + width_kernel - 1; i++) {
for (j = 0; j < height_image + height_kernel - 1; j++) {
output[i][j] = 0;
//kernel(p,q)*image(i-p, j-q)
for (p = 0; p < width_kernel; p++) {
//avoid unnecessary comparisons
if (i - p < 0) {
break;
} else if (i - p < width_image) {
for (q = 0; q < height_kernel; q++) {
//idem as above
if (j - q < 0) {
break;
} else if (j - q < width_image) {
output[i][j] += kernel[p][q] * image[i - p][j - q];
}
}
}
}
}
}
}
int main() {
//allocate dummy memory of size for type double*
double ** OutImage = (double **) malloc(sizeof (double *));
// define image matrix
double A[3][3] = {
{ 1, 2, 3},
{ 4, 5, 6},
{ 7, 8, 9}
};
// copy image matrix
double ** A_ptr = (double **) malloc(sizeof (double *) * 3);
for (int i = 0; i < 3; i++)
A_ptr[i] = (double *) malloc(sizeof (double) * 3);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
A_ptr[i][j] = A[i][j];
printf(" %f ", A_ptr[i][j]);
}
}
printf("\n");
//define kernel matrix
double B[1][2] = {
{ 1, 2}
};
//copy kernel matrix
double ** B_ptr = (double **) malloc(sizeof (double *));
B_ptr[0] = (double *) malloc(sizeof (double)*2);
for (int i = 0; i < 1; i++) {
for (int j = 0; j < 2; j++) {
B_ptr[i][j] = B[i][j];
printf(" %f ", B_ptr[i][j]);
}
}
printf("\n");
//call filter
filter_2d(A_ptr, 3, 3, B_ptr, 1, 2, &OutImage);
//print result
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++)
cout << OutImage[i][j] << endl;
}
// No idea what that is
//system("PAUSE");
return 0;
}
P.S.: I just saw that Valy had a good solution.
Yes, functions can returns pointers, or even pointers to pointers. I believe both of your answers are addressed by this thread.
#include <stdlib.h>
int int_sorter( const void *first_arg, const void *second_arg )
{
int first = *(int*)first_arg;
int second = *(int*)second_arg;
if ( first < second )
{
return -1;
}
else if ( first == second )
{
return 0;
}
else
{
return 1;
}
}
int main()
{
int array[10];
int i;
/* fill array */
for ( i = 0; i < 10; ++i )
{
array[ i ] = 10 - i;
}
qsort( array, 10 , sizeof( int ), int_sorter );
for ( i = 0; i < 10; ++i )
{
printf ( "%d\n" ,array[ i ] );
}
}
#include <iostream>
#include <cstdlib>
using namespace std;
void swapNum(int *q, int *p)
{
int temp;
temp = *q;
*q = *p;
*p = temp;
}
void reverse(int *ip, int const size)
{
for (int k = 0; k < size; k++)
{
if (k == (size/2))
{
int *q = &ip[k];
int *p = &ip[k+1];
swapNum(q,p);
break;
}
else
swap(ip[k], ip[size-k]);
}
}
int main()
{
const int size = 20;
int arr[size];
int *ip;
ip = arr;
cout << "Please enter 20 different numbers." << endl;
for (int i = 0; i < size; i++)
{
cout << "\nNumber " << i+1 << " = ";
cin >> ip[i];
}
reverse(ip, size);
cout << "I will now print out the numbers in reverse order." << endl;
for (int j = 0; j < size; j++)
{
cout << ip[j] << " ";
}
return 0;
}
When I try to run this program it crashes. I don't know what's wrong and the purpose of my program is to swap number of the array using pointers. I am recently introduced to this so I am not that familiar with it. But I think that I am swapping the address of the numbers instead of swapping the numbers in the address. Correct me if I am wrong.
You're accessing outside the array bounds in reverse() when you do:
swap(ip[k], ip[size-k]);
On the first iteration of the for loop, k is 0 and size-k is size. But array indexes run from 0 to size-1. So it should be:
swap(ip[k], ip[size-k-1]);
But I don't see a definition of swap in your program. I think it should actually be:
swapNum(&ip[k], &ip[size-k-1]);
Another improvement: Instead of handling size == k/2 specially and using break, just use size < k/2 as the bound test in the for loop.
swap(ip[k], ip[size-k]);
Your problem is there. size - k when k is 0 will lead to undefined behavior (accessing an array out of bounds). Your loop structure in reverse can be simplified:
for (int k = 0; k < size / 2; k++)
swapNum(&ip[k], &ip[size - k - 1]); // updated to use the address since your swap function takes pointers.
Function reverse is invalid
void reverse(int *ip, int const size)
{
for (int k = 0; k < size; k++)
{
if (k == (size/2))
{
int *q = &ip[k];
int *p = &ip[k+1];
swapNum(q,p);
break;
}
else
swap(ip[k], ip[size-k]);
}
}
For example when k is equal to 0 then you call
swap(ip[0], ip[size]);
However the array has no element with index size.
ALso you mess two functions std::swap and swapNum
This code snippet also is invalid
if (k == (size/2))
{
int *q = &ip[k];
int *p = &ip[k+1];
swapNum(q,p);
break;
}
When size is an even number (or an odd number) as in your code then you make incorrect swap. For example if size is equal to 20 then you should swap ip[9[ with ip[10]. However according to the code snippet above you swap ip[10] with ip[11].
You could use standard algorithm std::reverse
for example
#include <algorithm>
#include <iterator>
//...
std::reverse( std::begin( arr ), std::end( arr ) );
or
#include <algorithm>
//...
std::reverse( arr, arr + size );
If you want to write the function yourself then it could look as
void reverse( int a[], int size )
{
for (int k = 0; k < size / 2; k++)
{
int tmp = a[k];
a[k] = a[size-k-1];
a[size-k-1] = tmp;
}
}
Or if you want to use your function swapNum then
void reverse( int a[], int size )
{
for (int k = 0; k < size / 2; k++)
{
swapNum( &a[k], &a[size-k-1] );
}
}
EDIT: I removed qualifier const from the first parameter that was a typo.
I've looked up some websites but I couldn't find an answer to my problem.
Here's my code:
#include "stdafx.h"
#include <iostream>
#include <math.h>
#include <time.h>
#include<iomanip>
#include<array>
#include <algorithm>
using namespace std;
const int AS = 6;
int filling(void);
void printing(int[AS][AS]);
int forsorting(int[][AS], int);
int main()
{
int funny = 0;
int timpa = 0;
int counter = 0;
int Array[AS][AS];
srand(time(0));
for (int i = 0; i<AS; i++)
{
for (int j = 0; j<AS; j++)
Array[i][j] = filling();
}
cout << "The unsorted array is" << endl << endl;
printing(Array);
cout << "The sorted array is" << endl << endl;
for (int il = 0; il<AS; il++)
{
for (int elle = 0; elle<AS; elle++)
Array[il][elle] =forsorting(Array, funny);
printing(Array);
}
system("PAUSE");
return 0;
}
int filling(void)
{
int kira;
kira = rand() % 87 + 12;
return kira;
}
void printing(int Array[AS][AS])
{
int counter = 0;
for (int i = 0; i<AS; i++)
{
for (int j = 0; j<AS; j++)
{
cout << setw(5) << Array[i][j];
counter++;
if (counter%AS == 0)
cout << endl << endl;
}
}
}
int forsorting(int Array[AS][AS], int funny)
{
int c, tmp, x;
int dice = 0;
int Brray[AS*AS];
int timpa = 0;
int super = 0;
//Transofrming Array[][] into Brray[]
for (int i = 0; i < AS; i++)
{
for (int k = 0; k < AS; k++)
{
Brray[timpa] = Array[i][k];
timpa++;
}
}
//Bubble sorting in Brray[]
for (int passer = 1; passer <= AS-1; passer++)
{
for (int timon = 1; timon <= AS-1; timon++)
{
if (Brray[timpa]>Brray[timpa + 1])
{
super = Brray[timpa];
Brray[timpa] = Brray[timpa + 1];
Brray[timpa + 1] = super;
}
}
}
//Transforming Brray[] into Array[][]
for (int e = 0; e<AS; e++)
{
for (int d = 0; d<AS; d++)
{
Brray[dice] = Array[e][d];
dice++;
}
}
***There's a part missing here***
}
What I have to do is, write a program using 3 functions.
The 1st function would fill my 2D array randomly (no problem with this part)
the 2nd function would print the unsorted array on the screen (no problem with this part)
and the 3rd function would sort my array diagonally as shown in this picture:
Then I need to call the 2nd function to print the sorted array. My problem is with the 3rd function I turned my 2D array into a 1D array and sorted it using Bubble sorting, but what I can't do is turn it back into a 2D array diagonaly sorted.
If you can convert from a 2D array to a 1D array, then converting back is the reverse process. Take the same loop and change around the assignment.
However in your case the conversion itself is wrong. It should take indexes in the order (0;0), (0;1), (1;0). But what it does is take indexes in the order (0;0), (0;1), (1;1).
My suggestion is to use the fact that the sum of the X and Y coordinates on each diagonal is the same and it goes from 0 to AS*2-2.
Then with another loop you can check for all possible valid x/y combinations. Something like this:
for ( int sum = 0; sum < AS*2-1; sum++ )
{
for ( int y = sum >= AS ? sum-AS+1 : 0; y < AS; y++ )
{
x = sum - y;
// Here assign either from Array to Brray or from Brray to Array
}
}
P.S. If you want to be really clever, I'm pretty sure that you can make a mathematical (non-iterative) function that converts from the index in Brray to an index-pair in Array, and vice-versa. Then you can apply the bubble-sort in place. But that's a bit more tricky than I'm willing to figure out right now. You might get extra credit for that though.
P.P.S. Realization next morning: you can use this approach to implement the bubble sort directly in the 2D array. No need for copying. Think of it this way: If you know a pair of (x;y) coordinates, you can easily figure out the next (x;y) coordinate on the list. So you can move forwards through the array from any point. That is all the the bubble sort needs anyway.
Suppose you have a 0-based 1-dimensional array A of n = m^2 elements. I'm going to tell you how to get an index into A, given and a pair of indices into a 2D array, according to your diagonalization method. I'll call i the (0-based) index in A, and x and y the (0-based) indices in the 2D array.
First, let's suppose we know x and y. All of the entries in the diagonal containing (x,y) have the same sum of their coordinates. Let sum = x + y. Before you got to the diagonal containing this entry, you iterated through sum earlier diagonals (check that this is right, due to zero-based indexing). The diagonal having sum k has a total of k + 1 entries. So, before getting to this diagonal, you iterated through 1 + 2 + ... + (sum - 1) entries. There is a formula for a sum of the form 1 + 2 + ... + N, namely N * (N + 1) / 2. So, before getting to this diagonal, you iterated through (sum - 1) * sum / 2 entries.
Now, before getting to the entry at (x,y), you went through a few entries in this very diagonal, didn't you? How many? Why, it's exactly y! You start at the top entry and go down one at a time. So, the entry at (x,y) is the ((sum - 1) * sum / 2 + y + 1)th entry, but the array is zero-based too, so we need to subtract one. So, we get the formula:
i = (sum - 1) * sum / 2 + y = (x + y - 1) * (x + y) / 2 + y
To go backward, we want to start with i, and figure out the (x,y) pair in the 2D array where the element A[i] goes. Because we are solving for two variables (x and y) starting with one (just i) and a constraint, it is trickier to write down a closed formula. In fact I'm not convinced that a closed form is possible, and certainly not without some floors, etc. I began trying to find one and gave up! Good luck!
It's probably correct and easier to just generate the (x,y) pairs iteratively as you increment i, keeping in mind that the sums of coordinate pairs are constant within one of your diagonals.
Store the "diagonally sorted" numbers into an array and use this to display your sorted array. For ease, assume 0-based indexing:
char order[] = { 0, 1, 3, 6, 10, 2, 4, 7, 11, 15, .. (etc)
Then loop over this array and display as
printf ("%d", Array[order[x]]);
Note that it is easier if your sorted Array is still one-dimensional at this step. You'd add the second dimension only when printing.
Following may help you:
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <vector>
template<typename T>
class DiagArray
{
public:
DiagArray(int size) : width(size), data(size * size), orders(size * size)
{
buildTableOrder(size);
}
const T& operator() (int x, int y) const { return data[orders[width * y + x]]; }
T& operator() (int x, int y) { return data[orders[width * y + x]]; }
void sort() { std::sort(data.begin(), data.end()); }
void display() const {
int counter = 0;
for (auto index : orders) {
std::cout << std::setw(5) << data[index];
counter++;
if (counter % width == 0) {
std::cout << std::endl;
}
}
}
private:
void buildTableOrder(int size)
{
int diag = 0;
int x = 0;
int y = 0;
for (int i = 0; i != size * size; ++i) {
orders[y * size + x] = i;
++y;
--x;
if (x < 0 || y >= size) {
++diag;
x = std::min(diag, size - 1);
y = diag - x;
}
}
}
private:
int width;
std::vector<T> data;
std::vector<int> orders;
};
int main(int argc, char *argv[])
{
const int size = 5;
DiagArray<int> da(size);
for (int y = 0; y != size; ++y) {
for (int x = 0; x != size; ++x) {
da(x, y) = size * y + x;
}
}
da.display();
std::cout << std::endl;
da.sort();
da.display();
return 0;
}
Thank you for your assistance everyone, what you said was very useful to me. I actually was able to think about clearly and came up with a way to start filling the array based on your recommendation, but one problem now, Im pretty sure that my logic is 99% right but there's a flaw somewhere. After I run my code the 2nd array isnt printed on the screen. Any help with this?
#include "stdafx.h"
#include <iostream>
#include <math.h>
#include <time.h>
#include<iomanip>
#include<array>
#include <algorithm>
using namespace std;
const int AS = 5;
int filling(void);
void printing(int[AS][AS]);
int forsorting(int[][AS], int);
int main()
{
int funny = 0;
int timpa = 0;
int counter = 0;
int Array[AS][AS];
srand(time(0));
for (int i = 0; i<AS; i++)
{
for (int j = 0; j<AS; j++)
Array[i][j] = filling();
}
cout << "The unsorted array is" << endl << endl;
printing(Array);
cout << "The sorted array is" << endl << endl;
for (int il = 0; il<AS; il++)
{
for (int elle = 0; elle<AS; elle++)
Array[il][elle] =forsorting(Array, funny);
}
printing(Array);
system("PAUSE");
return 0;
}
int filling(void)
{
int kira;
kira = rand() % 87 + 12;
return kira;
}
void printing(int Array[AS][AS])
{
int counter = 0;
for (int i = 0; i<AS; i++)
{
for (int j = 0; j<AS; j++)
{
cout << setw(5) << Array[i][j];
counter++;
if (counter%AS == 0)
cout << endl << endl;
}
}
}
int forsorting(int Array[AS][AS], int funny)
{int n;
int real;
int dice = 0;
int Brray[AS*AS];
int timpa = 0;
int super = 0;
int median;
int row=0;
int col=AS-1;
//Transofrming Array[][] into Brray[]
for (int i = 0; i < AS; i++)
{
for (int k = 0; k < AS; k++)
{
Brray[timpa] = Array[i][k];
timpa++;
}
}
//Bubble sorting in Brray[]
for (int passer = 1; passer <= AS-1; passer++)
{
for (int timon = 1; timon <= AS-1; timon++)
{
if (Brray[timpa]>Brray[timpa + 1])
{
super = Brray[timpa];
Brray[timpa] = Brray[timpa + 1];
Brray[timpa + 1] = super;
}
}
}
//Transforming Brray[] into sorted Array[][]
for(int e=4;e>=0;e--)//e is the index of the diagonal we're working in
{
if(AS%2==0)
{median=0.5*(Brray[AS*AS/2]+Brray[AS*AS/2-1]);
//We start filling at median - Brray[AS*AS/2-1]
while(row<5 && col>=0)
{real=median-Brray[AS*AS/2-1];
Array[row][col]=Brray[real];
real++;
col--;
row++;}
}
else {
median=Brray[AS*AS/2];
//We start filling at Brray[AS*AS/2-AS/2]
while(row<5 && col>=0)
{real=Brray[AS*AS/2-AS/2];
n=Array[row][col]=Brray[real];
real++;
col--;
row++;}
}
}
return n;
}
Thanks again for your assistance