Finding closest numbers within two arrays [closed] - c++

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I have to find closest numbers within two arrays and shows their difference. I am using a loop for that but it takes too much time. Do you know any way to make that algorithm faster?
#include <cmath>
#include <cstdio>
using namespace std;
long long int red, yellow, minimum = 1000000000, difference = 0;
long long int TC[100001], ZT[100001];
int main()
{
scanf("%d", &red);
for (int y = 0; y < red; ++y)
{
scanf("%d", &TC[y]);
}
scanf("%d", &yellow);
for (int yy = 0; yy < yellow; ++yy)
{
scanf("%d", &ZT[yy]);
}
for (int yyy = 0; yyy < red; ++yyy)
{
for (int i = 0; i < yellow; ++i)
{
difference = abs(TC[yyy] - ZT[i]);
if (difference == 0)
{
minimum = 0;
break;
}
else if (difference < minimum)
minimum = difference;
}
}
printf("%d \n", minimum);
}

This shoud be O(nlgn):
sort two lists
let i = 0, j = 0, minval = abs(list1[0] - list2[0])
as long as both lists have more items:
minval = min(minval, abs(list1[i] - list2[j])
if abs(list1[i + 1] - list2[j]) < abs(list1[i] - list2[j + 1])
increment i
else increment j

If you sort them, you can optimize algorithm to run much faster. When your both arrays are sorted, you can check one by one and compare them less than your current algorithm. Because you'll skip some of them, since you know they are sorted.
By the way, since you get the numbers from user, I suggest you to put numbers in sorted. Every time user enters a number, put the number in a place where numbers after it are bigger than it and numbers before it are less than it. To do such a thing, maybe using linked list is better idea (or easier).

Related

Program runs in compiler but returns runtime error in online judge [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 2 years ago.
Improve this question
I'm trying to solve this problem on this online judge: https://a2oj.com/ladder?ID=3 (see problem below) using the following code. It runs successfully on the compiler but returns a runtime error on the online judge.
EDIT: Code after changing loop conditions
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
struct count {
int number;
int repetitions;
};
bool sortByNumber(const struct count &lhs, const struct count &rhs) {
return lhs.number < rhs.number;
}
int main() {
vector <int> input;
int n = 0;
do {
cin>>n;
input.push_back(n);
} while (n != 0);
struct count x[101] = {NULL};
for (int j = 0; j < input.size(); j++) {
int tracker = 0;
for (int z = 0; z < input.size(); z++) {
if (input[j] != x[z].number) {
tracker++;
}
}
if (tracker == input.size()) {
x[j].number = input[j];
}
}
sort(x, x+101, sortByNumber);
for (int y = 0; y < 101; y++) {
for (int w = 0; w < input.size(); w++) {
if (x[y].number == input[w]) {
x[y].repetitions++;
}
}
}
for (int v = 0; v < 101; v++) {
if (x[v].number != 0) {
cout << x[v].number << " " << x[v].repetitions << endl;
}
}
return 0;
}
I'm fairly new to programming so I apologize if the answer is obvious and I can't see it. I've researched causes of runtime errors and I can't see any memory leaks, logic errors, or divisions by zero. The only thing I can think of is that it's a segmentation fault caused by the many nested loops (this code uses a lot more memory and running time than the other programs I submitted to the online judge), but I can't think of another way to solve this problem. Any ideas, even just about where to look, would be very much appreciated.
EDIT: Problem
Problem Statement:
Amgad got a job as a Cashier in a big store, where he gets thousands of dollars everyday. As a cashier, he must count the amount of each dollar bill (banknote) he has at the end of each day.
Amgad wants you to help him by writing a computer program so Amgad can just enter the amount of each bill and you count each bill separately.
Input Format:
one or more positive numbers ending by zero each number is between 1 and 100 inclusive
Output Format:
print each number only once in one line followed by the number of repetitions
Sample Input:
100
20
5
2
10
20
5
5
20
100
10
2
2
10
5
0
Sample Output:
2 3
5 4
10 3
20 3
100 2
As #Component10 mentioned, your array is of a fixed size. Add an integer called count that increments every time a new number is popped out of the input. Change all the integer literal references to 8 to counter.
If input contains more than 101 elements, the conditions
if (tracker == 8) {
x[j].number = input[j];
}
and
if (input[j] != x[z].number) {
tracker++;
}
Are invoking undefined behavior for any j value above 100, due to out-of-bounds access of array x elements. Both z, and j are looped to input.size(), which can be higher than 101.
Undefined behavior can manifest itself in many ways. Runtime error is one of those possibilities.

Sum of the first 5 even numbers from the array [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 6 years ago.
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.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Improve this question
So, I need to get the sum of the first 5 even numbers from my array, this is the code that I've got so far, have no clue what to do next. It runs, but the result is incorrect
#include "stdafx.h"
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
int niz[10];
cout << "Unesi 10 brojeva:";
for (int i = 0; i < 10; i++) {
cin >> niz[i];
}
int suma = 0;
int parni[5];
int j = 0;
for (int i = 0; i < 10; i++) {
if (niz[i] % 2 == 0) {
niz[i] == parni[j];
j++;
if (j == 5) {
break;
}
}
}
for (int i = 0; i < 5; i++) {
suma = parni[i] + suma;
}
cout << suma;
system("PAUSE");
return 0;
}
This line:
niz[i] == parni[j];
does nothing. (It tests if niz[i] happens to be equal to the current, uninitialized value of parni[j], and throws away the result of the comparison.)
You want to store niz[i] in parni[j], so do this:
parni[j] = niz[i];
Incidentally, there is a problem if there are fewer than 5 even numbers in the niz array. In that case, you still sum up all five entries of the parni array, using uninitialized values, which is Bad. One way to avoid this is to just sum up the even entries as you find them, without using a secondary array.
IE, do suma += niz[i] at the line in question, and get rid of parni altogether.
Unless you're really required to use arrays here, vectors will work much more nicely.
You can also use a couple of standard algorithms to make your life easier (especially std::copy_if and std::accumulate).
// for the moment I'll ignore the code to read the input from the user:
auto input = read_input();
auto pos = std::remove_if(input.begin(), input.end(),
[](int i) { return i % 2 != 0; });
// assume that `input` always contains at least 5 elements
pos = std::min(pos, input.begin() + 5);
sum = std::accumulate(input.begin(), pos, 0);

Relative prime numbers [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Two integers a and b are relatively prime if and only if there are no integers
x > 1, y > 0, z > 0 such that a = xy and b = xz.
I wrote program that determine how many positive integers less than n are relatively prime to n, but my program work too slow because sometimes number is too big. Can you fix my program.
My program should work for n<=1000000000
Here is my code:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
long int n;
int cntr = 0, cntr2 = 0;
cin >> n;
if (!n) return 0;
vector <int> num;
for (int i = 2; i < n; i++)
{
if (n % i != 0)
{
if (num.size()>0)
{
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] != 0)
cntr2++;
}
if (cntr2 == num.size())
cntr++;
cntr2 = 0;
}
else
cntr++;
}
else
num.push_back(i);
}
cout << cntr + 1 << endl;
}
There are many things you can do to make this task go faster. Your approach is O(N^2), which strikes me as very poor.
A first pass at a simple faster version, would be to change your rel-prime test to using GCD.
for (int i = 2; i < n; i++)
{
if (GCD(i,n)==1) cntr++
}
cout << cntr + 1 << endl;
Using a standard Euler style GCD algorithm you can find easily off the web, this would be drastically better than what you are doing.
Try the iterative GCD funciton from here:GCD function in c++ sans cmath library
If this isnt good enough for your purposes (which it may not be) then I encourage you to search the web for one of several faster approaches. but, it may help in that searching to know that you are looking for the Euler Totient function: http://en.wikipedia.org/wiki/Euler%27s_totient_function
You need to do two things:
test fewer numbers
test them faster
Regarding point 1 - there are a number of things you can do. First - if n is even, there is no point in checking even numbers - so you can increment the "number to test" by 2. If n is divisible by 3, you can skip every third number. This is fairly easy to implement and will speed your code up for some numbers. The methos that Richard Plunkett outlined will help somewhat with point 2. I think there are much faster algorithms; I'll give it some thought.
Well to make it work for larger n values replace all int's with long int's and if you are using c++11 you could use long long int's if that still is not enough. To make it run faster you could just before the outer for loop add
/*reserve Some value that is close to the outcome*/
num.reserve(n/2);
this will help but not alot.

