Program for finding the transpose of given matrix - c++

I was thinking the approach to finding the transpose of a matrix and
below is the algorithm but it is not giving me proper output , so
anyone can tell me where I have done mistake and what should be proper
algorithm ? And how can I improve it ?
// m is the number of rows and n is the number of columns in a matrix
for (int i = 0; i < m; i++) // For swapping the non-diagonal elements
{
for (int j = 0; j < n; j++)
{
if (i != j)
{
int temp = 0;
temp = a[i][j];
a[i][j] = a[j][i];
a[j][i] = temp;
}
}
}
cout << "Elements of transpose matrix of a is: " << endl;
for (int i = 0; i < m; i++) // printing the elements after transpose
{
for (int j = 0; j < n; j++)
{
cout << a[i][j] << " ";
}
cout << endl;

You made the same mistake one can make while reversing a 1D array, hence I will use that as a simpler example:
#include <vector>
#include <iostream>
#include <utility>
std::vector<int> reverse_broken(std::vector<int> x){
for (size_t i=0;i< x.size(); ++i){
std::swap(x[i],x[x.size()-1-i]);
}
return x;
}
int main(){
auto x = reverse_broken({1,2,3,4});
for (const auto& e : x) std::cout << e << " ";
}
output:
1 2 3 4
reverse_broken iterates all elements and swaps them with the respective reversed element. However, once the first has been swapped with the last, the last has already been swapped. Later swapping the last with the first puts them in the original order again.
Same with your transpose. Once you swapped an element above the diagonal with one below the diagonal, they are already transposed. You don't need to swap them again.
I'll show you the fix for the reverse_broken and leave it to you to apply same fix to your transpose:
std::vector<int> reverse(std::vector<int> x){
for (size_t i=0;i< x.size()/2; ++i){
// stop in the middle ^^ because then all elements have been swapped
std::swap(x[i],x[x.size()-1-i]);
}
return x;
}
You should also consider to not transpose the matrix at all. Depending on how often you access swapped elements and how you populate it, it will be cheaper to either populate it in right order from the start, or just swapping the indices on access:
// normal access:
auto x = a[i][j];
// transposed access:
auto y = a[j][i];
PS: I used reverse only for illustration. To reverse a container you should actually use std::reverse. Also note that you can and should use std::swap. And last but not least, only a square matrix can be transposed in place. For a non square matrix you need to construct a new one with different dimensions.

Related

Comparing elements in an array?

as the title says I'm attempting to compare elements in an array. My intent is to have the user enter 3 integers into the program, thereafter it should increment through this array comparing the the 1st number to the 2nd, and so forth and swapping the element's from order of lowest to highest.
My issue currently is that it will swap the first and second elements but the third causes an integer overflow due to me comparing and assigning an integer in an index higher than the initialized array can hold.
I'm currently drawing a blank as to how I could still compare these numbers in this manner without causing it to overflow.
A hint or perhaps a whole different perspective would be appreciated.
#include "E:/My Documents/Visual Studio 2017/std_lib_facilities.h"
int main()
{
cout << "Enter three integers: \n";
int numbersArray[3];
int temp = 0; //This lets us hold our integers temporarily so we can swap them around in the array
//This enters integers as elements in the array
for (int i = 0; i < 3; i++)
{
cin >> numbersArray[i];
}
//This should swap the elements from smallest to greatest
for (int i = 0; i = 3; i++)
{
if (numbersArray[i] > numbersArray[i+1])
temp = numbersArray[i];
numbersArray[i] = numbersArray[i+1];
numbersArray[i+1] = temp;
//swap(numbersArray[i], numbersArray[++i]);
}
//This prints the index's containing the elements in the array
for (int i = 0; i < 3; i++)
{
cout << numbersArray[i] << ' ';
}
cout << endl;
keep_window_open();
return 0;
}
You will need to modify this to suit your needs, but this should get you on the right track. One important thing to investigate is how you decided to sort the elements. Your sorting needs to be looped, otherwise, you won't necessarily sort the entire array (depending on your inputs).
#include <iostream>
using namespace std;
int main()
{
cout << "Enter three integers: \n";
int numbersArray[3];
int temp = 0; //This lets us hold our integers temporarily so we can swap them around in the array
//This enters integers as elements in the array
for (int i = 0; i < 3; i++)
{
cin >> numbersArray[i];
}
for(int loop = 0; loop <3; loop++){
//This should swap the elements from smallest to greatest
for (int i = 0; i < 2; i++)
{
if (numbersArray[i] > numbersArray[i+1]){
temp = numbersArray[i];
numbersArray[i] = numbersArray[i+1];
numbersArray[i+1] = temp;
}
//swap(numbersArray[i], numbersArray[++i]);
}
}
//This prints the index's containing the elements in the array
for (int i = 0; i < 3; i++)
{
cout << numbersArray[i] << ' ';
}
cout << endl;
return 0;
}

How to add a block matrix onto a sparse matrix in Eigen

For example I have a 10x10 SparseMatrix A, and I want to add a 3x3 identity matrix to the upper left corner of A.
A is known to be already non-zero in those 3 entries.
If I have to add the values one by one it is ok too, but I didn't find the method to manipulate on elements of a Sparse Matrix in Eigen.
Did I miss something?
If all you want is to apply an operation to a specific element at a time, you can use coeffRef like so:
typedef Eigen::Triplet<double> T;
std::vector<T> coefficients;
for (int i = 0; i < 9; i++) coefficients.push_back(T(i, i, (i % 3) + 1));
Eigen::SparseMatrix<double> A(10, 10);
A.setFromTriplets(coefficients.begin(), coefficients.end());
std::cout << A << "\n\n";
for (int i = 0; i < 3; i++) A.coeffRef(i,i) += 1;
std::cout << A << "\n\n";

adjacency list error with list

Basically i generated a adj_matrix and i want to make an adj_list from the adj_matrix...However I keep getting an error saying "no match for call..."
i tried it without aPair i still get the same error i can't seem to figure out what my problem is. Can anyone tell me why list isn't working? the list is at the very end of the code
int **gen_random_graph(int n)
{
srand(time(0));
int **adj_matrix = new int*[n];
for(int i = 0; i < n; i++)
{
for (int j = i; j < n; j++) //generating a N x N matrix based on the # of vertex input
{
adj_matrix[i] = new int[n];
}
}
for(int u = 0; u < n; u++)
{
for (int v = u; v < n; v++)
{
bool edgeOrNot = rand() % 2; //decide whether it has an edge or not
adj_matrix[u][v] = adj_matrix[v][u] = edgeOrNot;
if(adj_matrix[u][v] == true)
{
adj_matrix[v][u] = true;
if(u == v) //We can't have i = j in an undirected graph so we set it to false
{
adj_matrix[u][v] = -1;
}
}
else //if adj_matrix[u][v] is false set the symmetry to be false
{
adj_matrix[v][u] = adj_matrix[u][v] = -1;
}
}
}
for(int i = 0; i < n; i++)
{
for(int j = i; j < n; j++) //create the N x N with edges and sets the weight between the edge randomly
{
if(adj_matrix[i][j] == true)
{
int weight = rand() % 10 + 1;
adj_matrix[i][j] = adj_matrix[j][i] = weight;
cout << " ( " << i << "," << j << " ) " << "weight: " << adj_matrix[i][j] << endl;
}
}
}
for(int i = 0; i < n; i++)
{
vector<int> adj_list;
for(int j = i; j < n; j++)
{
if(adj_matrix[i][j] > 0)
{
int weight = adj_matrix[i][j];
adj_list.push_back(j);
cout << adj_list[i] << " " << endl;
}
}
}
print(n,adj_matrix);
return (adj_matrix);
}
I see that adj_list is not callable, so your code there is broken. There are a couple simple solutions to that. Taking a look at these docs, you may simply either access listObj.front() and listObj.back() OR you may also just create an iterator using listObj.begin() and iterating over the two elements (which may be desirable if you ever decide to put more than two elements in the list). See this tutorial for a simple example on creating an iterator for a list, in the code snippet right above the summary.
Note, here, your list object which I called listObj for simplicity/abstraction would simply be adj_matrix[i][j] in that bottom loop. That should fix your syntax error.
Also, aside from the syntax of your code, I don't get why you're trying to push weights to a list, then you're printing out and returning the adjacency matrix. I also don't get why you would use lists of pair objects when it seems like you only want to push integer weights onto it. For that, you can use a simple vector of integers (i.e.: vector <int> adj_list;)... or even simpler, you could use a simple array of integers... rather than using a vector of lists of pairs.
EDIT: After running the code locally and taking a look at the values, I realized the issue a bug in the OP's output was simply that he was using "true" in C++ in place of an integer, which was creating a bug, as explained in this SO post. The OP also has a further design decision to make where adjacency lists are concerned. More on what an adjacency list is, conceptually, found on Wikipedia.

Nested for loop filling an array

I am trying to create a nested for loop that fills in values in an array from 1 to 20.
IE) array = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}
int array[20];
for(int i = 0; i<21; i++)
{
for(int j =1; j<21; j++)
{
array[i] = j;
cout<< array[i];
}
}
Supposedly, The array index should count up with "i", and should be equated to "j" which is also counting up. The array element is printed to the console as it is filled.
I expected 1 -20 to be printed out once, but when I run the code, 1-20 prints out multiple times. Can someone tell me the problem? Thanks!
Your outer for loop runs 21 times, your inner for loop runs 20 times each of the outer for loop iterations, so you have a total of 21 * 20 = 420 print statements.
You can simply do
for(int i = 0 ; i < array.length ; i++)
{
array[i] = i + 1;
cout << array[i] << endl;
}
If you look at your array when you're done, it will also be just a series of 20s. The first loop is saying "do this 20 times" and then the second loop is saying "set and print the value of that array element 20 times." What you need to do is include a check for whether you're assigning the correct j value to the correct array[i] value, and only set the value in that case. Something like:
if (j == i + 1) array[i] = j;
Why do you need a nested loop?
for(int i = 0; i<20; i++)
{
array[i] = i + 1;
cout<< array[i];
}
yes, you have two loops when you only need one:
for(int i = 0; i<21; i++)
{
array[i] = i + 1;
cout<< array[i];
}
In order to fill the array and to print the result you just need two simple for loops
for(int i = 0; i<20; i++)
{
array[i] = j;
}
for(int j =0; j<20; j++)
{
cout<< array[i];
}
The nested loop that you created above will do exactly what you described.
For each loop of the outer for loop it will execute the full 20 loops of the inner loop.
so in total you will execute it 21 * 20 times.
Also be careful with your index. You want to start with int i = 0 to i < 20 which loops exactly 20 times.
I don't know why you are attempting to print a single element in you array, but it isn't necessary to use nested loops here; in fact, a loop isn't required at all:
// vector version
std::vector<int> vec(20);
std::iota(vec.begin(), vec.end(), 1);
// array version
int arr[20];
std::iota(std::begin(arr), std::end(arr), 1);
If you want to print out the whole array after you've initialized it:
std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout, "\n"));
I see a lot of people answered about this question, so I will not repeat them, I'll just mention that you are writing outside the array size.
if you have int array[20], you should loop
for(int i = 0; i<20; i++)
the last index is 19
The outer loop 21 times repeats the inner loop
for(int i = 0; i<21; i++)
{
for(int j =1; j<21; j++)
{
array[i] = j;
cout<< array[i];
}
}
The inner loop does the same operation that is assigns elements of the array sequantial numbers. Moreover your code has a bug because due to the outer loop youare trying to access element array[20] that does not exist, because if the array was defined as
int arrat[20];
then the valid indicies are 0 - 19.
That do not bother about writing correctly required loop or loops you could use standard algorithm std::iota
For example
#include <iostream>
#include <numeric>
#include <iterator>
#include <algorithm>
int main()
{
const size_t N = 20;
int array[N];
std::iota( std::begin( array ), std::end( array ), 1 );
std::copy( std::begin( array ), std::end( array ), std::ostream_iterator<int>( std::cout, " " ) );
}
Or instead of the algorithms you could use the range based for statement. For example
#include <iostream>
int main()
{
const size_t N = 20;
int array[N];
int i = 1;
for ( int &x : array )
{
x = i++;
std::cout << x << ' ';
}
}
If you really want to use nested solution, (for example game board coordinates) then this is my solution.
// nesting arrays for example game board coordinates
#include <iostream>
int main(){
int x = 20;
int y = 40;
int array[x][y];
// initialize array of variable-sized.
for(int i = 0; i < x; ++i){
for(int j = 0; j < y; ++j){
array[i][j] = 0; // or something like i + j + (i * (y-1)) if you wish
// and send it to cout
std::cout << array[i][j] << " ";
}
std::cout << std::endl;
}
//notice, that when sent to cout like this, x and y flips on screen, but
//logics of coordinates is ok
// and then do something usefull with it
return EXIT_SUCCESS;
}
int size = 20;
for (int i = 0; i < size; i++)
{ int array[i];
array[i] = i + 1;
cout << array[i]<< " ";
}
You could populate your array with 1 for loop, and gauge the size of your array like stated above.

