C++ merge sort passed by value - c++

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

Related

reading for value in file giving wrong results - c++

posting again due to change in formatting and code
I'm trying to parse a csv file and search it to find values that match my randomly generated array.
I've tried a few methods but im getting lost, I need to access the entire file, search for these values and output the index column that it belongs to.
my code for my random array generator as well as my search csv function:
reproducible example:
#include <fstream>
#include <iostream>
#include <string>
#include <random>
using namespace std;
//fills array of size 6 with random numbers between 1-50
void random_array(int arr[])
{
for (int i = 0; i < 6; i++) {
int num = rand() % 51;
arr[i] = num;
}
}
int main()
{
string line;
fstream file;
int size = 6;
int numbers[size];
int found;
//gets random array from random_array func
srand(time(NULL));
random_array(numbers);
//opens file to search
file.open("CSV directory here");
if (file.is_open()) {
//print random array values
for (int i = 0; i < size; i++) {
cout << numbers[i] << " ";
}
cout << endl;
//get file contents and search if contents of array exist in file
while (getline(file, line)) {
for (int i = 0; i < size; i++) {
found = line.find(std::to_string(numbers[i]));
if (found != string::npos) {
//print found numbers
cout << found << " ";
}
}
}
}
return 0;
}
CSV sample format:
,Date,1,2,3,4,5,6,7
0,Wed 03 January 2001,5,6,16,17,19,22,40
1,Sat 06 January 2001,6,16,23,34,35,40,37
my output:
array generated:
35 35 38 37 16 31
numbers found (from entire csv not just sample above):
26 33 33 39 24 31 34 33 24 6 28 31 33 33 30 0 32 34 33 30 27 38 26 29
29 33 7 24 29 26 26 26 24 24 0 30 30 36 0 0 23 27 0 0 7 36 36 27 30 30
27 27 26 26 32 29 23 38 32 32 28 28 7 25 29 37 25 29 29 26 23 34 31 28
25 31 28 28 34 32 32 35 38 40 25 37 37 35 40 40 30 30 42 42 42 36 35
28 31 25 37 7 27 36 33 36 33 29 39 29 35 34 34 40 40 43 31
Obviously you can see these numbers aren't correct and are almost completely random. The numbers dont match what's within my array, am I doing something wrong with my file parsing?

