Competitive programming questions says wrong answer - c++

Paradox with averages Programming problem
I have an class of Computer Science students represented with an array, and a class of Economics students also represented as an array.
The array is filled with values representing each students IQ.
One well-known joke goes as follows: If a bad Computer Science student drops out of college and goes to a different college to study Economics instead, he will increase the average intelligence on both colleges.
I have to run through the computer science array and check if each student leaves and joins economics, will he increase the average IQ of both groups. I then have to count how many students and print to the screen.
I seem to have gotten the right answer but one of the test cases is wrong, can anyone lay their wisdom upon me? thanks.
int main() {
int cases;
cin >> cases;
for(int i = 0; i < cases; i++)
{
int numCs;
int numEc;
cin >> numCs;
cin >> numEc;
int csArray[numCs];
int ecArray[numEc];
long csTotal = 0;
long ecTotal = 0;
for(int j = 0; j < numCs; j++)
{
cin >> csArray[j];
csTotal += csArray[j];
}
for(int j = 0; j < numCs; j++)
{
cin >> ecArray[j];
ecTotal += ecArray[j];
}
double csAvg = csTotal / (double)numCs;
double ecAvg = ecTotal / (double)numEc;
int count = 0;
for(int j = 0; j < numCs; j++)
{
if((csArray[j] < csAvg) && (csArray[j] > ecAvg))
{
count++;
}
}
cout << count << endl;
}
return 0;
}

You second loop should run till numE not numC.
Also floating point division can be tricky at times since it is a finite approximation so line
if((csArray[j] < csAvg) && (csArray[j] > ecAvg))
can be replaced by
(csTotal > numCs * csArray[j]) && (ecTotal < numEc * csArray[j])
This conveys the same meaning without the hassle of floating point computation.

Related

Performance bottleneck in writing a large matrix of doubles to a file

My program opens a file which contains 100,000 numbers and parses them out into a 10,000 x 10 array correlating to 10,000 sets of 10 physical parameters. The program then iterates through each row of the array, performing overlap calculations between that row and every other row in the array.
The process is quite simple, and being new to c++, I programmed it the most straightforward way that I could think of. However, I know that I'm not doing this in the most optimal way possible, which is something that I would love to do, as the program is going to face off against my cohort's identical program, coded in Fortran, in a "race".
I have a feeling that I am going to need to implement multithreading to accomplish my goal of speeding up the program, but not only am I new to c++, I am new to multithreading, so I'm not sure how I should go about creating new threads in a beneficial way, or if it is even something that would give me that much "gain on investment" so to speak.
The program has the potential to be run on a machine with over 50 cores, but because the program is so simple, I'm not convinced that more threads is necessarily better. I think that if I implement two threads to compute the complex parameters of the two gaussians, one thread to compute the overlap between the gaussians, and one thread that is dedicated to writing to the file, I could speed up the program significantly, but I could also be wrong.
CODE:
cout << "Working...\n";
double **gaussian_array;
gaussian_array = (double **)malloc(N*sizeof(double *));
for(int i = 0; i < N; i++){
gaussian_array[i] = (double *)malloc(10*sizeof(double));
}
fstream gaussians;
gaussians.open("GaussParams", ios::in);
if (!gaussians){
cout << "File not found.";
}
else {
//generate the array of gaussians -> [10000][10]
int i = 0;
while(i < N) {
char ch;
string strNums;
string Num;
string strtab[10];
int j = 0;
getline(gaussians, strNums);
stringstream gaussian(strNums);
while(gaussian >> ch) {
if(ch != ',') {
Num += ch;
strtab[j] = Num;
}
else {
Num = "";
j += 1;
}
}
for(int c = 0; c < 10; c++) {
stringstream dbl(strtab[c]);
dbl >> gaussian_array[i][c];
}
i += 1;
}
}
gaussians.close();
//Below is the process to generate the overlap file between all gaussians:
string buffer;
ofstream overlaps;
overlaps.open("OverlapMatrix", ios::trunc);
overlaps.precision(15);
for(int i = 0; i < N; i++) {
for(int j = 0 ; j < N; j++){
double r1[6][2];
double r2[6][2];
double ol[2];
//compute complex parameters from the two gaussians
compute_params(gaussian_array[i], r1);
compute_params(gaussian_array[j], r2);
//compute overlap between the gaussians using the complex parameters
compute_overlap(r1, r2, ol);
//write to file
overlaps << ol[0] << "," << ol[1];
if(j < N - 1)
overlaps << " ";
else
overlaps << "\n";
}
}
overlaps.close();
return 0;
Any suggestions are greatly appreciated. Thanks!

