Matrix Enumeration Lab - c++

Your job is to write a program called matrix_enum, which takes three command line arguments: W, E and either an 'x' or an 'h'. Your program will enumerate all of the matrices for W and E, in any order you want, and print them out in one of the following two formats:
If the last argument is 'x', then you'll print the matrices out in the format below. You should print each matrix as W lines of W characters that are '.', 'X' or 'E'. After each matrix, you print a blank line.
If the last argument is 'h', then you'll convert each line of each matrix into an integer, and print that integer in hexadecimal, with no leading 0's and no leading "0x". If element i in a row is 'X' or 'E', then you'll set the i-th bit of the number to 1. Otherwise, the i-th bit is zero. You'll print each integer on its own line, and print a blank line at the end of each matrix.
UNIX> matrix_enum 2 0 x
X.
.X
.X
X.
UNIX> matrix_enum 2 0 h
1
2
2
1
Here's my code so far but I don't know where to go from here
5 class Matrix {
6 public:
7 int W;
8 int E;
9 int P; /* This is 'x' or 'h' */
10 vector <int> Perm; /* Permutation of 0 .. (W-1), for the 'X' elements. */
11 vector <int> Non_X; /* This is the row/col id of each of the non-X elements. */
12 vector <int> E_ID; /* This is the row/col id of the E elements */
13 void Print(); /* Print the matrix defined by W, Perm and E_ID */
14 void Permute(int index); /* This is the recursive permuting method. */
15 void Choose(int index); /* This is the recursive n-choose-k method. */
16 };
17
18 void Matrix::Print() {
19
20 for(int i = 0; i < Perm.size(); i++) {
21
22
23 }
24 }
25
26 void Matrix::Permute(int index) {
27 //recursion to permute matrix
28 string tmp;
29
30 if(index == Perm.size()) {
31 //Base case
32 for (int i = 0; i < W; i++) {
33 for(int j = 0; j < W; j++) {
34 //check if there is an 'x'
35 if(Perm.at(i) == j) {
36 continue;
37 }
38
39 Non_X.push_back(Perm.at(i));
40 Choose(0);
41 return;
42 }
43 }
44 }
45 //swap Perm[index] with Perm[i] and swap back
46 for(int i = index; i < Perm.size(); i++) {
47 //swap
48 tmp = Perm[i];
49 Perm[i] = Perm[index];
50 Perm[index] = tmp;
51
52 Permute(index+1);
53
54 //backtrack
55 tmp = Perm[i];
56 Perm[i] = Perm[index];
57 Perm[index] = tmp;
58 }
59 }
60
61 void Matrix::Choose(int index) {
62 //n choose k permutation
63 //people = non x
64 //eid = teams
65 if (E - E_ID.size() == 0) {
66 cout << E_ID[0];
67 for (i = 1; i < E_ID.size(); i++) cout << " " << E_ID[i];
68 cout << endl;
69 return;
70 }
71
72 if ((E - E_ID.size()) > Non_X.size() - index) return;
73
74 E_ID.push_back(Non_X[index]);
75 Choose(index+1, (E - E_ID.size())-1);
76 E_ID.pop_back();
77
78 Choose(index+1, (E - E_ID.size()));
79
80 // call Print();
81 }

Related

cycle detection in an undirected graph using dfs and height array

