C++: Could someone help me optimize my solution? [closed] - c++

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 1 year ago.
Improve this question
Program adds 2 fractions and displays their sum in a reduced form (n times). Could someone help me optimize my solution (According to SPOJ, the time limit has been exceeded)
My solution:
#include <iostream>
using namespace std;
int main()
{
int n, a, b, c, d, gcd;
long long num, den;
cin >> n;
for(int i = 0; i < n; i++)
{
cin >> a >> b >> c >> d;
num = (a*d)+(b*c);
den = b*d;
for(int j = 1; j <= num && j <= den; ++j)
{
if(num % j == 0 && den % j == 0)
{
gcd = j;
}
}
cout << num/gcd << " " << den/gcd << endl;
}
}

The key step in your code is computing the greatest common divisor of num and den. The code does this by testing every number less than or equal to either of them to find the largest that divides both. While this is a correct algorithm, it is very slow, requiring time proportional to whichever is smaller.
To make this faster, use the Euclidean algorithm, which takes time proportional to the logarithm of the smaller number, which means it is much faster. The essence of this algorithm is to divide one number by the other and replace the larger with the resulting remainder until that remainder is zero. Concretely, copying and slightly reformatting the code from tutorialspoint.com:
int gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
Alternatively, as noted in a comment by #badfilms, C++17 contains std::gcd in the library.

Related

