Finding the maximum sum in a field of numbers - c++

I have to write a program that sums up sequential elements of an array and outputs the maximum sum. As you will see my algorithm won't work if all elements are negative.
#include <iostream>
int main()
{
int nums[1000] = {-1,-3,-4,-2,-5,-1,-9,-4,-2,-2};
int sums[100][100];
int n = 9;
for(int i = 0; i <= n; i++) {
for(int j = n; j >= i; j--) {
for(int k = j; k >= i; k--) {
sums[i][j] += nums[k];
}
}
}
int max_sum = 0;
int max_begin;
int max_end;
for(int i = 0; i <= n; i++) {
for(int j = i+1; j <= n; j++){
std::cout << "i = " << i << " j = " << j << ": " << sums[i][j] << "\n";
if(max_sum < sums[i][j]) {
max_sum = sums[i][j];
max_begin = i;
max_end = j;
}
}
}
std::cout << "Maximum: " << max_sum << " bei i = " << max_begin << " bis j = " << max_end;
return 0;
}
I already tried this solution
#include <climits>
...
int max_sum = INT_MIN;
...
While this works perfectly fine we didn't have climits in our lecture yet so I'm looking for another way.

Change to:
int max_sum = sums[0][0];
This way you will never have to worry about the range of numbers.

This is one of the main motivations for a std::optional type (when all values in a range are valid). If you cannot use it, we can imitate it for our purposes with a simple boolean:
bool max_set = false;
int max_sum = 0;
// ...
if (!max_set || max_sum < sums[i][j]){
max_set = true;
max_sum = sums[i][j];
}
We can make a simple class to further imitate it if we'd like (untested code):
class optional_int{
bool is_set = false;
int value = 0;
public:
bool operator()() const{return is_set;}
int& operator=(int _value){value = _value; is_set=true; return value;}
int& get(){
if (!is_set){throw std::logic_error("attempting to access unset optional");}
return value;
};
optional_int max_sum;
//...
if (!max_sum || max_sum.get() < sums[i][j]){
max_sum = sums[i][j];
}
We can continue to make this type more and more generic, but we'd only be re-implementing std::optional

Related

Reliable comparison of double

I have an admittedly very basic problem: I need to compare two numbers of type double for >=. For some reason, however, my code evaluates to true for values I know to be less than the threshold.
EDIT: My code (the error occurs in the countTrig() method of the Antenna class):
#define k 0.0000000000000000000000138064852 // Boltzmann's constant
class Antenna{
vector<vector<double> > output;
int channels, smplrate, smpldur, samples, timethld;
double resistance, temp, bandwidth, lnanoise, lnagain, RMS;
public:
Antenna(
const int _channels, const int _smplrate, const int _smpldur,
const double _resistance, const double _temp, const double _bandwidth,
const double _lnanoise, const double _lnagain
){
channels = _channels; smplrate = _smplrate; smpldur = _smpldur;
resistance = _resistance; temp = _temp; bandwidth = _bandwidth;
lnanoise = _lnanoise; lnagain = _lnagain;
RMS = 2 * sqrt(4 * k * resistance * temp * bandwidth);
RMS *= lnagain * pow(10,(lnanoise/10));
samples = smplrate/smpldur;
timethld = 508; //= (1/smplrate) * 0.127;
}
void genThrml(int units);
void plotTrig(int timethld, double voltsthld);
void plotThrml();
int countTrig(double snrthld, int iter);
};
double fabs(double val){ if(val < 0){ val *= -1; } return val; }
void Antenna::genThrml(int units){
output.resize(samples, vector<double>(channels));
samples *= units;
gRandom->SetSeed(time(NULL));
for(int i = 0; i < samples; ++i){
for(int j = 0; j < channels; ++j){
output[i][j] = gRandom->Gaus(0,RMS);
}
}
}
void Antenna::plotThrml(){
//Filler
}
int Antenna::countTrig(double snrthld, int iter){
int count = 0;
int high = iter + timethld;
int low = iter - timethld;
if(low < 0){ low = 0; }
if(high > samples){ high = samples; }
for(int i = low; i < high; ++i){
for(int j = 0; j < channels; ++j){
if(output[i][j] >= snrthld) count++; std::cout << output[i][j] << " " << snrthld << "\n";
}
}
if(iter >= 3) return 1;
else return 0;
}
void Antenna::plotTrig(int timethld, double voltsthld){
double snrthld = voltsthld / RMS;
for(int i = 0; i < samples; ++i){
for(int j = 0; j < channels; ++j){
countTrig(snrthld, i);
}
}
}
int main(){
Antenna test(20,4000,1,50,290,500000000,1.5,60);
test.genThrml(1);
test.plotTrig(400,0.0005);
return 0;
}
With a threshold of 0.147417, I get output like this:
0.0014238
-0.00187276
I believe I understand the problem (unless there's some obvious mistake I've made and not caught), and I understand the reasoning behind floating point errors, precision, etc. I don't, however, know, what the best practice is here. What is a good solution? How can I reliably compare values of type double? This will be used in an application where it is very important that values be precise and comparisons be reliable.
EDIT: A smaller example:
int countTrig(double snrthld, int iter, vector<vector<double> > output, int timethld){
int count = 0;
int high = iter + timethld;
int low = iter - timethld;
if(low < 0){ low = 0; }
if(high > 3){ high = 3; }
for(int i = low; i < high; ++i){
for(int j = 0; j < 3; ++j){
if(fabs(output[i][j]) >= snrthld) count++; std::cout << output[i][j] << " " << snrthld << "\n";
}
}
if(iter >= 3) return 1;
else return 0;
}
void plotTrig(int timethld, double snrthld){
vector<vector<double> > output = {{0.000028382, -0.0028348329, -0.00008573829},
{0.183849939, 0.9283829020, -0.92838200021},
{-0.00292889, 0.2399229929, -0.00081009189}};
for(int i = 0; i < 3; ++i){
for(int j = 0; j < 3; ++j){
countTrig(snrthld, i, output, timethld);
}
}
}
int main(){
plotTrig(1,0.1);
return 0;
}
You have a typo.
if(output[i][j] >= snrthld) count++; std::cout << output[i][j] << " " << snrthld << "\n";
this line means
if(output[i][j] >= snrthld)
count++;
std::cout << output[i][j] << " " << snrthld << "\n";
aka
if(output[i][j] >= snrthld)
{
count++;
}
std::cout << output[i][j] << " " << snrthld << "\n";
and you want:
if(output[i][j] >= snrthld)
{
count++;
std::cout << output[i][j] << " " << snrthld << "\n";
}

Bubble sort logical error?

I am trying to do a bubble sort, but I don't know what's happening in my code. I am a noob so sorry if the code I wrote seems obvious ^.^
main() {
int a[5], i, j, smallest, temp;
cout << "Enter 5 numbers: " << endl;
for ( i = 0; i <= 4; i++ ) {
cin >> a[i];
}
for ( i = 0; i <=4; i++ ) {
smallest = a[i];
for ( j = 1; j <= 4; j++ ) {
if ( smallest > a[j] ) {
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
cout << endl << endl;
for ( i = 0; i <= 4; i++ ) {
cout << a[i] << endl;
}
system("pause");
}
Any answer will be highly appreciated. Thanks!
Your bubblesort almost appears to be a selection sort. Bubblesort looks at pairs of items and swaps them if necessary. Selection sort looks for the lowest item in the rest of the array, and then swaps.
#include <iostream>
#include <utility>
using std::cin;
using std::cout;
using std::endl;
using std::swap;
void bubblesort(int a[5])
{
bool swapped = true;
while (swapped)
{
swapped = false;
for (int i = 0; i < 4; i++)
{
if (a[i] > a[i + 1])
{
swap(a[i], a[i + 1]);
swapped = true;
}
}
}
}
void selectionSort(int a[5])
{
for (int i = 0; i < 4; i++)
{
int smallest = i;
for (int j = smallest; j < 5; j++)
{
if (a[smallest] > a[j])
{
smallest = j;
}
}
if (smallest != i)
{
swap(a[i], a[smallest]);
}
}
}
int main(int argc, char* argv[])
{
int a[5];
cout << "Enter 5 numbers: " << endl;
for (int i = 0; i < 5; i++ )
{
cin >> a[i];
}
//selectionSort(a);
bubblesort(a);
cout << endl << endl;
for (int i = 0; i <= 4; i++ ) {
cout << a[i] << endl;
}
}

Codeforces "The New President "

I tried to answer write a code to solve this problem, but I'm still getting a wrong answer at test 15 and I don't know what is missing in my code.
I tried a lot of test cases but the code has solved them all correctly.
My Code :
#include <iostream>
#include <map>
#include <vector>
using namespace std;
int main()
{
int c; cin >> c;
int v; cin >> v;
if (c == 1 && v == 0)
{
cout << 1 << " " << 1;
}
else
{
int cArray[c + 1];
int voting[v][c];
for (int j = 0; j<v; j++)
{
for (int z = 0; z<c; z++)
{
int temp; cin >> temp;
voting[j][z] = temp;
}
}
for (int j = 0; j <= c; j++)cArray[j] = 0;
for (int j = 0; j<v; j++)cArray[voting[j][0]]++;
int maxim = 0;
int maxN = 0;
int count = 0;
map<int, int > cand;
for (int j = 1; j <= c; j++)
{
if (cArray[j]>maxN)
{
cand.clear();
cand[j] = 1;
maxN = cArray[j];
maxim = j;
count = 0;
}
else if (cArray[j] == maxN)
{
cand[j] = 1;
count++;
}
}
if (count == 0)
cout << maxim << " " << 1;
else
{
for (int j = 0; j<v; j++)
{
for (int z = 1; z<c; z++)
{
if (cand.count(voting[j][z]))
{
cArray[voting[j][z]]++;
break;
}
}
}
maxim = 0;
maxN = 0;
count = 0;
for (int j = 1; j <= c; j++)
{
if (cArray[j]>maxN)
{
maxN = cArray[j];
maxim = j;
count = 0;
}
else if (cArray[j] == maxN)
{
count++;
}
}
cout << maxim << " " << 2;
}
}
return 0;
}
Your algorithm for checking the first round (win or top two candidates) seems wrong. It looks like you are expecting the top two candidates to have the same number of primary votes - this is not the case. You want to pick the top two candidates and the top one wins if it has more than 50 % of the vote.
I don't want to give you the answer (as that is the point of doing the exercises), but you need to rethink how you are processing the first part of the vote.
Also note that once someone has voted for one of the top two candidates, their secondary votes should not then count toward the other candidate (which you are currently doing).

Shouldn't this recursive method end as soon as you get to the return?

I would like to know why my output is:
a-b-b-b-b-0
When I think it should just be a-1.
Shouldn't a recursive method end as soon as you get to a return? and why doesn't it here?
I only put the letters with '-' to clarify that the returns are being met but not stopping there.
#include <stdio.h>
#include <iomanip>
#include <iostream>
using namespace std;
void printv(int mask[], int elements[], int n)
{
int i;
printf("{ ");
for (i = 0; i < n; i++)
if (mask[i])
printf("%d ", elements[i]);
printf("}");
}
int next(int mask[], int size)
{
int i;
for (i = 0; (i < size) && mask[i]; i++)
mask[i] = 0;
if (i < size) {
mask[i] = 1;
return 1;
}
return 0;
}
void nSubsets(int mask[], int elements[], int size, int n)
{
int sum = 0;
int temp[10], count = 0;
for (int i = 0; i < 10; i++) //this MUST be here
temp[i] = 0;
for (int i = 0; i < size; i++)
{
if (mask[i])
{
count++;
for (int k = 0; k < 44; k++)
if (temp[k] == 0)
{
temp[k] = elements[i];
sum += elements[i];
break;
}
}
}
if (sum == n)
{
cout << "{ ";
for (int l = 0; l < count; l++)
cout << temp[l] << " ";
cout << "}";
}
}
int isEmptySet(int mask[], int elements[], int size, int n, int sizeRecursion)
{
int sum = 0;
int temp[10], count = 0;
for (int i = 0; i < 10; i++) //this MUST be here
temp[i] = 0;
for (int i = 0; i < size; i++)
{
if (mask[i])
{
count++;
for (int k = 0; k < 44; k++)
if (temp[k] == 0)
{
temp[k] = elements[i];
sum += elements[i];
break;
}
}
}
if (sum == n)
{
cout << "a-";
return 1;
}
sizeRecursion--;
if (sizeRecursion > 0)
{
next(mask, size);
isEmptySet(mask, elements, size, n, sizeRecursion);
}
cout << "b-";
return 0;
}
int main()
{
int n, size = 10;
int elements[size];
size = 6; n = 5;
elements[0] = 5;
elements[1] = 2;
elements[2] = 3;
elements[3] = 2;
elements[4] = 1;
elements[5] = 1;
int mask[10];
int i;
for (i = 0; i < size; ++i)
mask[i] = 0;
cout << "Subsets of elements: ";
printv(mask, elements, size); //this prints first subset
while (next(mask, size))
printv(mask, elements, size);
n = 3;
cout << "\nSubsets equal to " << n << "\n";
while (next(mask, size))
nSubsets(mask, elements, size, n);
cout << "\n" << isEmptySet(mask, elements, size, n, size);
return 0;
}
Shouldn't a recursive method end as soon as you get to a return? and why doesn't it here?
No, the way it works in general is that when a function call returns, it only returns for that function call, and then the immediate caller may continue execution. It doesn't matter whether the function is recursive or not, each function call is separate and each call needs to hit a return statement at some point (unless the return type is void).
When you have this code
...
if(sizeRecursion > 0)
{
next(mask,size);
isEmptySet(mask, elements, size, n,sizeRecursion);
}
cout<<"b-";
return 0;
}
What's going to happen is, as soon as the recursive call to isEmptySet returns, its going to go right to the cout << "b-"; line and then to return 0;. If you don't want that then you should put those in an else block, and maybe also modify the line that calls isEmptySet so that it returns the value returned from that call.

Sorting an array (c++)

I'm studying C++ and I had the task to create array[n][m], to fill it with integer numbers, then
"Characteristic of matrix rows is called the sum of its positive even elements. You need to sort the rows of the matrix in accordance with the growth of characteristics."
It's my code
#include "stdafx.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
srand((unsigned)time(NULL));
int n, m;
cout << "n = ";
cin >> n;
cout << "m = ";
cin >> m;
int ** mas = new int * [n];
for (int i = 0; i < n; ++i)
{
mas[i] = new int[m];
}
cout << "Array:\n";
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
mas[i][j] = rand()%41-20;
cout << mas[i][j] << "\t";
}
cout << "\n";
}
double * characteristic = new double[n];
for (int i = 0; i < n; ++i)
{
characteristic[i] = 0;
}
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
if((j%2 == 0) && (mas[i][j] >= 0))
{
characteristic[i] += mas[i][j];
}
}
}
cout << "Characteristics:\n";
for (int i = 0; i < n; ++i)
{
cout << characteristic[i] << " ";
}
cout << "\n";
for (int i = 0; i < n - 1; ++i)
{
int min = i;
for (int j = i + 1; j < n; ++j)
{
if (characteristic[min] <= characteristic[j]) continue;
min = j;
}
if (min != i)
{
double temp = characteristic[i];
characteristic[i] = characteristic[min];
characteristic[min] = temp;
for (int k = 0; k < m; ++k)
{
int temp1 = mas[i][k];
mas[i][k] = mas[min][k];
mas[min][k] = temp1;
}
}
}
cout << "\nSorted characteristics:\n";
for (int i = 0; i < n; ++i)
{
cout << characteristic[i] << " ";
}
cout << "\n";
cout << "Sorted array:\n";
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
cout << mas[i][j] << "\t";
}
cout << "\n";
}
for (int i = 0; i < n; ++i)
{
delete [] mas[i];
}
delete [] mas;
delete [] characteristic;
system("PAUSE");
return 0;
}
I created another one array for characteristics and sorted it and the first array at the same time, but it seems I used too difficult way to accomplish a given task. Maybe are there other ways?
Did you want to sort the matrix too, using the same ordering as the 'characteristic's?
Let's say you had C++ style code to calculate the characteristics:
std::vector<double> characteristic(n, 0.0);
std::transform(begin(mas), end(mas), begin(characteristic), sum_);
You could then sort them:
std::sort(begin(characteristic), end(characteristic));
Or you could, indeed sort the matrix immediately:
std::sort(begin(mas), end(mas), [&sum_](int_vec const& a, int_vec const& b)
{ return sum_(a)<sum_(b); });
Edit Fixed all versions to use the correct "characteristic sum" (kept the name though), thanks #Adam
Here's a full program that demonstrates this: See it Live on Coliru
#include <random>
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <iterator>
using namespace std;
int main()
{
typedef std::vector<int> int_vec;
srand((unsigned)time(NULL));
int n, m;
cout << "n = ";
cin >> n;
cout << "m = ";
cin >> m;
std::vector<int_vec> mas(n, int_vec(m));
for (auto& v : mas)
std::for_each(begin(v), end(v), [](int& i) { i = rand()%41-20; });
cout << "Array:\n";
for (auto const& v : mas)
{
std::copy(begin(v), end(v), ostream_iterator<int>(cout, "\t"));
cout << "\n";
}
auto sum_ = [m](int_vec const& v) {
double vchar = 0;
for (auto j = 0; j < m; j+=2)
if(v[j] >= 0) vchar += v[j];
return vchar;
};
std::vector<double> characteristic(n, 0.0);
std::transform(begin(mas), end(mas), begin(characteristic), sum_);
cout << "Characteristics:\n";
std::copy(begin(characteristic), end(characteristic), ostream_iterator<double>(cout, " "));
cout << "\n";
std::sort(begin(characteristic), end(characteristic));
cout << "\nSorted characteristics:\n";
std::copy(begin(characteristic), end(characteristic), ostream_iterator<double>(cout, " "));
cout << "\n";
std::sort(begin(mas), end(mas), [&sum_](int_vec const& a, int_vec const& b) { return sum_(a)<sum_(b); });
cout << "Sorted Array:\n";
for (auto const& v : mas)
{
std::copy(begin(v), end(v), ostream_iterator<int>(cout, "\t"));
cout << "\n";
}
}
Sample output:
n = m = Array:
11 15 19 18
-20 -16 2 -11
8 2 19 8
Characteristics:
30 2 27
Sorted characteristics:
2 27 30
Sorted Array:
-20 -16 2 -11
8 2 19 8
11 15 19 18
#sehe gives you great advice, but I suspect a lot of that stuff won't make sense until you know more C++.
Here's a simple improvement to eliminate a slow loop:
When doing your row swaps swap the row pointers instead of copying every value that they point to. Replace this:
for (int k = 0; k < m; ++k)
{
int temp1 = mas[i][k];
mas[i][k] = mas[min][k];
mas[min][k] = temp1;
}
With:
int* temp1 = mas[i];
mas[i] = mas[min];
mas[min] = temp1;
If you can figure out how to use a built-in sort algorithm that would be another improvement on top of this, but even this small change will gain you a lot.
Since the sizes n,m are known in compile time, you can use the qsort function from the C library.
#include <stdlib.h>
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
Where is compar is a function you write, which should treat both its arguments as pointers to a row of the matrix. Then it can calculate the characteristic of both rows, and return -1, 0 or 1 depending on which row's characteristic is greater.