My job is to complete the isCyclic() function in following program. I can handle this job with visited array and passing parent to dfs() function but I am trying another solution, So I use a height array to keep track of distance of nodes in DFS tree for determining parents and cycle. this height array initial by zero. If distance of two node be exactly one these two node are parent child.
But I cannot understand why my solution doesn't work. can someone tell me why output of this code is not correct?
thanks for your help.
An example of graph and height value of nodes:
/*
.1
/ \
.2 .2
/ \
.3 .3
*/
#include<bits/stdc++.h>
using namespace std;
class Graph
{
int V;
list<int> *adj;
public :
Graph(int V);
void addEdge(int v,int w);
bool isCyclic();
};
vector<int> g[100001];
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int v,int w)
{
adj[v].push_back(w);
adj[w].push_back(v);
}
int main()
{
int T;
cin>>T;
while(T--)
{
int _size,N;
cin>>_size>>N;
Graph *g = new Graph(_size);
for(int i=0;i<N;i++)
{
int u,v;
cin>>u>>v;
g->addEdge(u,v);
}
cout<<g->isCyclic()<<endl;
}
}
/*Please note that it's Function problem i.e.
you need to write your solution in the form of Function(s) only.
Driver Code to call/invoke your function is mentioned above.*/
/*The structure of the class is as follows
which contains an integer V denoting the no
of vertices and a list of adjacency vertices.
class Graph
{
int V;
list<int> *adj;
public :
Graph(int V);
void addEdge(int v,int w);
bool isCyclic();
};*/
/*You are required to complete this method*/
bool dfs(int v, int hi, list<int> *adj, int *h) {
h[v] = hi;
list<int>::iterator it;
for(it = adj[v].begin(); it != adj[v].end(); it++) {
int u = *it;
//cycle detect
if (h[u]>0 && hi - h[u] > 1)
return true;
if (h[u]==0 && dfs(u, hi+1, adj, h))
return true;
}
return false;
}
/*You are required to complete this method*/
bool Graph :: isCyclic()
{
//Your code here
int h[V];
for(int i = 0; i < V; i++) h[i] = 0;
for(int i = 0; i< V; i++)
if ( h[i] == 0 && dfs(i, 1, adj, h) ) return true;
return false;
}
A input that make my answer incorrect:
Input:
85 59
0 34 32 54 6 16 45 44 82 52 57 15 20 60 52 44 75 77 48 18 53 75 14 40 39 46 24 26 32 0 39 74 34 29 43 41 45 45 0 42 54 14 58 75 31 67 34 63 16 39 81 69 29 52 67 26 14 6 52 3 48 49 77 83 78 78 81 38 38 38 38 8 53 53 40 84 77 31 63 9 70 16 78 57 69 60 83 83 23 7 43 72 56 35 27 6 70 23 2 24 61 40 74 71 50 29 28 42 60 48 51 2 64 2 59 48 19 57
Its Correct output is:
1
And Your Code's output is:
0

C++ merge sort passed by value

I am trying to recursively implement the merge sort algorithm by only passing in a vector value to the function (no left or right index). The while loop in the following code works when the list to be sorted is passed as a pointer void merge_sort_array(int* v, int l, int r) or reference void merge_sort_ref(vector<int>& v, int l, int r) but I cannot for the life of me understand why the following code will not properly sort my list. I have a feeling it is something to do with either the starting values of i, j, k or the bounds within my while loop but I've tried anything that makes sense to me and can't figure it out.
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> merge_sort_value(vector<int> v) {
int n = v.size();
if(n == 1){
return v;
}
else{
int m = n/2;
vector<int> v1(v.begin(), v.begin()+m);
vector<int> v2(v.begin()+m, v.begin()+n);
merge_sort_value(v1);
merge_sort_value(v2);
vector<int> tmp(v.begin(), v.begin()+m);
int i = 0;
int j = m;
int k = 0;
while((i < m) or (j < n)){
if(i == m){
v[k] = v[j];
j +=1;
}
else if((j == n) or (tmp[i] < v[j])){
v[k] = tmp[i];
i+=1;
}
else{
v[k] = v[j];
j+=1;
}
k+=1;
# print output for debugging
for(auto x = v.begin(); x != v.end(); ++x)
cout << *x << " ";
cout << "" << endl;
cout << i << "\t"<< j << "\t" << k << endl;
}
return v;
}
}
int main(int argc, char** argv) {
vector<int> v(10);
for(int i=0; i < 10; ++i)
v[i] = rand() % 100;
v = merge_sort_value(v);
return 0;
}
I have included a sample output for reference below:
28 28
0 2 1
28 80
1 2 2
21 21
0 2 1
21 92
1 2 2
14 92 21
1 1 1
14 92 21
1 2 2
14 92 21
1 3 3
14 28 14 92 21
0 3 1
14 80 14 92 21
1 3 2
14 80 28 92 21
2 3 3
14 80 28 92 21
2 4 4
14 80 28 92 21
2 5 5
21 57
1 1 1
21 57
1 2 2
78 83
1 1 1
78 83
1 2 2
78 78 83
0 2 1
78 83 83
0 3 2
78 83 96
1 3 3
21 57 96 78 83
1 2 1
21 57 96 78 83
2 2 2
21 57 96 78 83
2 3 3
21 57 96 78 83
2 4 4
21 57 96 78 83
2 5 5
21 28 14 92 21 21 57 96 78 83
0 6 1
21 57 14 92 21 21 57 96 78 83
0 7 2
21 57 80 92 21 21 57 96 78 83
1 7 3
21 57 80 28 21 21 57 96 78 83
2 7 4
21 57 80 28 14 21 57 96 78 83
3 7 5
21 57 80 28 14 92 57 96 78 83
4 7 6
21 57 80 28 14 92 21 96 78 83
5 7 7
21 57 80 28 14 92 21 96 78 83
5 8 8
21 57 80 28 14 92 21 96 78 83
5 9 9
21 57 80 28 14 92 21 96 78 83
5 10 10
Thank you, any help is greatly appreciated!
after reviewing you code it seems you're making mistakes in the algorithm it self and in C++ as language so i've edited your algorithm to be more neat and more readable algorithm i will explain some part of the code
Code
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> merge_sort_value(vector<int> v) {
int n = v.size();
if(n == 1){
return v;
}
else{
int m = n/2;
vector<int> v1(v.begin(), v.begin()+m);
vector<int> v2(v.begin()+m, v.begin()+n);
v1 = merge_sort_value(v1); /* passing by value will left v1 with no sorting so you need to copy from the returned
object */
v2 = merge_sort_value(v2);
int i = 0;
int j = 0;
int k = 0;
const size_t left_vecS = v1.size();
const size_t right_vecS = v2.size();
while (i<left_vecS&&j<right_vecS) { // we must keep i (AND) j valid
if (v1[i] < v2[j])
v[k++] = v1[i++];
else
v[k++] = v2[j++];
}
while(i<left_vecS) // if we sorted v2 then what insert the rest of v1 in v as what kept from v1 will be sorted
v[k++] = v1[i++];
while(j<right_vecS)
v[k++] = v2[j++];
}
return v;
}
int main(int argc, char** argv) {
vector<int> v(10);
std::vector<int> x;
for(int i=0; i < 10; ++i)
v[i] = rand() % 100;
v = merge_sort_value(v);
for(auto&i:v)
std::cout << i << std::endl;
return 0;
}
1- I get rid of the printing inside the sorting function so we keep the code clean
2-
the first error you've did at the language level is you didn't copy the returned sorted vector object from merge_sort_value to the vectors.(i've mentioned that in the code in a comment) so that's the first thing to keep in mind
3- the logic part of the algorithm wasn't clear to me because i didn't see how you're sorting specially that part else if ((j == n) or (tmp[i] < v[j])) {
v[k] = tmp[i];
i += 1;
}
like you're comparing unsorted sub vector to another unsorted vector and you're giving it unsorted value again (you must compare v1 against v2)
the whole logic is missed up i think you need to review it
anyway i hope that helped