minimum number of moves required to convert a given into a lucky number [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
You are given a number, at a time either you can increase a number by 1 or decrease by 1 it is considered as one move find the minimum number of moves required to convert a given into a lucky number. A number is called lucky if all the digits in it are even.
I have writtern the code but I am not sure if it is correct. Can anybody please confirm me?
#include<bits/stdc++.h>
using namespace std;
int count(int n)
{
int count = 0;
while (n != 0)
{
n = n / 10;
++count;
}
return count;
}
int firstDigit(int n)
{
// Remove last digit from number
// till only one digit is left
while (n >= 10)
n /= 10;
// return the first digit
return n;
}
int main()
{
int n;
cin >> n;
int i,j,ans=0;
int x = count(n);
while(x--)
{
if(firstDigit(n)%2 != 0)
{
if(firstDigit(n) == 9)
{
ans = ans + pow(10,x);
n = n-pow(10,x);
}
else
{
ans = ans + pow(10,x);
n = n + pow(10,x);
}
}
else
n = n - pow(10,x);
}
cout << ans << endl;
}
Edit:
I found it is giving wrong answer at 100. Can you please help me in finding out the mistake
Not all code can easily be tested, thats why you should strive to write testable code right from the start (instead of first writing it all and then try to confirm correctness). In your case testability could benefit a lot from moving most logic from main into a dedicated function:
int minimal_steps(int input) {
....
}
Once you have that, you can either call it in main with user supplied input just as you do it now, but you can also write tests more easily:
void test() {
assert( minimal_steps(2222) == 0);
assert( minimal_steps(2221) == 1);
...etc...
}
Once you got into the habit of testing your code (you should also write tests for count and firstDigit) you may consider to use a testing framework to automate tests.
PS: It isnt wrong, but it is such a waste of CPU cycles that it is worth mentioning (actually it was already mentioned in a comment). You do not need to compute pow(10,x) in a loop where x is the loop counter. Consider that you are computing 10^2 almost as many times as the loop has iterations. Also 10^3 is the same in every iteration. Instead you should only update with *10 (in case x is incremented) or /10 when x decrements between iterations. Moreover, pow is for floating-points, not for integers.

TLE in C++ code of number of arithmetic progressions in {1,2,3,...,n} [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
How to find the number of arithmetic progressions in {1,2,3,...,n}, including trivial arithmetic progressions of lengths 1,2.
n <= 1e10
a(n+1) = (n + 1)(1 + Sum_{i=1..n} floor(n/i)) - Sum_{i=1..n} itau(i).
I used this formula, and my code is Time Limit Exceeded
//C++
const int mod = 1000000007;
long long L(long long n){
long long res = n;
for (int i = 1; i <= n-1; i++)
res = (res + (n-1)/i * (n+(n-1)%i-i+1) / 2) % mod;
return res;
}
now I can improve it:
Sum_{k=1..n} floor(n/k) = 2*(Sum_{i=1..floor(sqrt(n))} floor(n/i)) - floor(sqrt(n))^2
Sum_{i=1..n} itau(i) = Sum_{i=1..floor(sqrt(n))} ifloor(n/i)(1+floor(n/i)) - [floor(sqrt(n))(1+floor(sqrt(n)))/2]^2
I need just O(sqrt(n))
I have to assume that your intention is to generate L(n) for n from 1 to t.
By saying cin >> n; you are stopping the program to wait for console input, hence the timeout.
Try something like for (int n = 0; n < t; n++) cout >> n >> ' ' >> L(n) >> endl;
(The algorithm works BTW, I generated the 1st 1000 and matched against OEIS List)

Get number of digits in an int without divided by 10 [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Is there a way to get the number of digits without the division by 10?
For example i have this:
int main()
{
int dividend = 100;
int remainder=0;
int temp = 0;
while(dividend>=10)
{
dividend = dividend-10;
temp+=1;
}
printf("Quotient: %d\n",temp);
printf("Reminder: %d\n",dividend);
}
And now I will add to calculate the number of digits of the variable dividend.
You have to know the maximum range of integer to make this function usefull.
no function call, no division ...
int nbDigitInteger(int number)
{
if (-10 < number && number < 10) return (1);
if (-100 < number && number < 100) return (2);
if (-1000 < number && number < 1000) return (3);
if (-10000 < number && number < 10000) return (4);
if (-100000 < number && number < 100000) return (5);
...
}
Sometime, the simplier is the best.
If you are allowed to use logarithms then
int i = 123456;
int digitsCount = ceil(log10(abs(i)+1.0));
cout << digitsCount;
6
Your question is too broad, and the code is also unrelated.
Since you attempted to post the code, I'll provide the guidelines for the problem you asked for. Write the code yourself.
Take the absolute integer value. (abs())
Print it to a (large enough) buffer. (sprintf()/ snprintf()).
Use strlen() to get the length of the buffer (as string).
An alternative to the very elegant solution o #Yola is this.
intPow10 is returning 10 to the power exponent. I did not use pow from math.h, since it is numerically expensive and as #Tom's pointed out it can lead to invalid results.
#include <stdio.h>
#include<math.h>
int intPow10(int exponent){
int retval=1;
while (exponent){
retval *=10;
exponent --;
}
return retval;
}
int numDigits(const int i) {
int digits = 1;
while (intPow10(digits) <= fabs(i)) {
digits++;
}
printf("%i has %i digits.\n", i,digits);
return digits;
}
int main() {
numDigits(1);
numDigits(-1);
numDigits(10);
numDigits(13);
numDigits(-112312);
}
Is this code golf or what?
int b = 1000;
char a[10] = itoa(b);
printf("%d\n", strlen(a)); // 4
This simply turns b into a string, which is a. Then, prints the length. What would we do without atoi() and itoa()? Our own functions!

How to make this algorithm faster? [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 8 years ago.
Improve this question
I am trying to come up with the following algorithm:
The input is unsigned integer number.
The output is the size of the array of unordered pairs of unsigned integers, which, when multiplied, give a number less then or equal to the input.
I have one naive implementation working, but it is way too slow for my purpose (compl. O(n^2), please correct me if I am wrong). My question is: how to make it faster?
#include <iostream>
using namespace std;
bool notInYet(int t[][1], int mi, int ma, int m) {
bool val = true;
for(int i = 0; i < m; i++)
if(t[i][0] == mi && t[i][1] == ma)
val = false;
return val;
}
int main() {
int n, m;
int t[100000][1];
cin >> n;
m = 0;
for(int i = 1; i <= n; i++) {
for(int j = 1; j*i <= n && j <= i; j++) {
if(notInYet(t, j, i, m)) {
t[m][0] = j;
t[m][1] = i;
//cout << "t[" << m << "] = (" << t[m][0] << ", " << t[m][1] << ")" << endl;
m++;
}
}
}
cout << m << endl;
return 0;
}
I think it should be something like that - pseudocode:
int counter = 0;
for int i = 1 to sqrt(input), i++ {
if (input % i == 0) counter++;
}
counter is an answer if you need unique pairs, otherwise you need to multiply it by 2 (and sub 1 if input % sqrt(input) == 0)
If I'm reading correctly #jauser's algorithm doesn't get what you want.
If the target is 5, then the pairs are (1,1)(1,2)(1,3)(1,4)(1,5)(2,2). So the answer is 6. His algorithm will produce 1 because 5 mod 1 == 0, but not mod 2.
In general, if the target is n, then you know (1,k) is a counted pair for all k from 1 to n. There are n - 1 + 1 = n of these. Now you have (2,k) for k from 2 to floor(n/2) (skip 1 because your pairs are unordered). There are n/2-2+1 of these. Continue this through (j,k) for j= floor(sqrt(n)). Putting this is pseudocode
count = 0;
for j in 1 .. floor(sqrt(n))
count += floor(n / j) - j + 1;
Maybe there is even some clever series solution that gets this to a constant time calculation.
Am I missing something in the problem?
Well, you are spending a lot of time effectively calculating the following per i:
j= n/i;
So if you just do that you reduce the complexity to O(n). You can halve it also since the list will contain both (i, j) and (j, i) when i!=j, but that won't reduce the overall complexity.

Need help in avoiding 'Wrong Answer' on SPOJ [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
Problem : http://www.spoj.com/problems/EGYPIZZA/
I've been trying to solve this 'PIZZA' problem for quite some time and I have tried many, many
inputs and it seems to be working fine on my machine but the online judge keeps refusing to accept mu code saying its the wrong answer!!
Please help me out...
Here's my code:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char str[4],b[3][4]= {"1/4","1/2","3/4"};
unsigned int n, s = 1, count1 = 0, count2 = 0, count3 = 0;
scanf("%u",&n);
while(n--)
{
cin>>str;
if(strcmp(str,b[0])==0)
count2++;
else if(strcmp(str,b[1])==0)
count1++;
else if(strcmp(str,b[2])==0)
count3++;
}
while(count3!=0 && count2!=0)
{
count2--; count3--; s++;
}
if(count1%2!=0)
if(count2/2!=0)
{
count2-=2; count1--; s++;
}
s = s + (count1/2) + (count1%2) + (count2/4) + (count2%4) + count3 ;
printf("%u\n",s);
return 0;
}
EDIT :
I have updated my code after your suggestions please check it out guys!!
Still giving wrong answer..
Accepted Solution:
#include<iostream>
using namespace std;
int main()
{
string s;
int n, sum = 1, count1 = 0, count2 = 0, count3 = 0, extra;
cin >> n;
for (int i=0; i < n; i++)
{
cin >> s;
if (s == "1/2")count1 ++;
if (s == "1/4")count2 ++;
if (s == "3/4")count3 ++;
}
sum += count3 + count1/2.0 + 0.5;
extra = count3 + (count1%2)*2;
if (count2 >= extra)
{
count2 -= extra;
sum += count2 / 4.0 + 0.75;
}
cout << sum << endl;
return 0;
}
This problem would be more interesting if aboTrika don't insist on having his pizza one piece as the others. :)
Your program has numerous problems, such as using vectors where simple counters will suffice, and using floating point where integer arithmetic is appropriate. Perhaps the most serious problem is the statement s = s + q/4 + h/2 which in effect satisfies most requests for 1/4 pizza by grouping quarter-pizzas together and grouping half-pizzas together. Instead, requests for 1/4 pizza should be used first to complement as many 3/4-pizza requests as possible, then to fill up a 1/2-pizza request if the requested number of halves is odd, and only then used together.