greedy and optimal solution for maximum sub interval in certain range - c++

I tried to get first a greedy solution for me handling reservation buy getting 2 days (start, end) and getting the maximum days that can be reserved without the interval being overlap
#include <algorithm>
#include <iostream>
using namespace std;
struct Interval {
int start, end;
};
// Compares two intervals
// according to starting times.
bool comparesorting(Interval i1, Interval i2)//sorting
{
return (i1.end < i2.end);
}
bool compareoverlap(Interval i1, Interval i2)//overlap
{
return (i1.start < i2.start) ? true : false;
}
bool isIntersect(Interval arr[], int n)
{
// Sort intervals in increasing order of start time
sort(arr, arr + n, compareoverlap);
// In the sorted array, if start time of an interval
// is less than end of previous interval, then there
// is an overlap
for (int i = 1; i < n; i++)
if (arr[i - 1].end > arr[i].start)
//return true;
if (true) {
for (int i = 0; i < n; i++)
cout << "mmmm" << endl;
cout << "[" << arr[i].start << "," << arr[i].end
<< "] ";
}
// If we reach here, then no overlap
return false;
}
int main()
{
Interval arr[]
= { { 6, 8 }, { 7, 9 }, { 2, 4 }, { 4, 7 } , { 1,9 } , {6,9} ,{2,6} , {1,10} };
int n = sizeof(arr) / sizeof(arr[0]);
// sort the intervals in increasing order of
// start time
sort(arr, arr + n, comparesorting);
cout << "Intervals sorted : \n";
for (int i = 0; i < n; i++)
cout << "[" << arr[i].start << "," << arr[i].end
<< "] ";
int n1 = sizeof(arr) / sizeof(arr[0]);
isIntersect(arr, n1) ? cout << "Yes\n" : cout << "No\n";
return 0;
}
the output should be {2,4} {4,7} (that does not overlap)
I'm trying to make an optimal solution to solve this problem. I'm thinking to subtract the end - start and compare it to the addition of this greedy solution
please help I'm stuck!!!!

Related

Extra "0" in output when factorizing a number