Binary Search TestCase Not Returning a Value

So I am trying to solve the following question
Input Format is
N
x x x x x ...
q
y y y y y ...
N=size of array
x,x,x ... are elements of array
q=no of queries
y,y,y .. are queries to be searched in the array using binary search
Here is My code
#include <iostream>
#include<algorithm>
using namespace std;
int main()
{
int N,q;
cin>>N;
int a[N];
for(int i=1;i<=N;i++)
{
cin>>a[i];
}
cin>>q;
int b[q];
for(int i=0;i<q;i++)
{
cin>>b[i];
}
int len=sizeof(a)/sizeof(a[1]);
sort(a,a+len);
int beg=1,end=N;
for(int j=0;j<q;j++)
{
beg=1;end=N;
while(beg<=end)
{
int mid=(beg+end)/2;
if(b[j]==a[mid])
{
cout<<mid<<endl;
break;
}
else if(b[j]<a[mid])
{
end=mid-1;
}
else
beg=mid+1;
}
}
return 0;
}
My code is giving the following output which is wrong
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
for the input
100
100 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
correct output is
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Arrays are 0-based.
Arrays are not variable-length in C++.
You have a wrong update here:
else if(b[j]<a[mid])
{
end=mid-1;
}
The end is non-inclusive.
You will also want to keep going until (beg<end) not beg<=mid - otherwise mid will simply equal both.
Here's C++ version that fixes all of the above and uses iterators instead of indexes. Iterators remove the ambiguity (base-0 vs base-1) and make it very explicit that a range is [begin, end), by contract.
Live ON Coliru
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;
int main() {
int N;
cin >> N;
std::vector<int> a(N);
std::copy_n(std::istream_iterator<int>(std::cin), N, a.begin());
int q;
cin >> q;
std::vector<int> b(q);
std::copy_n(std::istream_iterator<int>(std::cin), q, b.begin());
sort(a.begin(), a.end());
for (auto query : b) {
auto beg = a.begin();
auto end = a.end();
while (beg < end) {
auto mid = beg + (end-beg) / 2;
if (query == *mid) {
cout << *mid << endl;
break;
} else if (query < *mid) {
end = mid;
} else beg = mid + 1;
}
}
}
Prints
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Problem 1
Your program has undefined behavior due to accessing a using an out of bounds index in the following loop.
for(int i=1;i<=N;i++)
{
cin>>a[i];
}
That loop needs to be changed to use a 0 based index.
for(int i = 0; i < N; i++)
{
cin >> a[i];
}
Problem 2
For similar reasons, the initial value of beg needs to be 0, not 1.
Problem 3
You are comparing with values of a[mid] but you are outputting mid. The output also needs to be a[mid].
Problem 4
else if(b[j]<a[mid])
{
end=mid-1;
}
needs to be
else if(b[j]<a[mid])
{
end=mid;
}
With the above changes, the program works as expected in my environment. Here's the updated program:
#include <iostream>
#include<algorithm>
using namespace std;
int main()
{
int N,q;
cin>>N;
int a[N];
for(int i=0;i<N;i++)
{
cin>>a[i];
}
cin>>q;
int b[q];
for(int i=0;i<q;i++)
{
cin>>b[i];
}
int len=sizeof(a)/sizeof(a[1]);
sort(a,a+len);
int beg=0,end=N;
for(int j=0;j<q;j++)
{
beg=0;end=N;
while(beg<end)
{
int mid=(beg+end)/2;
if(b[j]==a[mid])
{
cout << a[mid] << endl;
break;
}
else if(b[j]<a[mid])
{
end=mid;
}
else
beg=mid+1;
}
}
return 0;
}
See it working at https://ideone.com/wgF2IS.
Array start with 0 index.so make sure for N elements your loop must start with zero index.
for(int i = 0; i < N; i++)
{
cin >> a[i];
}
Similarly, for same reason assign beg '0' value and end 'N-1' value.

