Random matrix multiplication [closed] - c++

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 months ago.
Improve this question
I need to create at least 2 matrix 4x4, multiplicate them and display the result, but I'm getting this thing as as result img
I'm creating matrix a[i][j] and matrix b[k][l], and trying to pass the result to a new matrix called c[i][j]
Besides that, I need to make 2 kinds of matrix multiplication, one like this, and another one like this
Can you please please please help? Code below
#include<iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;
int matriz1() {
int a[4][4], i, j;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
a[i][j] = rand() % 100 + 1;
}
}
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
std::cout << a[i][j] << '\t';
std::cout << '\n';
}
std::cout << '\n';
std::cout << "x" << std::endl;
std::cout << '\n';
std::cout << "Matriz 2:" << std::endl;
int b[4][4], k, l;
for (k = 0; k < 4; ++k)
{
for (l = 0; l < 4; ++l)
{
b[k][l] = rand() % 100 + 1;
}
}
for (k = 0; k < 4; ++k)
{
for (l = 0; l < 4; ++l)
std::cout << b[k][l] << '\t';
std::cout << '\n';
}
std::cout << '\n';
int c[4][4], m, n, x;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
for (k = 0; k < 4; k++) {
c[i][j] += a[i][k] * b[k][j];
}
}
}
cout << " RESULTADO!!!!!!!!!!!!!!!!!!!!!!" << endl;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
cout << c[i][j] << "\t";
}
cout << "\n";
}
return 0;
}
int main()
{
srand(time(0));
std::cout << "Matriz 1:" << std::endl;
std::cout << matriz1() << std::endl;
}
SOLVED IN THE COMMENTS! Stop disliking my post its my first post

You do this:
c[i][j] += a[i][k] * b[k][j];
but you never initialized c array, it contains random values, likely something like
0xCDCDCDCD (-842150451). Initialize it like this:
int c[4][4] = {}
You have repeated code, so consider to break it up in functions, e.g. you can initialize matrices as functions and output one as another. THat would make code more readable and easier to find errors.