Number prime with c++, what is wrong with the code and how to optimize? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I'm trying to figure this problem http://www.urionlinejudge.com.br/judge/problems/view/1032, where I need to find the prime numbers between 1 to 3501 the fastest way, since the time limit may not exceed 1 second.
The way I'm calculating these prime numbers is to check if they are prime until their square root, then eliminating the multiple of the first prime numbers [2, 3, 5, 7] to improve the performance of the algorithm. Yet, the time exceeds.
My code (takes 1.560s as the internal testing of the submission system)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <iostream>
#include <set>
using namespace std;
set<int> circ;
set<int> primes;
/* Calculate List Primes */
void n_prime(int qtd){
int a, flag=1, l_prime = 1;
float n;
for(int i=0;i<qtd;i++){
switch (l_prime){
case 1:
l_prime = 2;
break;
case 2:
l_prime = 3;
break;
default:
while(1){
flag=1;
l_prime+=2;
if(l_prime>7)
while(l_prime%2==0||l_prime%3==0||l_prime%5==0||l_prime%7==0) l_prime++;
n=sqrt(l_prime);
for(a=2;a<=n;a++){
if(l_prime%a==0){
flag=0;
break;
}
}
if(flag) break;
}
}
primes.insert(l_prime);
}
}
/* Initialize set with live's */
void init_circ(int t){
circ.clear();
for(int a=0;a<t;a++){
circ.insert(a+1);
}
}
/* Show last live*/
void show_last(){
for(set<int>::iterator it=circ.begin(); it!=circ.end(); ++it)
cout << *it << "\n";
}
int main(){
int n = 0;
clock_t c1, c2;
c1 = clock();
n_prime(3501);
while(scanf("%d", &n)&&n!=0){
init_circ(n);
int idx=0, l_prime,count = 0;
set<int>::iterator it;
set<int>::iterator np;
np=primes.begin();
for(int i=0;i<n-1;i++){
l_prime=*np;
*np++;
idx = (idx+l_prime-1) % circ.size();
it = circ.begin();
advance(it, idx);
circ.erase(it);
}
show_last();
}
c2 = clock();
printf("\n\nTime: %.3lf", (double)(c2-c1)/CLOCKS_PER_SEC);
return 0;
}
The easiest way is the sieve of Eratosthenes, here's my implementation:
//return the seive of erstothenes
std::vector<int> generate_seive(const ulong & max) {
std::vector<int> seive{2};
std::vector<bool> not_prime(max+1);
ulong current_prime = seive.back();
bool done = false;
while(!done){
for (int i = 2; i * current_prime <= max;i++) {
not_prime[i*current_prime]=true;
}
for (int j = current_prime+1;true;j++) {
if (not_prime[j] == false) {
if( j >= max) {
done = true;
break;
}
else {
seive.push_back(j);
current_prime = j;
break;
}
}
}
}
return seive;
}
Generates all the prime numbers under max, BTW these are the times for my sieve and 3501 as the max number.
real 0m0.008s
user 0m0.002s
sys 0m0.002s
There is a better algorithm for finding primes. Have you heard about Eratosthenes and his sieve?
Also, you are using tons of STL (i.e. the set<>) as well as remainder operations in your code. This is simply killing the speed of your program.
Some basic advice, then a basic (albeit untested) answer...
The advice: If you have one resource that's very limited, take advantage of other resources. In this case, since time is limited, take up a lot of space. Don't dynamically allocate any memory, make it all fixed length arrays.
The way I would do it is simply to have one boolean array and apply Aristophanes' sieve to it:
void findPrimes(int cap) { // set to void for now, since I don't know your return type
bool[] possibilities = new bool[cap + 1]; // has to be dynamic so that you can scale for any top
possibilities[0] = false;
possibilities[1] = false;
int found = 0;
for (int i = 2; i < cap; ) {
++found;
for (int j = i + i; j < cap; j += i) {
possibilities[j] = false;
}
do {
++i;
} while (!possibilities[i]);
}
// at this point, found says how many you've found, and everything in possibilities that is true is a factor. Just return it however you need.
I see aaronman beat me to the punch with the sieve idea. Mine is a slightly different implementation (more exactly resembles the original sieve, using only addition), and uses less dynamic memory, so I'm still submitting it.
You can get quite a nice speedup by preexcluding even numbers, just change your increment to i += 2 and make sure you don't omit 2 in your result array. You might even think about trying to preexclude multiples of 3, but that starts getting dirty. Something along the lines:
for(long i = 1; i < qtd; i += 6) {
//check if i is prime
//check if i+4 is prime
}
This should be enough to get you below the limit.
The sieve of Eratosthenes is the right way to do it, as others have suggested. But the implementations I saw here were very complicated. The sieve is extremely easy to implement. E.g.:
std::vector<int> get_primes(uint max) {
std::vector<int> primes;
std::vector<bool> is_composite(max+1,false);
for (uint i = 2; i <= max; ++i) {
if (!is_composite[i]) {
primes.push_back(i);
for (uint j = i+i; j <= max; j += i) {
is_composite[j] = true;
}
}
}
return primes;
}
There are two big, technical performance drains in your code:
You insert your primes into a vector. Whenever the vector exceeds its allocated size, it will get a new, larger buffer, copy everything over, and delete the old one. new is very expensive in terms of performance, even more expensive than the copying involved. You can avoid this by telling the vector to reserve() enough space.
You use sqrt() in your inner loop. This too is a slow function, square the prime instead (takes only one cycle on modern hardware), it will be faster.

detecting duplicate in columns of a 2D array [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I would like an algorithm that goes through a 2D array and guarantees that each column has all distinct numbers. If a dupe is found in the array it should be replaced with a random number. The random number must also preserve the uniqueness.
If we put a random number, the whole column, should be unique.
is it possible to get an O(N) solution too ?
The best way I can think of is to make an unordered_map<int,bool> for each column, iterate through the column and if you see a number for the first time set the map to true, if the value is already true it's a dupe replace it with a random number. Then check the random number in the map and do the same thing, if it's also a dupe you will have to replace it with a random number again. This algo will like run in linear time, however because of the random number dupe possibility it could run infinitely.
pseudo code
2d_array // assume M rows by N cols
array_of_hashtables // N length
for each col
for each row
if array_of_hashtables[2d_array[row][col]] == false
set it to true
else
do
set 2d_array[row][col] to random
while array_of_hashtables[2d_array[row][col]] == true
end
end
not a huge fan of writing pseudo code but this is about right
Make a std::set and insert step by step elements of every column while checking the size of the set. If the size changes the inserted value is not a duplicate, if it does just randomize a value and add it again to the set. If size changes, you can continue.
Just for the heck of it, here is an implementation of Alexandru Barbarosie's solution:
#include <iostream>
#include <set>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
int L = 3;
int W = 3;
int R = 3;
int a[L][W];
srand(time(NULL));
for (int i = 0; i < L; i++)
{
for (int j = 0; j < W; j++)
{
a[i][j] = rand() % R + 1;
cout << a[i][j] << " ";
}
cout << endl;
}
cout << endl;
set<int> s;
int n = 0;
for (int j = 0; j < W; j++)
{
for (int i = 0; i < L; i++)
{
s.insert(a[i][j]);
if (s.size() != n)
n = s.size();
else
a[i--][j] = rand() % R + 1;
}
s.clear();
n = 0;
}
for (int i = 0; i < L; i++)
{
for (int j = 0; j < W; j++)
cout << a[i][j] << " ";
cout << endl;
}
}