Write a program that gives the longest period of days when the temperature was always above K degrees [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
Multiple Selection
My code works fine with the Test 1 inputs but with the Test 2 is stops at the first acceptable indexes and does not continue evaluating other elements and if I remove the break I'm getting off results
Possible Solution
I would like an assistance making the code to continue evaluating other elements even after finding a favorable element
Example Input
Test 1
7 30
25
36
29
33
34
36
30
Test 2
10 30
22
36
31
29
25
36
30
36
36
27
Expected Output
Test 1
4 6
Test 2
6 9
Code
#include <iostream>
using namespace std;
const int MaxN = 102;
void findInd(int T[], int N, int K){
int start = 0; //TODO Recursive
for (int i = 1; i <= N; i++) {
if (N >= 1 && N <= 100 && K >= -20 && K <= 50){
if (T[i] > K && T[i+1] > K){
start = i;
break;
}
}
}
if (start == 0){
cout << "none";
return;
}
int end = start; //TODO recursive
for (int i = N; i >= start; i--) {
if (N >= 1 && N <= 100 && K >= -20 && K <= 50){
if (T[i] > K){
end = i;
break;
}
}
}
cout << start << " " << end;
}
int main() {
int N, K;
cin >> N >> K;
int T[MaxN];
for (int i = 1; i <= N; ++i) {
cin >> T[i];
}
findInd(T, N, K);
return 0;
}
You only need one loop and no recursion, but you need more bookkeeping.
Consider the following example execution for your second case.
v - where you're looking
^ - the start of the current "at least K" range
v
22 36 31 29 25 36 30 36 36 27
max: 0
v
22 36 31 29 25 36 30 36 36 27
^ max: 1, start: 1, end: 1
v
22 36 31 29 25 36 30 36 36 27
^ max: 2, start: 1, end: 2
v
22 36 31 29 25 36 30 36 36 27
max: 2, start: 1, end: 2
v
22 36 31 29 25 36 30 36 36 27
max: 2, start: 1, end: 2
v
22 36 31 29 25 36 30 36 36 27
^ max: 2, start: 1, end: 2
v
22 36 31 29 25 36 30 36 36 27
^ max: 2, start: 1, end: 2
v
22 36 31 29 25 36 30 36 36 27
^ max: 3, start: 5, end: 7
v
22 36 31 29 25 36 30 36 36 27
^ max: 4, start: 5, end: 8
v
22 36 31 29 25 36 30 36 36 27
max: 4, start: 5, end: 8
Implementation left as an exercise.

Problem in Knights Tour using backtracking

I am getting a infinite loop when I try and run my solution for the Knights Tour problem using Backtracking
My Solution Code:
Link: https://ideone.com/Ud92vF
code:
#include <bits/stdc++.h>
using namespace std;
bool valid(int arr[8][8],int r,int c)
{
if(r>=0 and r<8 and c>=0 and c<8 and arr[r][c]== -1)
return true;
return false;
}
void fun(int arr[8][8],int r,int c,int x)
{
if(x==64){
cout<<"***********************ARRAY FOUND***********************\n";
for(int i=0;i<8;i++){
for(int j=0;j<8;j++)
cout<<arr[i][j]<<" ";
cout<<"\n";
}
return;
}
if(!valid(arr,r,c))
return;
arr[r][c] = x;
fun(arr,r-2,c+1,x+1); fun(arr,r-2,c-1,x+1);
fun(arr,r-2,c+2,x+1); fun(arr,r-2,c-2,x+1);
fun(arr,r+2,c+1,x+1); fun(arr,r+2,c-1,x+1);
fun(arr,r+1,c+2,x+1); fun(arr,r+1,c-2,x+1);
arr[r][c] = -1;
}
int main()
{
int arr[8][8] ;
for(int i=0;i<8;i++){
for(int j=0;j<8;j++)
arr[i][j] = -1;
}
int r=0,c=0,x=0; fun(arr,r,c,x);
}
Make sure your move array is correct:
fun(arr,r-2,c-1,x+1); fun(arr,r-2,c+1,x+1);
fun(arr,r-1,c-2,x+1); fun(arr,r-1,c+2,x+1);
fun(arr,r+1,c-2,x+1); fun(arr,r+1,c+2,x+1);
fun(arr,r+2,c-1,x+1); fun(arr,r+2,c+1,x+1);
With this I get a right answer:
***********************ARRAY FOUND***********************
0 11 8 5 2 13 16 19
9 6 1 12 17 20 3 14
30 27 10 7 4 15 18 21
63 24 31 28 35 22 47 44
32 29 26 23 48 45 36 57
25 62 51 34 39 56 43 46
52 33 60 49 54 41 58 37
61 50 53 40 59 38 55 42
Note that as you use the 65th move to validate you answer, you'll get 8 of the same correct answers in a row. And then another 8. Etc. You can fix this by printing after your 64th move:
void fun(int arr[8][8],int r,int c,int x)
{
if(!valid(arr,r,c))
return;
arr[r][c] = x;
if(x==63){
cout<<"***********************ARRAY FOUND***********************\n";
for(int i=0;i<8;i++){
for(int j=0;j<8;j++)
cout<<arr[i][j]<<" ";
cout<<"\n";
}
}
else
{
fun(arr,r-2,c-1,x+1); fun(arr,r-2,c+1,x+1);
fun(arr,r-1,c-2,x+1); fun(arr,r-1,c+2,x+1);
fun(arr,r+1,c-2,x+1); fun(arr,r+1,c+2,x+1);
fun(arr,r+2,c-1,x+1); fun(arr,r+2,c+1,x+1);
}
arr[r][c] = -1;
}
And one last issue is that you only ever start at {0,0} so you'll only find knights tours which start on that square. You really want to start from every square to find all possible knights tours. Or if you're feeling clever you only need to check a subset of the starting squares and use symmetry to generate the others.

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

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.