A common "Beginner's Problem" is writing too much code. One consequence is that there are too many places where bugs and other flaws can hide.
This is in 'C', but the only 'C++' aspect of your code is using cout for output. printf() can also be used with C++.
#include <stdio.h>
#include <stdlib.h>
void fill4x4( int a[][4] ) {
for( int r = 0; r < 4; r++ )
for( int c = 0; c < 4; c++ )
a[r][c] = rand() % 100 + 1;
}
void show4x4( int a[][4] ) {
for( int r = 0; r < 4; r++ )
for( int c = 0; c < 4; c++ )
printf( "%5d%c", a[r][c], " \n"[c] );
puts( "" );
}
int showPair( int a, int b, int pos ) {
printf( "%2dx%-2d%c", a, b, " \n"[pos] );
return a * b;
}
void mult4x4( int a[][4], int b[][4], int d[][4], bool x ) {
for( int r = 0; r < 4; r++ )
for( int c = 0; c < 4; c++ )
// assign (=), not accumulate (+=)
// notice the 'exchange' of row/col access of 'b[][]'
if( x )
d[r][c] = showPair( a[r][c], b[r][c], c );
else
d[r][c] = showPair( a[r][c], b[c][r], c );
puts( "" ); show4x4( d );
}
int main()
{
srand(time(0));
int a[4][4]; fill4x4( a ); show4x4( a );
int b[4][4]; fill4x4( b ); show4x4( b );
int d[4][4];
mult4x4( a, b, d, true );
mult4x4( a, b, d, false );
return 0;
}
Copy, paste, compile and run this to see the (random) output.
EDIT: Pointed out by a question from the OP, here's a further compaction of one function that may-or-may-not be self-evident:
void mult4x4( int a[][4], int b[][4], int d[][4], bool x ) {
for( int r = 0; r < 4; r++ )
for( int c = 0; c < 4; c++ )
d[r][c] = showPair( a[r][c], x?b[r][c]:b[c][r], c );
puts( "" ); show4x4( d );
}
Further EDIT: A common problem for those with time to fill is mucking around, shrinking code that already works. Here's the result of some of that..
#include <stdio.h>
#include <stdlib.h>
char *fmt1 = "%5d%.2s";
char *fmt2 = "%2dx%-2d%.2s";
char *tail1 = " ::";
char *tail2 = " \n";
void show2x4x4( int a[][4], int b[][4] ) {
for( int r = 0, c; r < 4; r++ ) {
for( c = 0; c < 4; c++ ) printf( fmt1, a[r][c], &tail1[c+c] );
for( c = 0; c < 4; c++ ) printf( fmt1, b[r][c], &tail2[c+c] );
}
puts( "" );
}
int main() {
srand(time(0));
int r, c, v, a[4][4], b[4][4], d[4][4], e[4][4], *px, *py;
// fill 2 4x4 arrays of random ints as if both were 1x16
for( px = &a[0][0], py = &b[0][0], v = 0; v < 4 * 4; v++ ) {
int num = rand();
*px++ = num % 100; // two digits only
*py++ = num / 100 % 100;
}
show2x4x4( a, b ); // display
// show and perform the calc of the product matrices
for( r = 0; r < 4; r++ ) {
for( c = 0; c < 4; c++ ) {
printf( fmt2, a[r][c], b[r][c], &tail1[c+c] );
d[r][c] = a[r][c] * b[r][c];
}
for( c = 0; c < 4; c++ ) { // note b[] swaps col & row
printf( fmt2, a[r][c], b[c][r], &tail2[c+c] );
e[r][c] = a[r][c] * b[c][r];
}
}
puts( "" );
show2x4x4( d, e ); // show both products
return 0;
}
Output
29 66 71 20 : 35 88 22 22
35 80 36 85 : 53 1 28 54
12 14 12 71 : 95 98 92 19
62 61 89 17 : 94 63 32 43
29x35 66x88 71x22 20x22 :29x35 66x53 71x95 20x94
35x53 80x1 36x28 85x54 :35x88 80x1 36x98 85x63
12x95 14x98 12x92 71x19 :12x22 14x28 12x92 71x32
62x94 61x63 89x32 17x43 :62x22 61x54 89x19 17x43
1015 5808 1562 440 : 1015 3498 6745 1880
1855 80 1008 4590 : 3080 80 3528 5355
1140 1372 1104 1349 : 264 392 1104 2272
5828 3843 2848 731 : 1364 3294 1691 731

Related

Find similar numbers - array inconsistency