how to check a matrix for duplicate numbers C++

I'm trying to generate a 5x20 matrix filled with random numbers. How can I make sure none of the random numbers are duplicates? This is the code I have for filling the matrix with random numbers.
srand(time(0));
int matrix[5][20];
int i = 0;
int j = 0;
for (i = 0; i < 5; i++)
{
for (j = 0; j < 20; j++)
{
matrix[i][j] = 1 + (rand() % 100);
cout << matrix[i][j] <<"_";
}
cout << endl;
}
the code works but there are sometimes duplicates. If this were an array I could make use of a simple for loop and compare all of the elements in the array. but I have no idea how to do so with a matrix. I have searched everywhere but cant seem to find a solution.
It's not quite fit your question title but I think you should take a look.
for (i = 0; i < 5; i++)
{
for (j = 0; j < 20; j++)
{
matrix[i][j] = 1 + (rand() % 100);
cout << matrix[i][j] <<"_";
}
cout << endl;
}
I don't know the 5x20 and 100 (in rand() % 100) is compulsory or just an example you want to give. So I suggest for all case I can consider:
Let call the number of matrix elements is a, the number of set (contains all possible generated number) is b. In your is example, a is 5x20=100 and b is 100 (from 1 to 100).
a > b: no valid matrix without duplicates since Dirichlet principle
a == b: take a look at http://en.cppreference.com/w/cpp/algorithm/random_shuffle. Just create an 1-dimension array containing consecutive number from 0 to b-1 (or from min and max of your range) and permute them. Then use it to fill in the matrix.
a < b: similar to case a==b, but you just take a part of the permutation.
Of course, when a =< b then you can use rand() but you have to check duplicate and retry rand(), which is quite complicated. You can create a mark array (which cost memory) or iterate through your matrix again (which cost time).
as a heads up, you shouldn't use rand() unless you've got explicit reasons to (such as a professor's requirements).
The following approach uses a GetIndex function to simulate an int[5][20] with an int[100]. See if you can figure out how to use the code I wrote to create an int[5][20].
Your code fills the matrix with random numbers between 1 and 100 (1 + (rand() % 100)) inclusively, but you do no work to ensure you don't get duplicates! So you won't be able to guarantee that you don't get duplicates (in fact, it's very unusual for you to get no duplicates).
If you first initialize all your values to 1,...,100 and then later shuffle them, you know you have no duplicates.
#include <iostream>
#include <iomanip>
#include <random>
#include <algorithm>
constexpr size_t kDefaultMatrixHeight = 20;
constexpr size_t kDefaultMatrixWidth = 5;
constexpr size_t GetIndex(size_t i, size_t j) {
return i * kDefaultMatrixWidth + j;
}
int main() {
int matrix[kDefaultMatrixWidth * kDefaultMatrixHeight];
for (size_t i = 0 ; i < kDefaultMatrixHeight * kDefaultMatrixWidth ; i++) {
matrix[i] = i + 1;
}
std::mt19937 rng(std::random_device{}());
std::shuffle(std::begin(matrix), std::end(matrix), rng);
for (size_t i = 0 ; i < kDefaultMatrixHeight ; i++) {
for (size_t j = 0; j < kDefaultMatrixWidth ; j++) {
std::cout << std::setw(4) << matrix[GetIndex(i,j)];
}
std::cout << '\n';
}
}
And for example output:
Test#Test:/tmp/example$ g++ example.cpp && ./a.out
93 28 70 14 39
83 3 80 95 58
42 69 71 16 49
75 63 41 82 46
26 50 81 33 97
65 10 77 68 12
8 19 30 86 37
57 24 78 31 88
2 90 4 13 56
36 15 35 32 85
29 76 99 45 18
54 11 44 62 98
9 96 79 34 27
40 21 52 22 55
72 1 47 92 59
94 7 64 91 53
74 5 61 100 89
48 23 66 67 51
38 6 87 17 20
60 25 84 43 73
not exactly answer your question but for your purpose you can try something like this:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
srand(time(0));
int matrix[5][20];
int *pmatrix = &matrix[0][0];
int i = 0;
for (i = 0; i < 100; i++)
{
pmatrix[i] = i+1;
}
std::random_shuffle(pmatrix, pmatrix+100);
for (i = 0; i < 100; i++)
{
std::cout<<pmatrix[i]<<",";
}
}
cpp.sh/5bnyt
Update fixed memory out of bounds problem.