How to compare structs faster (who met the most people problem)

I will start by saying that I'm not a native speaker so please excuse me my grammatical errors.
I'm an university student and my task is the following: I have an input that tells me the number of people, and then every line contains the time of arrival and the time of exit, both natural numbers separated by a space.
I have to find the (index of the) person who met the most people and then output the number of meetings that person had.
Example input and output:
If person A has datestamps of 3 and 6 and person B has 6 and 7, it is still considered a meeting.
I already solved this problem with a fixed size array of structs that compares every person to everybody else to find out the number of meetings and then searched for the person with the most meetings.
My problem is that this code is very slow and I must hadle inputs consisting of maximum 200000 people and timestamps ranging from 1 to 1000000.
This - compare everyone with everyone else - solution works for small sample sizes, but there is no way it can work for 200000 structs.
Also, this code has to successfully run under 0.2 sec.
What is a faster way to solve this?
#include <iostream>
using namespace std;
const int maxN = 20000;
struct Data {
int arrival;
int departure;
int meetings = -1;
};
int main()
{
Data x[maxN];
int N;
///input
cin >> N;
for (int i = 0; i < N; i++) {
cin >> x[i].arrival;
cin >> x[i].departure;
}
for(int i = 0; i < N; i++) {
for(int j = 0; j < N; j++){
if ( ((x[i].arrival >= x[j].arrival && x[i].arrival <= x[j].departure) || (x[i].departure >= x[j].arrival && x[i].departure <= x[j].departure)) || ((x[j].arrival >= x[i].arrival && x[j].arrival <= x[i].departure) || (x[j].departure >= x[i].arrival && x[j].departure <= x[i].departure)) ) {
x[i].meetings++;
}
}
}
int maxInd = 0;
int maximum = 0;
for(int i = 0; i < N; i++) {
if (x[i].meetings > maximum){
maxInd = i;
maximum = x[i].meetings;
}
}
///output
cout << maxInd+1 << endl;
cout << maximum << endl;
return 0;
}
I will only give you a starting point...
If I had to solve it, i would start by defining the following structure:
struct come_or_go {
size_t person_index;
int time;
bool arrival; // true for arrival, false for leaving
};
Next I would read the input into a vector<come_or_go> with two entries for each person. One when it arrives and one when it leaves. Next I'd sort that vector with respect to the elements time member. Finally I'd try to come up with a clever idea that requires to traverse this vector only once.
So far thats all I can provide, maybe I will update when I can give more hints. Hope this helps to push you into a differernt direction, because your brute force simply looses by complexity. Instead of trying to get details of it "faster" you need to change your overall approach.
I managed to do it by creating a vector and storing the 100.000 points of time in it.
I added 1 to each index where a person came in, stayed, and left.
Working with 100.000 long vectors, I managed to solve this problem with only one for loop se it ran reasonably fast.

Searching an array with user-input