I'm trying to solve a simple beginner exercise, I compare two arrays and find the numbers that appear in both. The result is put into another array called result. For whatever reason the result should contain "2 44 55" but it shows "2 1 10 10". What did I do wrong?
#include <iostream>
void common_elements(int array_1[], int array_2[]){
int result[] {0};
int counter{0};
for (int i{0}; i < 10; i++){
for (int j{0}; j < 10; j++){
if (array_2[i] == array_1[j]){
result[counter] = array_1[j];
counter++;
}
}
}
if (counter == 0) {
std::cout << "There are 0 common elements";
} else {
std::cout << "There are " << counter << " common elements they are : ";
for (int k{0}; k < counter; k++){
std::cout << result[k] << " ";
}
}
}
int main(){
int data1[] {1,2,4,5,9,3,6,7,44,55};
int data2[] {11,2,44,45,49,43,46,47,55,88};
common_elements(data1,data2);
return 0;
}
I'm confused because when I std::cout the numbers during examination (two nested loops), the result is correct.
It is just containing one single element, because the compiler deduces the length to 1. This would mean the 2 is valid, all other values are "out of bound". Thanks for your help. I repaired it to
int result[10]{0};
Now it's working, thanks a lot.
Btw: It is a C++ course but it starts from the very beginning. That why this looks like C.
For starters the function should be declared at least like
std::vector<int> common_elements( const int array_1[], size_t n1,
const int array_2[], size_t n2 );
Using the magic number 10 within the function as
for (int i{0}; i < 10; i++){
does not make sense. The function can be called for arrays that have different numbers of elements.
This declaration of an array
int result[] {0};
declares an array with only one element that also does not make sense.
Also the function should not output any message. It is the caller of the function that decides whether to output a message. The function should return a sequence of common elements of two arrays.
The function can be defined the following way
#include <vector>
#include <iterator>
#include <functional>
//...
std::vector<int> common_elements( const int array_1[], size_t n1,
const int array_2[], size_t n2 )
{
std::vector<int> v;
if ( n1 != 0 && n2 != 0 )
{
if ( n2 < n1 )
{
std::swap( n1, n2 );
std::swap( array_1, array_2 );
}
for ( size_t i = 0; i < n1; i++ )
{
size_t count = 1;
for ( size_t j = 0; j < i; j++ )
{
if ( array_1[j] == array_1[i] ) ++count;
}
for ( size_t j = 0; count != 0 && j < n2; j++ )
{
if ( array_2[j] == array_1[i] )
{
--count;
}
}
if ( count == 0 ) v.push_back( array_1[i] );
}
}
return v;
}
And in main the function is called like
int data1[] {1,2,4,5,9,3,6,7,44,55};
int data2[] {11,2,44,45,49,43,46,47,55,88};
auto v = common_elements( data1, std::size( data1 ), data2, std::size( data2 ) );
if ( std::size( v ) == 0 )
{
std::cout << "There are 0 common elements";
}
else
{
std::cout << "There are " << std::size( v ) << " common elements they are : ";
for ( const auto &item : v )
{
std::cout << item << ' ';
}
std::cout << '\n';
}
Instead of the vector you could use std::map<intg, size_t>. In this case the container will contain how many times a common number is encountered in the both arrays.
Here is a demonstration program.
#include <iostream>
#include <vector>
#include <iterator>
#include <functional>
std::vector<int> common_elements( const int array_1[], size_t n1,
const int array_2[], size_t n2 )
{
std::vector<int> v;
if (n1 != 0 && n2 != 0)
{
if (n2 < n1)
{
std::swap( n1, n2 );
std::swap( array_1, array_2 );
}
for (size_t i = 0; i < n1; i++)
{
size_t count = 1;
for (size_t j = 0; j < i; j++)
{
if (array_1[j] == array_1[i]) ++count;
}
for (size_t j = 0; count != 0 && j < n2; j++)
{
if (array_2[j] == array_1[i])
{
--count;
}
}
if (count == 0) v.push_back( array_1[i] );
}
}
return v;
}
int main()
{
int data1[]{ 1,2,4,5,9,3,6,7,44,55 };
int data2[]{ 11,2,44,45,49,43,46,47,55,88 };
auto v = common_elements( data1, std::size( data1 ), data2, std::size( data2 ) );
if (std::size( v ) == 0)
{
std::cout << "There are 0 common elements";
}
else
{
std::cout << "There are " << std::size( v ) << " common elements they are : ";
for (const auto &item : v)
{
std::cout << item << ' ';
}
std::cout << '\n';
}
}
The program output is
There are 3 common elements they are : 2 44 55

printing stack in the incorrect order in c++

I have a function that pushes down all non zero integers to the top of my array and then reprints it in a 3x3 matrix.
the problem i am having is when i push all the non zero integers into my stack it reverses the order.
** the indexing of my array is backwards. ie, in a 3x3 matrix the coordinates (0,0) would be the bottom left **
here is the relevant code:
void State::pushDown() {
std::stack<int> tempStack;
for ( int c = 0; c < BOARDSIZE; c++ )
{
for ( int r = 0; r < BOARDSIZE ; r++ )
{
if ( grid[r][c] != 0 ) tempStack.push( grid[r][c] );
}
for ( int r = BOARDSIZE; r != 0; --r )
{
if ( !tempStack.empty() )
{
grid[r-1][c] = tempStack.top();
tempStack.pop();
}
else
{
grid[r-1][c] = 0;
}
}
}
}
State() {
for (int i = 0; i < BOARDSIZE; i++)
for (int j = 0; j < BOARDSIZE; j++)
grid[i][j] = rand() % 7;
}
void State::printBoard() {
cout << endl;
for (int i = 0; i < BOARDSIZE; i++) {
for (int j = 0; j < BOARDSIZE; j++) {
cout << " " << grid[BOARDSIZE - i - 1][j] << " ";
}
cout << endl;
}
}
int main() {
srand(time(0));
State state;
state.printBoard();
state.pushDown();
state.printBoard();
return 0;
}
here is my current output:
before push down function
045
504
226
after push down function:
006
224
545
as you can see it successfully pushes the non zero elements to the bottom of the matrix however in the process it reverses the order of the other numbers and i believe this is because of the stack.
my expected output would be the following:
before push down function
045
504
226
after push down function:
005
544
226
My question is- how can i fix my function so that the order of the elements remain the same without reversing.
Here is a demonstrative program that shows how the loops can be defined.
#include <iostream>
#include <stack>
const int BOARDSIZE = 3;
void reformat( int ( &a )[BOARDSIZE][BOARDSIZE] )
{
std::stack<int> tempStack;
for ( int c = 0; c < BOARDSIZE; c++ )
{
for ( int r = 0; r < BOARDSIZE ; r++ )
{
if ( a[r][c] != 0 ) tempStack.push( a[r][c] );
}
for ( int r = BOARDSIZE; r != 0; --r )
{
if ( !tempStack.empty() )
{
a[r-1][c] = tempStack.top();
tempStack.pop();
}
else
{
a[r-1][c] = 0;
}
}
}
}
int main()
{
int a[BOARDSIZE][BOARDSIZE] =
{
{ 0, 4, 5 },
{ 5, 0, 4 },
{ 2, 2, 6 }
};
for ( const auto &row : a )
{
for ( const auto &item : row ) std::cout << item << ' ';
std::cout << '\n';
}
std::cout << '\n';
reformat( a );
for ( const auto &row : a )
{
for ( const auto &item : row ) std::cout << item << ' ';
std::cout << '\n';
}
std::cout << '\n';
return 0;
}
Its output is
0 4 5
5 0 4
2 2 6
0 0 5
5 4 4
2 2 6
If you are outputting the array starting from its last row then use the following loops
#include <iostream>
#include <stack>
const int BOARDSIZE = 3;
void reformat( int ( &a )[BOARDSIZE][BOARDSIZE] )
{
std::stack<int> tempStack;
for ( int c = 0; c < BOARDSIZE; c++ )
{
for ( int r = 0; r < BOARDSIZE ; r++ )
{
if ( a[BOARDSIZE-r-1][c] != 0 ) tempStack.push( a[BOARDSIZE-r-1][c] );
}
for ( int r = 0; r != BOARDSIZE; ++r )
{
if ( !tempStack.empty() )
{
a[r][c] = tempStack.top();
tempStack.pop();
}
else
{
a[r][c] = 0;
}
}
}
}
int main()
{
int a[BOARDSIZE][BOARDSIZE] =
{
{ 2, 2, 6 },
{ 5, 0, 4 },
{ 0, 4, 5 }
};
for ( size_t i = 0; i < BOARDSIZE; i++ )
{
for ( const auto &item : a[BOARDSIZE - i - 1] ) std::cout << item << ' ';
std::cout << '\n';
}
std::cout << '\n';
reformat( a );
for ( size_t i = 0; i < BOARDSIZE; i++ )
{
for ( const auto &item : a[BOARDSIZE - i - 1] ) std::cout << item << ' ';
std::cout << '\n';
}
std::cout << '\n';
return 0;
}
The program output is the same as shown above
0 4 5
5 0 4
2 2 6
0 0 5
5 4 4
2 2 6
But now the array is outputted starting from its last line.

minimizing memory use in c++

I was working on a problem in codeforces and I have no problems in the functionality of the code but the code exceeds the memory usage. Can someone explain how to improve this? How to learn about memory management in general while programming because I didn't find anything related to that. Here's my code :
Summary of the problem: You are given 6 input numbers, the first 5 numbers should be multiplied each by another integer and the summation of them after multiplication is the sixth integer in the input. You should find all the combinations of the numbers the can be multiplied by each value in the input to seek the summation. the output is basically the sum of the integers chosen for each number in the input to be multiplied by.
#include <iostream>
#include <vector>
#ifndef MAX
#define MAX 100
#endif
using namespace std;
void storeAndFilter(vector <int> &arr,int chosenNumConst, int mypasha);
void print(vector<int> &v);
int printsum(vector<int> &v);
int main(int argc, char const *argv[])
{
//array of input options
int a1, a2, a3, a4, a5, pasha;
cin >> a1 >> a2 >> a3 >> a4 >> a5 >> pasha;
//declarations of vectors
vector<int> arrStrA1;
vector<int> arrStrA2;
vector<int> arrStrA3;
vector<int> arrStrA4;
vector<int> arrStrA5;
//sorting and filtering the vectors
storeAndFilter(arrStrA1,a1,pasha);
storeAndFilter(arrStrA2,a2,pasha);
storeAndFilter(arrStrA3,a3,pasha);
storeAndFilter(arrStrA4,a4,pasha);
storeAndFilter(arrStrA5,a5,pasha);
//cout<<"All Posibilities valid (Minimized by removing values < pasha) : "<<endl;
// print (arrStrA1);
// print (arrStrA2);
// print (arrStrA3);
// print (arrStrA4);
// print (arrStrA5);
//scores vectors
vector<int> resultsA1;
vector<int> resultsA2;
vector<int> resultsA3;
vector<int> resultsA4;
vector<int> resultsA5;
int i,j,k,l,m;
for (i=0; i < (int)arrStrA1.size(); ++i)
{
for (j=0; j < (int)arrStrA2.size(); ++j)
{
for (k=0; k < (int)arrStrA3.size(); ++k)
{
for (l=0; l < (int)arrStrA4.size(); ++l)
{
for (m=0; m < (int)arrStrA5.size(); ++m)
{
if(arrStrA1.at(i)+arrStrA2.at(j)+arrStrA3.at(k)+arrStrA4.at(l)+arrStrA5.at(m)==pasha)
{
resultsA1.push_back(arrStrA1.at(i));
resultsA2.push_back(arrStrA2.at(j));
resultsA3.push_back(arrStrA3.at(k));
resultsA4.push_back(arrStrA4.at(l));
resultsA5.push_back(arrStrA5.at(m));
}
}
}
}
}
}
//divise each term by the card value
for (int i = 0; i < (int)resultsA1.size(); ++i)
{
if (a1==0)
resultsA1.at(i) /= 1;
else
resultsA1.at(i) /= a1;
}
for (int i = 0; i < (int)resultsA2.size(); ++i)
{
if (a2==0)
resultsA2.at(i) /= 1;
else
resultsA2.at(i) /= a2;
}
for (int i = 0; i < (int)resultsA3.size(); ++i)
{
if(a3==0)
resultsA3.at(i) /= 1;
else
resultsA3.at(i) /= a3;
}
for (int i = 0; i < (int)resultsA4.size(); ++i)
{
if (a4==0)
resultsA4.at(i) /= 1;
else
resultsA4.at(i) /= a4;
}
for (int i = 0; i < (int)resultsA5.size(); ++i)
{
if(a5==0)
resultsA5.at(i) /= 1;
else
resultsA5.at(i) /= a5;
}
//Uncomment to show the table list after division
// print(resultsA1);
// print(resultsA2);
// print(resultsA3);
// print(resultsA4);
// print(resultsA5);
int scra1=printsum(resultsA1);
int scra2=printsum(resultsA2);
int scra3=printsum(resultsA3);
int scra4=printsum(resultsA4);
int scra5=printsum(resultsA5);
cout << scra1 <<" "<< scra2 <<" "<< scra3 <<" "<<scra4 <<" "<< scra5 <<endl;
return 0;
}
void print(vector<int> &v)
{
int size = v.size();
cout<<"========================"<<endl;
for (int i = 0; i < size; ++i)
cout<<v.at(i)<<endl;
cout<<"========================"<<endl;
}
int printsum(vector<int> &v)
{
int sum =0;
for (int i = 0; i < (int)v.size(); ++i)
sum += v.at(i);
return sum;
}
void storeAndFilter(vector <int> &arr,int chosenNumConst, int mypasha)
{
arr.reserve(10);
int i=0;
for (; i <= MAX; ++i)
{
arr.push_back(i*chosenNumConst);
if (arr.at(i)>mypasha)
break;
}
arr.resize(i);
}
Some stuff that I thought about:
Arrays instead of Vectors maybe better
The nested for loops may be the one that is taking too much memory
But to be clear, the nested for loops doesn't make too much calculations, they find all the combinations of 5 numbers '5 loops' to sum to a specific value. Filtering before entering the loop is applied so maybe the nested loop isn't the issue.
Max memory constrain in the problem is: 256 MB
You can use much less memory by not using all those vectors. You can just write your code like this:
// make sure we handle zero properly
auto end = [&](int num){
return num == 0 ? num : pasha/num;
};
for (auto i=0, end_i = end(a1); i <= end_i; ++i)
{
for (auto j=0, end_j = end(a2); j <= end_j; ++j)
{
for (auto k=0, end_k = end(a3); k <= end_k; ++k)
{
for (auto l=0, end_l = end(a4); l <= end_l; ++l)
{
for (auto m=0, end_m = end(a5); m <= end_m; ++m)
{
if(a1*i+a2*j+a3*k+a4*l+a5*m==pasha)
{
std::cout << i << " " << j << " " << k << " " << l << " " << m << "\n";
}
}
}
}
}
}
and it outputs all the valid results. For Example for the input 0 2 3 4 5 6 it produces
0 0 2 0 0
0 1 0 1 0
0 3 0 0 0
See working example here

C++ TopDown Pyramid

I had an idea to make a program that would take user input and make a... I am not quite sure how to call it correctly, so my WIP is top down pyramid. So that we don't get confused it should look something like this.
If c is 5:
11111
10001
10101
10001
11111
If c is 7:
0000000
0111110
0100010
0101010
0100010
0111110
0000000
Here is an image to help visualize the problem
The only conditions are that there has to be a 1 in the middle and that cin is odd.
Now, I've been thinking about it in my spare time and it seemed quite easy in my head, but when I try to put my thoughts into my code it never works out.
Is there anyone who could help me? I am quite desperate .-.
PS: Here is my WIP code so far (Please excuse my Czech ints and texts)
#include <iostream>
using namespace std;
void FillArray(int **PyramidArray,int a,int b,int c);
void ExtractArray(int **PyramidArray,int a,int b,int c);
int main()
{
cout << "input array size.(only odd numbers)" << endl;
int c;
cin >> c;
if (c%2 == 0)
{
cout << "Only odd numbers!" << endl;
return 1;
}
int **PyramidArray;
PyramidArray = new int*[c];
for (int i =0;i<c;i++)
{
PyramidArray[i] = new int[i];
}
FillArray(PyramidArray,c,c,c);
ExtractArray(PyramidArray,c,c,c);
return 0;
}
void FillArray(int **PyramidArray, int a, int b, int c)
{
for(int i=0;i<a;i++)
{
for (int j=0;j<b;j++)
{
PyramidArray [i][j] = 1;
}
}
}
void ExtractArray(int **PyramidArray, int a,int b,int c)
{
for(int i=0;i<a;i++)
{
for (int j=0;j<b;j++)
{
cout << PyramidArray [i][j] << " ";
}
cout << endl;
}
cout << endl;
}
For solving this kind of problem, if you find you need a new, then something is wrong. Just keep tracing the current state of printing, everything can be done in one-pass.
#include <iostream>
int main() {
int n = 0, half_n = 0;
std::cin >> n;
if ( n % 2 == 0 ) return -1;
half_n = n / 2;
// the first symbol to print, 1 or 0
int start_symbol = 1 - half_n % 2;
// how many steps from beginning require alternating symbol ?
int alternate_range = 0;
// 0 for upperhalf, 1 for lowerhalf
int direct = 0;
for ( int i = 0; i < n; ++i ) {
int current_symbol = start_symbol;
for ( int j = 0; j < alternate_range; ++j ) {
std::cout << current_symbol;
current_symbol = 1 - current_symbol;
}
for ( int j = alternate_range; j < n - alternate_range; ++j ) {
std::cout << current_symbol;
}
for ( int j = n - alternate_range; j < n; ++j ) {
current_symbol = 1 - current_symbol;
std::cout << current_symbol;
}
std::cout << "\n";
if ( alternate_range == half_n ) {
direct = 1;
}
if ( direct == 0 ) {
++alternate_range;
} else {
--alternate_range;
}
}
}

C++ Remove the last new line

I'm using cout and endlto print some guides, the output (my intention) is like:
From Spot 1
Spot 2
Spot 5
Spot 8
Spot 6
To Spot 3
Here, the Spot No. is random and generated from some iterations. Because of iterations, i can only print the result like:
From Spot 1
Spot 2
Spot 5
Spot 8
Spot 6
Spot 3
Is there any method to remove my last new line Spot 3?
EDIT:
I want to find the shortest path (using Floyd-Warshall Algorithm) between two vertices. Here's my code, and it describes the following gragh:
#include <iostream>
using namespace std;
const int INF = 100000;
int n = 10, path[11][11], dist[11][11], map[11][11];
void init() {
int i, j;
for ( i = 1; i <= n; i++ )
for ( j = 1; j <= n; j++ )
map[i][j] = ( i == j ) ? 0:INF;
map[1][2] = 2, map[1][4] = 20, map[2][5] = 1;
map[3][2] = 3, map[4][3] = 8, map[4][6] = 6;
map[4][7] = 4, map[5][3] = 7, map[5][8] = 3;
map[6][3] = 1, map[7][8] = 1, map[8][6] = 2;
map[8][10] = 2, map[9][7] = 2, map[10][9] = 1;
}
void floyd() {
int i, j, k;
for ( i = 1; i <= n; i++ )
for ( j = 1; j <= n; j++ )
dist[i][j] = map[i][j], path[i][j] = 0;
for ( k = 1; k <= n; k++ )
for ( i = 1; i <= n; i++ )
for ( j = 1; j <= n; j++ )
if ( dist[i][k] + dist[k][j] < dist[i][j] )
dist[i][j] = dist[i][k] + dist[k][j], path[i][j] = k;
}
void output( int i, int j ) {
if ( i == j ) return;
if ( path[i][j] == 0 ) cout << "Spot" << j << endl;
else {
output( i, path[i][j] ); // iterations
output( path[i][j], j );
}
}
int main() {
int u, v;
init();
floyd();
u = 1, v = 3;
if ( dist[u][v] == INF ) cout << "No path" << endl;
else {
cout << "From Spot" << u << endl;
output( u, v );
cout << endl;
}
return 0;
}
The problem now is to find the conditon of the last iteration so that i can cout a different expression. But i think it is more easier to solve the problem by simply removing the last expression and rewriting, so i didnt attach my code.
EDIT 2:
I've achieved my purpose with the help of Fabian Tamp though it seems a little stupid of me writing the code above. Here goes the modified code:
#include <iostream>
#include <queue>
using namespace std;
const int INF = 100000;
int n = 10, path[11][11], dist[11][11], map[11][11];
void init() {
int i, j;
for ( i = 1; i <= n; i++ )
for ( j = 1; j <= n; j++ )
map[i][j] = ( i == j ) ? 0:INF;
map[1][2] = 2, map[1][4] = 20, map[2][5] = 1;
map[3][3] = 3, map[4][3] = 8, map[4][6] = 6;
map[4][7] = 4, map[5][3] = 7, map[5][8] = 3;
map[6][3] = 1, map[7][8] = 1, map[8][6] = 2;
map[8][10] = 2, map[9][7] = 2, map[10][9] = 1;
}
void floyd() {
int i, j, k;
for ( i = 1; i <= n; i++ )
for ( j = 1; j <= n; j++ )
dist[i][j] = map[i][j], path[i][j] = 0;
for ( k = 1; k <= n; k++ )
for ( i = 1; i <= n; i++ )
for ( j = 1; j <= n; j++ )
if ( dist[i][k] + dist[k][j] < dist[i][j] )
dist[i][j] = dist[i][k] + dist[k][j], path[i][j] = k;
}
void output( int i, int j, queue<int> &output_queue ) {
if ( i == j ) return;
if ( path[i][j] == 0 ) output_queue.push(j);
else {
output( i, path[i][j], output_queue); // iterations
output( path[i][j], j, output_queue);
}
}
void print_path(queue<int> output_queue) {
if (output_queue.empty()) return;
int item = output_queue.front();
while (!output_queue.empty()) {
item = output_queue.front();
output_queue.pop();
if (output_queue.empty()) {
cout << "To ";
}
cout << "Spot " << item << endl;
}
}
int main() {
int u, v;
init();
floyd();
u = 1, v = 3;
if ( dist[u][v] == INF ) cout << "No path" << endl;
else {
cout << "From Spot " << u << endl;
queue<int> output_queue;
output(u, v, output_queue);
print_path(output_queue);
}
return 0;
}
The output is the guide at the very beginning. Thank you all!
Change your output function thusly:
void output( int i, int j, Queue<int> &output_queue ) {
if ( i == j ) return;
if ( path[i][j] == 0 ) output_queue.push(j);
else {
output( i, path[i][j], output_queue); // iterations
output( path[i][j], j, output_queue);
}
}
Then change your main():
//....
else {
Queue<int> output_queue;
output_queue.push(u);
output(u, v, output_queue);
print_path(output_queue);
}
//...
Then add print_path:
void print_path(Queue<int> output_queue) {
if (output_queue.empty()) return;
auto item = output_queue.front();
cout << "From Spot " << item << endl;
while (!output_queue.empty()) {
item = output_queue.front();
output_queue.pop();
if (output_queue.empty()) {
cout << "To ";"
}
cout << "Spot " << item << endl;
}
}
A couple of things here:
I haven't compiled or tested this. Try and figure out any errors yourself and letting me know in the comments.
It would be really helpful for you to look at the STL. http://www.cplusplus.com/reference is a great resource for this.
If you're not familiar with passing by reference, that's the strategy I used to make sure that we're adding information to the same output_queue. Note that I've passed by copy for print_path() because it destroys the data in the parameter. It's one of the most powerful techniques in C++.
if you have how many lines you had printed you can use this macro
#define gotoxy(a,b) {COORD coord; coord.X=(b); coord.Y=(a) ; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);}
and go to that line and print " " for all characters you had printed.
It will make it easier if you do not print a newline after each line. Then you can go back and "erase" the text on the current line by outputting a number of "\b" (backspace) characters equal to the number of characters on the line, followed by the same number of spaces (to wipe out what was there). Then you can return to the beginning of the line by writing "\r" and write the whole line again.