Increment working very strangely

This program is supposed to give to the last 100 digits of any size factorial. However, there's something weird going on with the counter2++ in main(). counter2 is incremented +1 for each time the loop runs in the main() function (which is 99 times). However this is what is displayed:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
71
86
90
123
164
196
207
254
300
362
432
471
551
620
630
708
761
772
857
896
985
1036
1100
1116
1207
1209
1280
1356
1417
1452
1512
Counter2 ends up being 1512 instead of 100, but if I remove either mult(i) or carry() from main() then it displays 100. Why does counter2 end up being 1512 and not 100?
#include <iostream>
using namespace std;
int numbers[100];
int counter2 = 0;
void init(){
//sets elements 1-99 of numbers[] to 0, increments counter2 by 1, sets numbers[0] = 1
for (int i = 1; i < 100; i++){
numbers[i] = 0;
}
numbers[0] = 1;
counter2++;
}
void mult(int x){
//multiplies each element by 1 through n to calculate for !n
//this is used to represent a very large number without using a BigInt library
//the nth element is a placeholder for the n+1 position of the number
//e.g 2nd element represents 100-900 of the number, 4th represents 1000-9000, etc
//carry() is used to take care of overflow, so that it's only 1 digit per element
for (int i = 0; i < 100; i++){
numbers[i] *= x;
}
}
void carry(){
//in order to make previous function work, this adds any overflow to the next
//element. e.g: 8 * 4 = 32, 3 is added to numbers[i+1], sets numbers[i] to 2
int counter = 0;
for (int i = 0; i < 100; i++){
if (numbers[i] >= 10){
counter = numbers[i] / 10;
numbers[i+1] += counter;
numbers[i] = numbers[i] % (counter * 10);
}
}
}
int main()
{
init();
for (int i = 2; i < 101; i++){
//calculates the last 100 digits of !100, but counter2 ends up being 1512
mult(i);
carry();
counter2++;
cout << counter2 << endl;
}
}
You are writing past the end of the numbers array in carry():
numbers[i+1] += counter;
Here, i can be 99, in which case numbers[i+1] is out of bounds.
Technically, this is undefined behaviour. What happens in practice is that you overwrite the count2 variable, which happens to sit in memory right after the array.
One nasty thing about memory bugs is that they can go symptomless for a long time, and then surface in the worst possible circumstances. valgrind is a great tool for detecting problems of this type.
In this line
numbers[i+1] += counter;
you are writing out of bounds of array numbers[100];when i == 99 thus changing the value of int counter2 = 0; which (in your case, but not necessarily) sits right next to numbers in memory.