Find Two Largest Numbers, C++

I'm using this approach: First find the largest among 5 numbers then save the subscript of array of the largest number in an "ivariable" after displaying the largest number, do like this
array[ivariable] = 0 ;
so that first largest set to zero and its no longer here in the array.
And do the same again, find the largest, but I'm not getting what I'm trying to.
Its a logical error.
Thanks
#include <iostream>
using namespace std;
int main(void)
{
int counter, large,number,det_2, i , large3, det_3= 0;
int det[5] = {0,0,0,0,0};
for(int k(0); k < 5 ; k++)
{
cout << "Enter the number " << endl ;
cin >> det[k] ;
}
for( i; i<5; i++)
{
large = det[i] ;
if (large > det_2)
{
det_2= large ;
counter = i ;
}
else
{
}
}
cout << "Largest among all is " << det_2 << endl;
det[i] = 0 ;
for( int j(0); j<5; j++)
{
large3 = det[j] ;
if(large3 > det_3)
{
det_3= large3 ;
}
else
{
}
}
cout << "Second largest " << large3 << endl ;
system("PAUSE");
}
You've got possible syntax and initialization errors. Fix those first:
for(int k(0); k < 5 ; k++): I've never seen an integer initialized this way. Shouldn't it be:
for (int k = 0; k < 5; k++) ? (Same with the last loop.)
Also,
for( i; i<5; i++)
The variable i is uninitialized. Variables are not initialized to any default value in C++. Because you've left it uninitialized, it might execute 5 times, no times, or 25,899 times. You don't know.
This should be:
for (i = 0; i < 5; i++)
But the whole thing could probably be a bit clearer anyway:
#include <iostream>
using namespace std;
int main(void)
{
int largest = -1;
int second_largest = -1;
int index_of_largest = -1;
int index_of_second_largest = -1;
int det[5] = {0, 0, 0, 0, 0};
for (int i = 0; i < 5; i++)
{
cout << "Enter the number " << endl;
cin >> det[i]; // assuming non-negative integers!
}
for (int j = 0; j < 5; j++) // find the largest
{
if (det[j] >= largest)
{
largest = det[j];
index_of_largest = j;
}
}
for (int k = 0; k < 5; k++) // find the second largest
{
if (k != index_of_largest) // skip over the largest one
{
if (det[k] >= second_largest)
{
second_largest = det[k];
index_of_second_largest = k;
}
}
}
cout << "Largest is " << largest << " at index " << index_of_largest << endl;
cout << "Second largest is " << second_largest <<
" at index " << index_of_second_largest << endl;
return 0;
}
Always give your variables values before you use them
det_2 = det[0];
counter = 0;
for (i = 1; i < 5; i++)
first problem I saw was that you are iterating using i as an index, but you don't initialize i.
code should be:
for(i = 0; i<5; i++)
^^^^
same goes for det_2. You compare elements against it, but do not initialize it. You should set it to det[0] before the loop where you use it.
third problem: Your "set largest value to zero after printing" sounds like it is there so that you can apply the same algorithm the second time.
You should create an additional function that gives you the index of the largest element, and call it like this:
int index = find_largest_index(a);
cout << "largest element: " << a[index] << endl;
a[index] = 0;
cout << "second largest element: " << a[ find_largest_index(a) ] << endl;
GCC 4.7.3: g++ -Wall -Wextra -std=c++0x largest.cpp
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
int main() {
std::cout << "Enter 5 numbers: ";
// Read 5 numbers.
std::vector<int> v;
for (auto i = 0; i < 5; ++i) {
int x = 0;
while (!(std::cin >> x)) {
// Error. Reset and try again.
std::cin.clear();
std::cin.ignore();
}
v.push_back(x);
}
// partition on element 3 (4th number)
std::nth_element(std::begin(v), std::next(std::begin(v), 3), std::end(v));
std::cout << "Two largest are: ";
std::copy(std::next(std::begin(v), 3), std::end(v), std::ostream_iterator<int>(std::cout, " "));
}
In the specific case of 5 elements, the algorithm you use is unlikely to make any real difference.
That said, the standard algorithm specifically designed for this kind of job is std::nth_element.
It allows you to find the (or "an", if there are duplicates) element that would end up on position N if you were to sort the entire collection.
That much is pretty obvious from the name. What's not so obvious (but is still required) is that nth_element also arranges the elements into two (or three, depending on how you look at it) groups: the elements that would short before that element, the element itself, and the elements that would sort after that element. Although the elements are not sorted inside of each of those groups, they are arranged into those groups -- i.e., all the elements that would sort before it are placed before it, then the element itself, then the elements that would sort after it.
That gives you exactly what you want -- the 4th and 5th elements of the 5 you supply.
As I said originally, in the case of just 5 elements, it won't matter much -- but if you wanted (say) the top 50000 out of ten million, choosing the right algorithm would make a much bigger difference.
nth_element isn't always suitable (or as efficient as it could be) as it needs to rearrange the input elements.
It's very common to want just the top two elements, and can be done efficiently in one pass by keeping the best and second-best values seen so far, and whenever a value you iterate over is better than the second-best, you'll either replace the second-best with it or the best, and in the latter case you also overwrite the best with the new value. That can look like this:
#include <utility>
template <typename It, typename EndIt, typename Less = std::less<>>
auto top_two(It it, EndIt end, Less less = Less{}) -> std::pair<It, It>
{
It first = it;
if (it == end || ++it == end)
return {first, end};
std::pair<It, It> results = less(*it, *first) ? std::pair{first, it} : std::pair{it, first};
while (++it != end)
if (less(*results.second, *it))
results.second = less(*results.first, *it)
? std::exchange(results.first, it) : it;
return results;
}
(See it running at http://coliru.stacked-crooked.com/a/a7fa0c9f1945b3fe)
I return iterators so the caller can know where in the input the top two elements are, should they care (e.g. to erase them from a container, or calculate their distance from begin(), or modify their values).
It you want the two lowest values, just pass std::greater<>{} as your "less" argument.
Some convenience functions to make it easier to call with containers or initializer_lists:
template <typename Container, typename Less = std::less<>>
auto top_two(const Container& c, Less less = Less{})
{
return top_two(begin(c), end(c), less);
}
template <typename T, typename Less = std::less<>>
auto top_two(const std::initializer_list<T>& il, Less less = Less{})
{
return top_two(begin(il), end(il), less);
}
If you want a general solution for the top-N elements, it's better to make N an argument and create a multiset of N top values (using a dereferencing comparison type), putting the initial N elements in, then whenever a new element is more than the **top_n.begin() value, do a top_n.insert(it); followed by top_n.erase(top_n.rbegin()); to drop the worst element: these operations are O(log N) so remain reasonably efficient even in pathological cases, such as input that is incrementing numbers.