Actually this is one of the challenges from hackerearth. Here is the link to the problem : https://www.hackerrank.com/challenges/antipalindromic-strings
I somehow figured a way to find the answer. But the problem my code doesn't get accepted due to timeout. Please help me which part makes my code slower.
This is my code :
int anti_palindrome(long int n,long int m,int mod)
{
int prod;
prod=m;
if(n>1)
prod=prod*(m-1);
if(n>2)
{
n=n-2;
while(n)
{
prod=prod*(m-2);
n--;
}
}
return prod%mod;
}
int main()
{
char scanned[1000];
int input = 0;
int T=0;
int T_cur=0;
long int N,M;
char str[1000];
int mod=1000000007;
while(fgets(scanned,1000,stdin))
{
switch(input)
{
case 0: {
T=atoi(scanned);
input=1;
}
break;
case 1: {
T_cur++;
strcpy(str,scanned);
sscanf(str,"%d %d",&N,&M);
//printf("%lf %lf\n",N,M);
printf("%d\n",anti_palindrome(N,M,mod));
}
break;
}
if(T_cur==T)
break;
}
return 0;
}
Any one run of the program may need to process up to 105 N, M pairs, with N and M each between 1 and 109.
Please help me which part makes my code slower.
There aren't many parts to consider. Generally speaking, I/O is much slower than computation, but you haven't any more I/O than is needed, so let's disregard that for the moment.
Consider, then, your anti_palindrome() function. In the general case, it loops N times, performing three arithmetic operations and two assignments in each iteration. That's not expensive on a per-iteration basis, but you may have a billion iterations per test case, and ten thousand test cases, for a total of around 5x1014 mixed operations. That number of operations is going to take more than a few seconds.
While I'm at it, I observe that your algorithm is wrong anyway. You are supposed to report the answer modulo 109 + 7, but long before you get to the end of the computation, you will have overflowed the prod variable. The resulting behavior is undefined. If prod had an unsigned type then the behavior would be defined, but still wrong. Switching to pow() instead of a loop would improve the performance enormously, but would not solve this problem. You need something cleverer.
As m-2 is constant, write m= m-2; before the loop. Now, what remains is that n times prod=prod*m; is executed. This is equivalent to prod= prod*pow(m,n); The math library may have an efficient implementation of pow() that will prevent your timing issue.
In C you may have to cast the parameters to double, and the return value to long int.
int anti_palindrome(long int n,long int m,int mod)
{
int prod;
prod=m;
if(prod>1)
prod=prod*(m-1);
if(prod>2)
{
n=n-2;
m=m-2;
prod= prod*pow(m,n);
}
return prod%mod;
}
Related
My code generates 5 random numbers and I want the user to guess these numbers after 5 seconds of flashing it.
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
main()
{
menuchoose1();
}
int menuchoose1(){
int menu1choose;
int score=0;
int mode,i,j;
int n=5;
printf("1.Continuous Mode\n");
printf("2.Stage Mode\n");
scanf("%d",&menu1choose);
switch(menu1choose){
int answers;
case 1:
srand(time(NULL)* getpid() );
int a[5];
unique(a,5,10,99);
int i;
printf("You have 5 seconds to remember these numbers\n");
for(i=0;i<5;i++)
printf("%d\t",a[i]);
sleep(5);
system("cls");
scanf("%d",&answers);
if(answers==a[i]){
printf("Correct");
}else
printf("Incorrect");
break;
}
return;
}
void unique(int array[], int length, int min, int max){
int new_randomnum;
bool unique;
int i;
for(i=0;i<length;i++){
do{
new_randomnum = (rand()%(max - min + 1 )) + min;
unique = true;
int j;
for(j=0;j<0;j++)
if(array[j] == new_randomnum) unique = false;
}while(!unique);
array[i] = new_randomnum;
}
}
I've tried using scanf but it always ends up incorrect and generating it one by one then checking it one by one would be inefficient.
First off, this program produces a ton of compiler warnings. I strongly suggest you get in the habit of enabling warnings, and never ignore them! For instance, you are missing a lot of headers and forward declarations. If your compiler does not give you those warnings, then you should consider switching to a better one.
Below I will only mention those bugs that do not trigger warnings.
srand(time(NULL)* getpid() );
If you call srand on each round of the game, you risk getting the same sequence of numbers again. Just call it once at the start of the program, e.g. in main.
for(i=0;i<5;i++)
printf("%d\t",a[i]);
sleep(5);
system("cls");
scanf("%d",&answers);
if(answers==a[i]){
printf("Correct");
}else
printf("Incorrect");
break;
I fixed the indentation to emphasize the bug. The if(answers == a[i]) is after the loop and therefore i always has the value 5 when it is reached, which is out of bounds for the array a, causing undefined behavior. You probably want the code to get and check the user's answer to be in a loop of its own.
for(j=0;j<0;j++)
if(array[j] == new_randomnum)
unique = false;
The j<0 condition means this loop will never execute. You probably meant j<i.
Detail on one part of OP's code.
srand(time(NULL)* getpid() ); is a weak way to initialize the random number generator.
Example: if either of the least significant bits of time(NULL) or getpid() are 0, the product with have a least significant bit of zero. Thus that bit has a 75% change of being 0.
Instead, call srand() once, before the loops and use the 2 function calls like: (unsigned) time(NULL) ^ getpid(). By using ^, the bits will not get biased as discussed above.
This question already has answers here:
Project Euler Question 14 (Collatz Problem)
(8 answers)
Closed 3 years ago.
I was writing a program which involved input up to the range of 1 million, when I was using datatype 'int' to deal with my values the run time was very very high, the program never executed itself completely so I was not able to note down the run time.
code before;
#include<stdio.h>
int main()
{
int n,m,i,maxt=0,maxn;
for(n=2;n<=1000000;n++){
m=n;
i=0;
for(i=0;m!=1;i++){
if(m%2==0)
m=m/2;
else
m=(3*m+1);
}
if(i>maxt){
maxt=i;
maxn=n;
}
}
printf("%d%d",maxn,maxt);
return 0;
}
But then while juggling with the code I changed the datatype from 'int' to 'long long int' surprisingly the run time decreased drastically(milli seconds), can anyone explain what may be the reason behind this ?
code after;
#include<stdio.h>
int main()
{
long long int n,m,i,maxt=0,maxn;
for(n=2;n<=1000000;n++){
m=n;
i=0;
for(i=0;m!=1;i++){
if(m%2==0)
m=m/2;
else
m=(3*m+1);
}
if(i>maxt){
maxt=i;
maxn=n;
}
}
printf("%lld%lld",maxn,maxt);
return 0;
}
You are calculating the Collatz conjecture. For some numbers n as input, the m's can get very large. If m gets larger than 231, with a normal int, you get a negative number. To be more explicit: when m >= 231 and m < 232 a signed 32-bit value will be interpreted as a negative number: the computer can not see such difference when only working with 32-bit.
Negative numbers for m get caught in an endless loop never reaching the m == 1 end condition. Therefore, an int type of 64 bits is needed. On the wikipedia page, 3 different loops between negative numbers are shown, for example m=-1 becomes m=-2 which again becomes m=-1 in a never ending loop.
The first time m gets larger than 231 is for n=113383 where m reaches 2482111348.
To further clarify: the problem is not with n but with m in following loop.
m=n;
for(i=0;m!=1;i++){
if(m%2==0)
m=m/2;
else
m=(3*m+1);
}
For each n, this loop gets executed many times. m starts with getting the value of n, for example 113383. In this case, after 120 steps, m reaches 2482111348, which is so big it doesn't fit anymore in a 32-bit signed integer. On most modern processors, 2482111348 gets the same representation as -1812855948. The loop now continues further with negative values. After a while, it gets in an endless loop always repeating the same 18 numbers -17, -50, -25, ..., -34, -17. And never reaching the condition m==1 needed to stop the for-loop.
Here is a small modification to your code that works with gcc
#include<stdio.h>
#include<stdlib.h>
void overflow()
{
fprintf(stderr, "Overflow\n");
exit(1);
}
int main()
{
int n,m,i,maxt=0,maxn;
for(n=2;n<=1000000;n++){
m=n;
i=0;
for(i=0;m!=1;i++){
if(m%2==0)
m=m/2;
else {
int m_prev = m;
// Replacing m = (3*m+1) with operations that checks for
// overflow
if(__builtin_mul_overflow(m,3,&m)) {
printf("%d\n", m_prev);
printf("%d\n", INT_MAX);
overflow();
}
if(__builtin_add_overflow(m,1,&m))
overflow();
}
}
if(i>maxt){
maxt=i;
maxn=n;
}
}
printf("%lld%lld",maxn,maxt);
return 0;
}
If an overflow happens, it will print "overflow" and exit. And that's what's happening. What's happening is that the result of 3*m+1 gets too large for an int to hold, which overflows it.
You can read about those gcc functions here: https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html
I came across a question online - to find the Z function of the factorial of t nos (no of zeroes at the lsb end of the factorial)
#include<stdio.h>
int fact(int x)
{
if(x==1)
return 1;
else
return (x*fact(x-1));
}
int main()
{
int t,n,k,c;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
k=fact(n);
c=0;
while(k%10==0)
{
k/=10;
c++;
}
printf("%d\n",c);
}
return 0;
}
This is the program I made, but it's too slow. How can I do this faster?
Looking at your code I can think of two possible solutions at the first glance.
change the recursive loop into an iterative loop
use memoization to speed up calculation of already known function values (basically it works like a cache)
Memoization technique can speed up the calculation significantly, though at the cost of usage of memory.
If I were you I'd do the memoization. I am very confident your code will run faster, since it is a simple factorial function (actually a classic example for memoization, like the Fibonacci numbers).
I am unable to understand why i am getting runtime error with this code. Problem is every number >=6 can be represented as sum of two prime numbers.
My code is ...... Thanks in advance problem link is http://poj.org/problem?id=2262
#include "stdio.h"
#include "stdlib.h"
#define N 1000000
int main()
{
long int i,j,k;
long int *cp = malloc(1000000*sizeof(long int));
long int *isprime = malloc(1000000*sizeof(long int));
//long int *isprime;
long int num,flag;
//isprime = malloc(2*sizeof(long int));
for(i=0;i<N;i++)
{
isprime[i]=1;
}
j=0;
for(i=2;i<N;i++)
{
if(isprime[i])
{
cp[j] = i;
j++;
for(k=i*i;k<N;k+=i)
{
isprime[k] = 0;
}
}
}
//for(i=0;i<j;i++)
//{
// printf("%d ",cp[i]);
//}
//printf("\n");
while(1)
{
scanf("%ld",&num);
if(num==0) break;
flag = 0;
for(i=0;i<j&&num>cp[i];i++)
{
//printf("%d ",cp[i]);
if(isprime[num-cp[i]])
{
printf("%ld = %ld + %ld\n",num,cp[i],num-cp[i]);
flag = 1;
break;
}
}
if(flag==0)
{
printf("Goldbach's conjecture is wrong.\n");
}
}
free(cp);
free(isprime);
return 0;
}
Two possibilities immediately spring to mind. The first is that the user input may be failing if whatever test harness is being used does not provide any input. Without knowing more detail on the harness, this is a guess at best.
You could check that by hard-coding a value rather than accepting one from standard input.
The other possibility is the rather large memory allocations being done. It may be that you're in a constrained environment which doesn't allow that.
A simple test for that is to drop the value of N (and, by the way, use it rather than the multiple hardcoded 1000000 figures in your malloc calls). A better way would be to check the return value from malloc to ensure it's not NULL. That should be done anyway.
And, aside from that, you may want to check your Eratosthenes Sieve code. The first item that should be marked non-prime for the prime i is i + i rather than i * i as you have. I think it should be:
for (k = i + i; k < N; k += i)
The mathematical algorithm is actually okay since any multiple of N less than N * N will already have been marked non-prime by virtue of the fact it's a multiple of one of the primes previously checked.
Your problem lies with integer overflow. At the point where N becomes 46_349, N * N is 2_148_229_801 which, if you have a 32-bit two's complement integer (maximum value of 2_147_483_647), will wrap around to -2_146_737_495.
When that happens, the loop keeps going since that negative number is still less than your limit, but using it as an array index is, shall we say, inadvisable :-)
The reason it works with i + i is because your limit is well short of INT_MAX / 2 so no overflow happens there.
If you want to make sure that this won't be a problem if you get up near INT_MAX / 2, you can use something like:
for (k = i + i; (k < N) && (k > i); k += i)
That extra check on k should catch the wraparound event, provided your wrapping follows the "normal" behaviour - technically, I think it's undefined behaviour to wrap but most implementations simply wrap two positives back to a negative due to the two's complement nature. Be aware then that this is actually non-portable, but what that means in practice is that it will only work on 99.999% of machines out there :-)
But, if you're a stickler for portability, there are better ways to prevent overflow in the first place. I won't go into them here but to say they involve subtracting one of the terms being summed from MAX_INT and comparing it to the other term being summed.
The only way I can get this to give an error is if I enter a value greater than 1000000 or less than 1 to the scanf().
Like this:
ubuntu#amrith:/tmp$ ./x
183475666
Segmentation fault (core dumped)
ubuntu#amrith:/tmp$
But the reason for that should be obvious. Other than that, this code looks good.
Just trying to find what went wrong!
If the sizeof(long int) is 4 bytes for the OS that you are using, then it makes this problem.
In the code:
for(k=i*i;k<N;k+=i)
{
isprime[k] = 0;
}
Here, when you do k = i*i, for large values if i, the value of k goes beyond 4 bytesand get truncated which may result in negative numbers and so, the condition k<N is satisfied but with a negative number :). So you get a segmentation fault there.
It's good that you need only i+i, but if you need to increase the limit, take care of this problem.
have wrote the code for what i see to be a good algorithm for finding the greatest prime factor for a large number using recursion. My program crashes with any number greater than 4 assigned to the variable huge_number though. I am not good with recursion and the assignment does not allow any sort of loop.
#include <stdio.h>
long long prime_factor(int n, long long huge_number);
int main (void)
{
int n = 2;
long long huge_number = 60085147514;
long long largest_prime = 0;
largest_prime = prime_factor(n, huge_number);
printf("%ld\n", largest_prime);
return 0;
}
long long prime_factor (int n, long long huge_number)
{
if (huge_number / n == 1)
return huge_number;
else if (huge_number % n == 0)
return prime_factor (n, huge_number / n);
else
return prime_factor (n++, huge_number);
}
any info as to why it is crashing and how i could improve it would be greatly appreciated.
Even fixing the problem of using post-increment so that the recursion continues forever, this is not a good fit for a recursive solution - see here for why, but it boils down to how fast you can reduce the search space.
While your division of huge_number whittles it down pretty fast, the vast majority of recursive calls are done by simply incrementing n. That means you're going to use a lot of stack space.
You would be better off either:
using an iterative solution where you won't blow out the stack (if you just want to solve the problem) (a); or
finding a more suitable problem for recursion if you're just trying to learn recursion.
(a) An example of such a beast, modeled on your recursive solution, is:
#include <stdio.h>
long long prime_factor_i (int n, long long huge_number) {
while (n < huge_number) {
if (huge_number % n == 0) {
huge_number /= n;
continue;
}
n++;
}
return huge_number;
}
int main (void) {
int n = 2;
long long huge_number = 60085147514LL;
long long largest_prime = 0;
largest_prime = prime_factor_i (n, huge_number);
printf ("%lld\n", largest_prime);
return 0;
}
As can be seen from the output of that iterative solution, the largest factor is 10976461. That means the final batch of recursions in your recursive solution would require a stack depth of ten million stack frames, not something most environments will contend with easily.
If you really must use a recursive solution, you can reduce the stack space to the square root of that by using the fact that you don't have to check all the way up to the number, but only up to its square root.
In addition, other than 2, every other prime number is odd, so you can further halve the search space by only checking two plus the odd numbers.
A recursive solution taking those two things into consideration would be:
long long prime_factor_r (int n, long long huge_number) {
// Debug code for level checking.
// static int i = 0;
// printf ("recursion level = %d\n", ++i);
// Only check up to square root.
if (n * n >= huge_number)
return huge_number;
// If it's a factor, reduce the number and try again.
if (huge_number % n == 0)
return prime_factor_r (n, huge_number / n);
// Select next "candidate" prime to check against, 2 -> 3,
// 2n+1 -> 2n+3 for all n >= 1.
if (n == 2)
return prime_factor_r (3, huge_number);
return prime_factor_r (n + 2, huge_number);
}
You can see I've also removed the (awkward, in my opinion) construct:
if something then
return something
else
return something else
I much prefer the less massively indented code that comes from:
if something then
return something
return something else
But that's just personal preference. In any case, that gets your recursion level down to 1662 (uncomment the debug code to verify) rather than ten million, a rather sizable reduction but still not perfect. That runs okay in my environment.
You meant n+1 instead of n++. n++ increments n after using it, so the recursive call gets the original value of n.
You are overflowing stack, because n++ post-increments the value, making a recursive call with the same values as in the current invocation.
the crash reason is stack overflow. I add a counter to your program and execute it(on ubuntu 10.04 gcc 4.4.3) the counter stop at "218287" before core dump. the better solution is using loop instead of recursion.