Write a function int fact(int n) which displays the factors of the integer n, and returns the number of factors. Call this function in main() with user input
#include<iostream>
using namespace std;
int fact(int n);
int main() {
int n,factor;
cout << "Enter an integer : ";
cin >> n;
factor = fact(n);
cout << factor;
return 0;
}
int fact(int n)
{
for (int i = 1; i <= n; ++i)
{
if (n % i == 0)
cout << i << endl;
}
return 0;
}
If I enter 7, I get 1,7,0 . How do i remove this 0 and how do i find the number of factors?
You should count in your int fact() function. Set a variable to 0 and increment each time you currently display i. Then at the end of the function instead of returning 0 return the count variable.
int fact(int n)
{
int count=0;
for (int i = 1; i <= n; ++i)
{
if (n % i == 0) {
cout << i << endl;
count++;
}
}
return count;
}
The key part is "and returns the number of factors". You don't do that. Keep a count of the factors:
int fact(int n)
{
int count = 0;
for (int i = 1; i <= n; ++i)
{
if (n % i == 0)
{
// found a factor, add to the count
count++;
cout << i << endl;
}
}
// return the count instead
return count;
}
Then, your main function can use that count:
factor = fact(n); // fact(n) will already print the factors
// now just print the number
cout << "Number of factors: " << factor << '\n';
#include <iostream>
#include <vector>
std::vector<int> fact(int n);
int main() {
int n;
std::cout << "Number: ";
std::cin >> n;
std::vector<int> factors = fact(n);
for (auto i : factors) {
std::cout << i << ' ';
}
std::cout << '\n';
std::cout << "Number of factors: " << factors.size() << '\n';
return 0;
}
std::vector<int> fact(int n) {
std::vector<int> vec{1};
for (int i = 2; i <= n / 2; ++i) {
if (n % i == 0) {
vec.push_back(i);
}
}
vec.push_back(n);
return vec;
}
If you're going to return anything from fact(), it should be the factors. To do so, I am using a std::vector. It is an array that can grow on demand. The numbers 1 and n are always factors, so I don't bother doing the math for them. The vector is initialized already holding the value 1, and I only calculate numbers up to and including half of n (Anything greater than n/2 won't divide evenly, so my loop is finished about half as fast by recognizing the actual range). I then just add n to the vector, which I return.
My main prints the vector, and the vector knows its own size, which is the number of factors.
Alternatively, you can just keep a count in your fact() function.
#include <iostream>
#include <vector>
// Prints factors of n and returns the number of factors
int fact(int n);
int main() {
int n;
std::cout << "Number: ";
std::cin >> n;
int numFactors = fact(n);
std::cout << "Number of factors: " << numFactors << '\n';
return 0;
}
int fact(int n) {
int factorCount = 2; // Already counting 1 and n
std::cout << "1 ";
for (int i = 2; i <= n / 2; ++i) {
if (n % i == 0) {
std::cout << i << ' ';
++factorCount;
}
}
std::cout << n << '\n';
return factorCount;
}
The main problem with your code is that your function always returns zero. You need to keep a count of factors and return it.
Besides that your code performance badly as the loop goes on much longer than needed. You can use the square root of n as the limit in the for loop. Like:
int fact(int n)
{
if (n < 1) return 0;
int res = 0;
int limit = sqrt(n);
for (int i = 1; i <= limit; ++i)
{
if (n % i == 0)
{
res += 2;
cout << i << " - " << n/i << endl;
}
}
if (limit * limit == n)
{
--res;
}
return res;
}
For n = 36 the output is:
1 - 36
2 - 18
3 - 12
4 - 9
6 - 6
and the returned value is 9
Below is another approach. It doesn't use square root. Instead it keeps the number of loops low by using the square of i as loop limit.
int fact(int n)
{
if (n < 1) return 0;
int res = 0;
int i = 1;
int i_square = i * i;
while (i_square < n)
{
if (n % i == 0)
{
res += 2;
cout << i << " - " << n/i << endl;
}
++i;
i_square = i * i;
}
if (i_square == n)
{
++res;
cout << i << " - " << n/i << endl;
}
return res;
}
Fact() always returns 0 so this line print 0
cout << factor;
for the number of factors you can change the return value of fact() :
int fact(int n)
{
int nb = 0;
for (int i = 1; i <= n; ++i)
{
if (n % i == 0) {
cout << i << endl;
nb++;
}
}
return nb;
}

Filter out duplicate values in array in C++

I have a row of ten numbers for example:
5 5 6 7 5 9 4 2 2 7
Now I want a program that finds all duplicates and gives them out in the console like 3 times 5, 2 times 2, 2 times 7.
While I did code an algorithm that finds duplicates in a row of numbers I can't give them out in the console as described. My program will output:
3 times 5
2 times 5
2 times 7
2 times 2
How can I solve this problem?
#include <iostream>
using namespace std;
int main()
{
int arr[10];
int i,j;
int z = 1;
for(i = 0; i < 10; i++) {
cin >> arr[i];
}
for(i = 0; i < 10; i++){
for(j = i+1; j < 10; j++){
if(arr[i] == arr[j]){
z++;
}
}
if(z >= 2){
cout << z << " times " << arr[i] << endl;
z = 1;
}
}
return 0;
}
You can use the STL here (C++11):
int arr[10];
std::map<int, int> counters;
for (auto item : arr)
{
cin >> item;
++counters[item];
}
std::for_each(counters.begin(), counters.end(), [](const std::pair<int,int>& item)
{
if(item.second > 1) std::cout << item.second << " times " << item.first << std::endl;
});
You need to check that arr[i] is not already found before, like this for example:
if(z >= 2) {
int found_before = 0;
for(j = 0; j < i; ++j)
if(arr[i] == arr[j])
found_before = 1;
if(!found_before)
cout << z << " times " << arr[i] << endl;
z = 1;
}
which will print:
3 times 5
2 times 7
2 times 2
That way you don't print 5 again.
With your code it would print that it found 5 three times (for the first 5 in your array), and then when it would move to he second 5 in your array, it would forgot about the first 5 in your array, and report that it found 5 twice (itself and the 5th number of the array).
Why not use STL?
std::map<int, int> counter;
for (i = 0; i < 10; i++)
counter[arr[i]] ++;
for (i = 0; i < 10; i++) {
if (counter.count(arr[i]) > 0){
std::cout << counter[arr[i]] << " times "<< arr[i] << std::endl;
counter.erase(arr[i]);
}
}
std::map is a convenient tool for this job. You can easily count up occurrences of a specific number. After counting, you can print the count of each array element. With counter.erase, it's guaranteed that you won't print the same element for multiple times.
Why keeping your algorithm idea, I suggest to create sub method:
std::size_t count(const int* arr, std::size_t start, std::size_t end, int value)
{
std::size_t res = 0;
for (std::size_t i = start; i != end; ++i) {
if (arr[i] == value) {
++res;
}
}
return res;
}
then your fixed algorithm would be:
for (std::size_t i = 0; i != 10; ++i) {
if (count(arr, 0, i, arr[i]) != 0) {
continue; // Already visited
}
auto total = count(arr, i, 10, arr[i]);
if(total >= 2){
std::cout << z << " times " << arr[i] << std::endl;
}
}
An easy way is to make another array for it, especially if the numbers are not that big.
Lets say you have initialized your array like so: int nums[10] = { 5, 5, 6, 7, 5, 9, 4, 2, 2, 7 }
int result[max(nums)]; //Fill with zeroes, max(nums) is the highest number in the array
for(int i = 0; i < 10; i++) {
result[nums[i]]++;
}
for(int i = 0; i < max(nums); i++) {
if (result[i] > 1) cout << result[i];
}
Mind you this isn't optimized for memory. For larger number contents you might want to consider hashmaps.
If you don't need performance but rather compact code, then std::multiset with std::upper_bound is an alternative:
#include<set>
#include<iostream>
#include<algorithm>
int main(int a, char** b)
{
int array[] = {5, 5, 6, 7, 5, 9, 4, 2, 2, 7};
std::multiset<int> a(std::begin(array), std::end(array));
for(auto it = a.begin(); it != a.end(); it = std::upper_bound(a.begin(), a.end(), *it))
{
if(a.count(*it) > 1)
std::cout << *it << " times " << a.count(*it) << std::endl;
}
return 0;
}

How to move elements in an array, putting odds to the beginning of the array (smallest to largest), and evens to the back ( largest to smallest )

I have to write a functioncalled moveAndSortInt() that will receive an array of integers as an argument, and move all the even values down to the second half of the array and sort them from largest to smallest, while all the odd values will be sorted from smallest to largest. How can I improve my code?
#include <iostream>
using namespace std;
void moveAndSortInt(int[], int);
void displayName();
int main() {
int ary1[] = { -19, 270, 76, -61, 54 };
int size = 5;
int i;
int ary2[] = {9, 8, -103, -73, 74, 53};
int size2 = 6;
int j;
displayName();
cout << endl;
cout << "Original ary1[]" << endl;
for (i = 0; i < size; i++) {
cout << " " << ary1[i] << " ";
}
cout << endl;
cout << "\nCallingMoveAndSortInt() --\n " << endl;
moveAndSortInt(ary1, size);
cout << "Updated ary1[]" << endl;
for (i = 0; i < size; i++) {
cout << " " << ary1[i] << " ";
}
cout << endl;
cout << "\nOriginal ary2[]" << endl;
for (j = 0; j < size2; j++) {
cout << " " << ary2[j] << " ";
}
cout << endl;
cout << "\nCallingMoveAndSortInt() --\n" << endl;
moveAndSortInt(ary2, size2);
cout << "Updated ary2[]" << endl;
for (j = 0; j < size2; j++) {
cout << " " << ary2[j] << " ";
}
}
void moveAndSortInt(int ary[], int size) {
int i, j;
int temp;
for (i = 0; i < 1 + size / 2; i++) {
if (ary[i] % 2 == 0) {
for (j = size - 1; j > size / 2; j--) {
if (ary[j] % 2 != 0) {
temp = ary[i];
ary[i] = ary[j];
ary[j] = temp;
j = 0;
}
}
}
}
return;
I would suggest using std::sort, the standard algorithm for sorting, which is often implemented with a Quicksort. It is very fast, and also supports custom comparison. Here's some code to get you started:
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> data = { 2, 213, 2, 2, 3 ,123, 4, 213, 2132, 123 };
std::sort(data.begin(), data.end(), [](int lhs, int rhs)
{
if (lhs % 2) // if lhs is odd
if (rhs % 2) // and rhs is odd then just use comparision
return lhs < rhs;
else // and if rhs is even then rhs is "bigger"
return false;
else // if lhs is even
if (rhs % 2)
return true; // and rhs is odd then lhs is "bigger"
else // and if they are both even just use comparision.
return lhs < rhs;
});
}
I'm sorry if that code is a little hard to read, but it does the trick.
This of course would work with C-style arrays too, just replace data.begin() with data and data.end() with data + size.
Alright, so I looked at it a bit. Let's start with conventions.
int i;
for (i = 1; i < 10; i++)
Can be shortened to:
for (int i = 1; i < 10; i++)
Which looks better and is more readable. It would also be nice to have a few more comments, but that's something everyone needs to get better at, no matter how good they are.
So it seems that your code does correctly sort the array into even and odd halves. That's all you need to do yourself as long as you know where they end because sorting them largest to smallest is something that std::sort can do for you.
Edit: It was pointed out to me that my previous example is not exactly the same, as with the second one i can only be used in the loop. For your purposes, they work the same.
You can just reorder it
#include <algorithm>
#include <climits>
#include <iostream>
#include <vector>
int main()
{
auto const shuffle = [] (int input)
{
if ( input % 2 )
{
unsigned const dist_from_min = (unsigned)input - INT_MIN;
return dist_from_min >> 1;
}
else
{
unsigned const dist_from_max = INT_MAX - (unsigned)input;
return INT_MIN + (dist_from_max >> 1);
}
};
auto const ordering = [shuffle] (int left, int right)
{ return shuffle (left) < shuffle (right); };
std::vector <int> data =
{ 5, 2, 3, 0, -1, -3, 1, 100
, INT_MIN, INT_MIN + 1, INT_MAX, INT_MAX - 1
, -567, -765, 765, 567, -234, -432, 234, 432
};
std::sort ( data.begin ( ), data.end ( ), ordering );
for ( auto item : data )
std::cout << item << "\n";
}

Merge sort code debugging

I am trying to write a code for merge sort. I am not getting the correct output. I am following this pseudocode link Following is my code. I pass my unsorted array into merge_sort function and call merge function recursively to sort and combine the sub arrays.I know there are more simpler and efficient ways to write code for merge sort but I want to try on my own otherwise I won't learn. Thanks in advance.
int* merge_sort(int* a,int size)
{
//cout<<size;
//cout<<"hi";
if(size == 1)
{
//cout<<"less";
//cout<<a[0];
return a;
}
int* left;
int* right;
int middle = ceil(size/2);
left = new int(middle);
right = new int(middle);
for(int i=0;i<middle;i++)
{
left[i]=a[i];
//cout<<left[i];
}
cout<<"\t";
for(int j=middle;j<size;j++)
{
right[j]=a[j];
//cout<<right[j];
}
cout<<"\t";
left = merge_sort(left,middle);
//if(size==2)
//cout<<left[0];
right = merge_sort(right,middle);
//if(size==2)
//cout<<right[0];
return merge(left,right,middle);
}
int* merge(int* l,int* r,int m)
{
int* result;
result = new int(2*m); //to store the output
int lsize=m; // to keep track of left sub list
int rsize=m; // to keep track of right sub list
int counter = 0; // will use to index result
//cout<<m;
while(lsize>0 || rsize>0)
{
if(lsize>0 && rsize>0)
{
if(l[0]<=r[0])
{
result[counter]=l[0];
counter++; //to store next value in result
lsize--;
l=&l[1]; //decrementing the size of left array
}
else
{
result[counter]=r[0];
counter++;
rsize--;
r=&r[1]; //dec. size of right array
}
}
else if(lsize>0)
{
result[counter]=l[0];
counter++;
lsize--;
l=&l[1];
}
else if(rsize>0)
{
result[counter]=l[0];
counter++;
lsize--;
l=&l[1];
}
}
return result;
}
Your code:
int *left = new int(middle);
allocates a single integer initialized to middle. You need:
int *left = new int [middle];
which allocates an array of middle integers. Rinse and repeat for int *right. Actually, you need to use:
int *right = new int [size - middle];
This gets the correct size for the right array. You then have to modify the recursive call to merge_sort() for the right sub-array:
merge_sort(right, size - middle);
Finally, you have to rewrite merge() to take the size of the left array and the size of the right array independently, because they may be of different sizes. For example, if you sort 10 elements,
you then end up with a call to merge two arrays of 5 (which is fine), but at the next level you need to merge an array of 2 and an array of 3 elements (and you're hosed).
The allocation of result also has the () vs [] allocation problem. And there are some other as yet unresolved problems. But these are important steps in the right direction.
As mentioned in a comment to the question, you have a monumental memory leakage problem, too. What's more, it is not trivial to fix because merge_sort() does an early exit without allocating new memory, so it isn't as simple as 'delete the memory returned by merge_sort()'.
Copy and paste is wonderful until you forget to edit the pasted copy correctly:
else if (lsize > 0)
{
result[counter] = l[0];
counter++;
lsize--;
l = &l[1];
}
else if (rsize > 0)
{
result[counter] = l[0];
counter++;
lsize--;
l = &l[1];
}
Methinks you should be using r and rsize in the second of these blocks.
This still isn't the whole story...
And the residual problem (apart from memory management, which is still 100% leaky and problematic) is:
for(int j=middle;j<size;j++)
{
right[j]=a[j];
//cout<<right[j];
}
You're copying into parts of right that you've not allocated. You need something more like:
for(int j = 0; j < size - middle; j++)
{
right[j] = a[j + middle];
//cout<<right[j];
}
This code works as long as you always sort at least two items at the top level (you crash freeing unallocated space if you sort 1 item — that's part of the memory management problem).
#include <iostream>
using namespace std;
namespace {
int *merge(int *l, int m, int *r, int n);
void dump_array(int *a, int size)
{
int i;
cout << size << ": ";
for (i = 0; i < size; i++)
{
cout << ' ' << a[i];
if (i % 10 == 9)
cout << '\n';
}
if (i % 10 != 0)
cout << '\n';
}
};
int *merge_sort(int *a, int size)
{
cout << "-->> merge_sort:\n";
dump_array(a, size);
if (size <= 1)
{
cout << "<<-- merge_sort: early return\n";
return a;
}
int middle = size/2;
int *left = new int[middle];
int *right = new int[size - middle];
cout << middle << ": ";
for (int i = 0; i < middle; i++)
{
left[i] = a[i];
cout << ' ' << left[i];
}
cout << "\n";
cout << (size - middle) << ": ";
for (int j = 0; j < size - middle; j++)
{
right[j] = a[j + middle];
cout << ' ' << right[j];
}
cout << "\n";
cout << "MSL:\n";
int *nleft = merge_sort(left, middle);
cout << "NL: ";
dump_array(nleft, middle);
cout << "OL: ";
dump_array(left, middle);
cout << "OR: ";
dump_array(right, size - middle);
cout << "MSR:\n";
int *nright = merge_sort(right, size - middle);
cout << "NR: ";
dump_array(nright, size - middle);
cout << "NL: ";
dump_array(nleft, middle);
cout << "OL: ";
dump_array(left, middle);
cout << "OR: ";
dump_array(right, size - middle);
int *result = merge(nleft, middle, nright, size - middle);
cout << "<<-- merge_sort:\n";
dump_array(result, size);
return result;
}
namespace {
int *merge(int *l, int m, int *r, int n)
{
int *result = new int[m + n];
int lsize = m;
int rsize = n;
int counter = 0;
cout << "-->> merge: (" << m << "," << n << ")\n";
dump_array(l, m);
dump_array(r, n);
while (lsize > 0 || rsize > 0)
{
if (lsize > 0 && rsize > 0)
{
if (l[0] <= r[0])
{
result[counter] = l[0];
cout << "C: " << counter << "; L = " << l[0] << "; LS = " << lsize << '\n';
counter++;
lsize--;
l++;
}
else
{
result[counter] = r[0];
cout << "C: " << counter << "; R = " << r[0] << "; RS = " << rsize << '\n';
counter++;
rsize--;
r++;
}
}
else if (lsize > 0)
{
result[counter] = l[0];
cout << "C: " << counter << "; L = " << l[0] << "; LS = " << lsize << '\n';
counter++;
lsize--;
l++;
}
else if (rsize > 0)
{
result[counter] = r[0];
cout << "C: " << counter << "; R = " << r[0] << "; RS = " << rsize << '\n';
counter++;
rsize--;
r++;
}
}
cout << "<<-- merge:\n";
dump_array(result, m+n);
return result;
}
};
int main()
{
for (int i = 2; i <= 10; i++)
{
int array1[] = { 9, 3, 5, 7, 1, 8, 0, 6, 2, 4 };
cout << "\nMerge array of size " << i << "\n\n";
int *result = merge_sort(array1, i);
delete[] result;
}
return 0;
}
This is the debug-laden code. It's the level to which I went to get the result. I could perhaps have used a debugger. Were I on a machine where valgrind works, it might have helped too (but it does not work on Mac OS X 10.8.x, sadly).
There are still many, many ways to improve the code — including the memory management. You'd probably find it easiest to pass the input array to merge() for use as the result array (avoiding the memory allocation in that code). This would reduce the memory management burden.
When you remove the debug code, you'll need to call the dump_array() function in the main() program to get the before and after sorting array images.
Code converted to template functions and leak-free
I've simplified the code a fair bit, especially in the merge() function. Also, more as a matter of curiosity than anything else, converted it to a set of template functions, and then used them with 4 different array types (int, double, std::string, char). The amount of debugging has been dramatically reduced, and the main debugging is conditional on being compiled with -DTRACE_ENABLED now.
The code is now leak-free; valgrind on a Linux box (virtual machine) gives it a clean bill of health when there are no exceptions. It is not guaranteed exception-safe, though. In fact, given the naked uses of new and delete, it is pretty much guaranteed not to be exception-safe. I've left the namespace control in place, but I'm far from convinced it is really correct — indeed, I'd lay odds on it not being good. (I'm also curious if anyone has any views on how to layout code within a namespace { … }; block; it seems odd not indenting everything inside a set of braces, but …)
#include <iostream>
using namespace std;
namespace {
#if !defined(TRACE_ENABLED)
#define TRACE_ENABLED 0
#endif
enum { ENABLE_TRACE = TRACE_ENABLED };
template <typename T>
void merge(T *l, int m, T *r, int n, T *result);
template <typename T>
void dump_array(const char *tag, T *a, int size)
{
int i;
cout << tag << ": (" << size << ") ";
for (i = 0; i < size; i++)
{
cout << " " << a[i];
if (i % 10 == 9)
cout << '\n';
}
if (i % 10 != 0)
cout << '\n';
}
};
template <typename T>
void merge_sort(T *a, int size)
{
if (size <= 1)
return;
if (ENABLE_TRACE)
dump_array("-->> merge_sort", a, size);
int middle = size/2;
T *left = new T[middle];
T *right = new T[size - middle];
for (int i = 0; i < middle; i++)
left[i] = a[i];
for (int j = 0; j < size - middle; j++)
right[j] = a[j + middle];
merge_sort(left, middle);
merge_sort(right, size - middle);
merge(left, middle, right, size - middle, a);
delete [] left;
delete [] right;
if (ENABLE_TRACE)
dump_array("<<-- merge_sort", a, size);
}
namespace {
template <typename T>
void merge(T *l, int m, T *r, int n, T *result)
{
T *l_end = l + m;
T *r_end = r + n;
T *out = result;
if (ENABLE_TRACE)
{
cout << "-->> merge: (" << m << "," << n << ")\n";
dump_array("L", l, m);
dump_array("R", r, n);
}
while (l < l_end && r < r_end)
{
if (*l <= *r)
*out++ = *l++;
else
*out++ = *r++;
}
while (l < l_end)
*out++ = *l++;
while (r < r_end)
*out++ = *r++;
if (ENABLE_TRACE)
dump_array("<<-- merge", result, m+n);
}
};
#include <string>
int main()
{
for (size_t i = 1; i <= 10; i++)
{
int array1[] = { 9, 3, 5, 7, 1, 8, 0, 6, 2, 4 };
if (i <= sizeof(array1)/sizeof(array1[0]))
{
cout << "\nMerge array of type int of size " << i << "\n\n";
dump_array("Original", array1, i);
merge_sort(array1, i);
dump_array("PostSort", array1, i);
}
}
for (size_t i = 1; i <= 10; i++)
{
double array2[] = { 9.9, 3.1, 5.2, 7.3, 1.4, 8.5, 0.6, 6.7, 2.8, 4.9 };
if (i <= sizeof(array2)/sizeof(array2[0]))
{
cout << "\nMerge array of type double of size " << i << "\n\n";
dump_array("Original", array2, i);
merge_sort(array2, i);
dump_array("PostSort", array2, i);
}
}
for (size_t i = 1; i <= 10; i++)
{
std::string array3[] = { "nine", "three", "five", "seven", "one", "eight", "zero", "six", "two", "four" };
if (i <= sizeof(array3)/sizeof(array3[0]))
{
cout << "\nMerge array type std::string of size " << i << "\n\n";
dump_array("Original", array3, i);
merge_sort(array3, i);
dump_array("PostSort", array3, i);
}
}
for (size_t i = 1; i <= 10; i++)
{
char array4[] = "jdfhbiagce";
if (i <= sizeof(array4)/sizeof(array4[0]))
{
cout << "\nMerge array type char of size " << i << "\n\n";
dump_array("Original", array4, i);
merge_sort(array4, i);
dump_array("PostSort", array4, i);
}
}
return 0;
}

C++ Array copying/shift

We had a project that asked us to Write a program that allows a user to enter a series of numbers "read numbers into an array for further processing, user signals that they are finished by entering a negative number (negative not used in calculations), after all numbers have been read in do the following, sum up the #'s entered, count the #'s entered, find min/max # entered, compute average, then output them on the screen. So the working version of this that I made looks like so
/* Reads data into array.
paramater a = the array to fill
paramater a_capacity = maximum size
paramater a_size = filled with size of a after reading input. */
void read_data(double a[], int a_capacity, int& a_size)
{
a_size = 0;
bool computation = true;
while (computation)
{
double x;
cin >> x;
if (x < 0)
computation = false;
else if (a_size == a_capacity)
{
cout << "Extra data ignored\n";
computation = false;
}
else
{
a[a_size] = x;
a_size++;
}
}
}
/* computes the maximum value in array
paramater a = the array
Paramater a_size = the number of values in a */
double largest_value(const double a[], int a_size)
{
if(a_size < 0)
return 0;
double maximum = a[0];
for(int i = 1; i < a_size; i++)
if (a[i] > maximum)
maximum = a[i];
return maximum;
}
/* computes the minimum value in array */
double smallest_value(const double a[], int a_size)
{
if(a_size < 0)
return 0;
double minimum = a[0];
for(int i = 1; i < a_size; i++)
if (a[i] < minimum)
minimum = a[i];
return minimum;
}
//computes the sum of the numbers entered
double sum_value(const double a [], int a_size)
{
if (a_size < 0)
return 0;
double sum = 0;
for(int i = 0; i < a_size; i++)
sum = sum + a[i];
return sum;
}
//keeps running count of numbers entered
double count_value(const double a[], int a_size)
{
if (a_size < 0)
return 0;
int count = 0;
for(int i = 1; i <= a_size; i++)
count = i;
return count;
}
int _tmain(int argc, _TCHAR* argv[])
{
const int INPUT_CAPACITY = 100;
double user_input[INPUT_CAPACITY];
int input_size = 0;
double average = 0;
cout << "Enter numbers. Input negative to quit.:\n";
read_data(user_input, INPUT_CAPACITY, input_size);
double max_output = largest_value(user_input, input_size);
cout << "The maximum value entered was " << max_output << "\n";
double min_output = smallest_value(user_input, input_size);
cout << "The lowest value entered was " << min_output << "\n";
double sum_output = sum_value(user_input, input_size);
cout << "The sum of the value's entered is " << sum_output << "\n";
double count_output = count_value(user_input, input_size);
cout << "You entered " << count_output << " numbers." << "\n";
cout << "The average of your numbers is " << sum_output / count_output << "\n";
string str;
getline(cin,str);
getline(cin,str);
return 0;
}
That went fine, the problem I am having now is part 2. Where we are to "copy the array to another and shift an array by N elements". I'm not sure where to begin on either of these. I've looked up a few resources on copying array's but I was not sure how to implement them in the current code I have finished, especially when it comes to shifting. If anyone has any thoughts, ideas, or resources that can help me on the right path it would be greatly appreciated. I should point out as well, that I am a beginner (and this is a beginners class) so this assignment might not be the 'optimal' way things could be done, but instead incorporates what we have learned if that makes sense.
for(int i = 0; i < n; ++i){
int j = (i - k)%n;
b[i] = a[j];
}
Check it. I'm not sure
If this works you could improve it to
for(int i = 0; i < n; ++i)
b[i] = a[(i - k)%n];//here can be (i +/- k) it depends which direction u would shift
If you only want to copy the array into another array and shift them
ex : input = 1, 2, 3, 4, 5; output = 3, 4, 5, 1, 2
The cumbersome solution is
//no template or unsafe void* since you are a beginner
int* copy_to(int *begin, int *end, int *result)
{
while(begin != end){
*result = *begin;
++result; ++begin;
}
return result;
}
int main()
{
int input[] = {1, 2, 3, 4, 5};
size_t const size = sizeof(input) / sizeof(int);
size_t const begin = 2;
int output[size] = {0}; //0, 0, 0, 0, 0
int *result = copy_to(input + begin, input + size - begin, output); //3, 4, 5, 0, 0
copy_to(input, input + begin, result); //3, 4, 5, 1, 2
return 0;
}
How could the stl algorithms set help us?
read_data remain as the same one you provided
#include <algorithm> //std::minmax_element, std::rotate_copy
#include <iostream>
#include <iterator> //for std::begin()
#include <numeric> //for std::accumulate()
#include <string>
#include <vector>
int main(int argc, char *argv[]) //don't use _tmain, they are unportable
{
const int INPUT_CAPACITY = 100;
double user_input[INPUT_CAPACITY];
int input_size = 0;
double average = 0;
cout << "Enter numbers. Input negative to quit.:\n";
read_data(user_input, INPUT_CAPACITY, input_size);
auto const min_max = std::minmax_element (user_input, user_input + input_size); //only valid for c++11
std::cout << "The maximum value entered was " << min_max.second << "\n";
std::cout << "The lowest value entered was " << min_max.first << "\n";
double sum_output = std::accumulate(user_input, user_input + input_size, 0);
cout << "The sum of the value's entered is " << sum_output << "\n";
//I don't know the meaning of you count_value, why don't just output input_size?
double count_output = count_value(user_input, input_size);
cout << "You entered " << count_output << " numbers." << "\n";
cout << "The average of your numbers is " << sum_output / count_output << "\n";
int shift;
std::cout<<"How many positions do you want to shift?"<<std::endl;
std::cin>>shift;
std::vector<int> shift_array(input_size);
std::rotate_copy(user_input, user_input + shift, user_input + input_size, std::begin(shift_array));
//don't know what are they for?
std::string str;
std::getline(std::cin,str);
std::getline(std::cin,str);
return 0;
}
if your compiler do not support c++11 features yet
std::minmax_element could replace by
std::min_element and std::max_element
std::begin() can replace by shift_array.begin()
I don't know what is the teaching style of your class, in my humble opinion, beginners should
start with those higher level components provided by c++ like vector, string, algorithms
and so on.I suppose your teachers are teaching you that way and you are allowed to use the
algorithms and containers come with c++(Let us beg that your class are not teaching you "c with classes" and say something like "OOP is the best thing in the world").
ps : You could use vector to replace the raw array if you like