There’s a problem I have trouble solving.
Shortly written, here’s how it goes:
There are N professors at a school, born in a certain year and you need to find the amount of years the professors share (if two professors share a year, it’s one year which is repeated).
Example: Input: (first line) 3 (second line) 1975 1960 1975 Output: (third line) 1
I’ve started somehow, and I have only managed to create the input:
int N;
cin >> N;
int array[N];
for (int i = 0; i < N; i++) {
cin >> array[i];
}
Now, I don’t know how to continue, or use the information (years) the user has entered.
Edit: Although there might be better ways of solving this, I am just looking for a simple solution, or a code explaining how I can continue this program.
Edit: It should display the amount of years which repeat.
In your program above, you were able to have the user input how many years they are entering as well as the years you are comparing. Now to get the output, you should use for loops to iterate through the array and compare the years.
For example:
User entered: 1975 1960 1975
In your code this will be stored as: array[0] = 1975, array[1] = 1960, array[2] = 1975.
One option I would suggest would be:
Iterate through the array and count the number of duplicates. If we find a higher count, then set that as the highest number of duplicates.
Example: Read in 1975 and compare with each element if there are duplicates. If we find a duplicate, then increase the counter. If the counter is greater than the highest count, then that becomes the highest count. Repeat this process for the entire array.
Program:
int N;
cin >> N;
int A[N];
int highest_count = 0;
for (int i = 0; i < N; i++) {
cin >> A[i];
}
for (int i = 0; i < N; i++) {
int counter = 0;
for (int j = i; j < N; j++) {
if (A[i] == A[j] {
counter++;
}
if (counter > highest_count) {
highest_count = counter;
}
}
}
cout << highest_count;

Simple C++ Summing Program

This is my first time using C++ and I am writing a small program to sum up to ten numbers (doubles) that will be entered in the command prompt.
I have written the following code and I cannot figure out why it will not produce the desired result.
int main()
{
double num[10];
double sum = 0;
int i;
int n = 10;
while (scanf_s("%lf", &num) != EOF)
{
for (i = 0; i < n; ++i)
{
scanf_s("%lf", &num);
sum = sum + num[i];
}
}
cout << sum;
system("pause");
return 0;
}
The data entry is terminated with a control D.
In my eyes it should run fine but it doesn't. Could someone please give me some pointers for solving this, I don't just want to be told the correct way I would rather learn it myself.
The problem is that &num is the address of the array. SO you read your value always in num[0] meaning that num[i]is random in most of the cases.
Try to change your loop:
for (i = 0; i < n && (cin>>num[i]); ++i)
{
sum = sum + num[i];
}

Reordering Indices for matrix multiplication in c++

const int n=50;
double a[n][n];
double b[n][n];
double c[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
c[i][j] += a[i][k] * b[k][j];
}
cout << c[i][j] << " ";
}
cout << "\n";
I currently have a working code that multiplies two nxn matrices. I am trying to reorder the indices (ie i,k,j ... k,i,j) without touching the equation that does the multiplication. I am doing this to see how the order of the indices affects performance time, but if I just change the 'j's to 'k's and vice versa in my loops, my multiplication equation will not be correct.
I am wondering if what I am attempting to do is possible and if anyone can shed some light on what steps I can take to achieve this.
First of all, you shouldn't be printing out the c matrix at the point you are doing so, especially if you are trying to time an algorithm. What you should be doing is more similar to this:
const int n=50;
double a[n][n];
double b[n][n];
double c[n][n];
/* First multiply the matrices a,b into c. */
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
c[i][j] += a[i][k] * b[k][j];
}
}
}
/* now print out the result for visual correctness check */
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
std::cout << c[i][j] << ' '; //this will leave a space after last character, but for this use case, nobody cares.
}
std::cout << std::endl;
}
Then you can just switch around the lines containing for loops (ie. for (int i = 0; i < n; i++)) around, and see if changing access pattern changes execution time/results.
Spoiler: It shouldn't affect results except in some border cases of weird values inside the matrices, that are caused by inexactness of floating point math. It should however affect execution time, but it will be brutally dominated by time taken by printing the matrix, unless measured properly.
If you are taking about performance time then It always come down to complexity. No matter how you change the order, your complexity is defined by the area of code which is doing most of your work.
Here all your loops run till n. Now no matter what order you change you have complexity of order O(n^3) Unless you change your logic. The best Matrix Multiplication Algorithm known so far is the Coppersmith-Winograd algorithm with O(n^2.3736 ) complexity but it is not used for practical purposes.
But you can use Strassen's algorithm which has O(n^2.8074 ) complexity