I took the suggestion from NetVipeC and modified your program a bit. The changes were:
- I used a #defined constant
MAXNUM
to control the number of iterations.
- I added a
result
array to store previous results.
- In the
col
function, it now ends when it finds a previous result, instead of just stopping at 1.
The Modified Program
#include <stdio.h>
#define MAXNUM 1000000
unsigned short result[MAXNUM];
long long int col(long long int n)
{
if (n < MAXNUM && result[n] != 0)
return result[n];
if(n%2==0)
return (1+col(n/2));
else
return (1+col(3*n+1));
}
int main()
{
long long int i=0, c, max, k=1;
max=1;
result[1] = 1;
for(i=2; i<MAXNUM; i++)
{
c=result[i]=col(i);
if(c>max)
{
max=c;
k=i;
}
}
printf("%lld",max);
printf("\n%lld\n",k);
return 0;
}
I also went ahead and rewrote your program to remove recursion, add in a small optimization, and allow the max to be set by a command line argument:
The Rewritten Program
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <inttypes.h>
#define DEFAULT_MAXNUM 100000000
static uint16_t *result;
uint16_t collatz(uint64_t n)
{
uint64_t originalNumber = n;
uint16_t count = 1;
while (1) {
if (n & 1) {
n = n*3+1;
} else {
n >>= 1;
if (n < originalNumber)
return count + result[n];
}
count++;
}
}
int main(int argc, char *argv[])
{
uint64_t i = 0;
uint16_t count = 0;
uint16_t bestCount = 1;
uint64_t bestNum = 1;
uint64_t maxNum = DEFAULT_MAXNUM;
if (argc > 1) {
maxNum = strtoull(argv[1], NULL, 0);
if (maxNum < 2)
maxNum = 2;
}
result = malloc(maxNum * sizeof(result[0]));
if (result == NULL) {
fprintf(stderr, "Error: Not enough memory\n");
return 1;
}
result[1] = 1;
for(i=2; i<maxNum; i++) {
count = result[i] = collatz(i);
if (count > bestCount) {
bestCount = count;
bestNum = i;
}
}
printf("Max considered: %" PRIu64 "\n", maxNum);
printf("Largest number: %" PRIu64 "\n", bestNum);
printf("Largest count : %d\n", bestCount);
return 0;
}
The Timing Results
Here are the timing results from the three programs. Note that I used 100000000 as the number of iterations (100x the original amount) to get longer run times. I also used gcc -O4
to build all programs.
Original program : 37.7s
Modified program : 2.0s
Rewritten program: 1.2s
int cache[1000] = {0};
, and save in every element of the container thecollatz chain length
when starting with that number. Using thiscache
could stop calculating a lot ofcollatz chain length
when encounter an already calculated number. \$\endgroup\$