This question already has answers here:
Project Euler Question 14 (Collatz Problem)
(8 answers)
Closed 1 year ago.
Hi I am new to C and I chose a project to get better
I wanted to make a program that would brute force every number if it is according to Collatz conjecture.
Collatz conjecture:
For those who do not know what Collatz conjecture is click here
Summary:
If a number is odd it is multiplied by 3 and increased by 1
If even it is divided by 2
This is repeated until it reaches 1
My code:
#include <stdio.h>
int main(){
int n, x, a, b;
n = 5; //number we check first (has to be bigger than 4 because 4,3,2,1 is a loop)
//n is later on a number that is currently being tested
//all numbers smaller than 2 ** 64 were brute force tested and are according to Collatz's conjecture
x = n; //x begins as n and then changes according to rules of cenjecture until it reaches 1
a = 1; //a is set to 1 until x = 1 which means that number n is according to conjecture
b = 1; //creates an infinite loop
while(b == 1){ //runs forever
if(a == 1){
if(x == 1){
a = 0; //if x reaches 1 (number n is according to conjecture) a is set to 0 and n is increased by 1 ===
} // ||
else{ // ||
if(x % 2 == 0){ // ||
x = x / 2; // ||
} // ||
else{ // ||
x = x * 3 + 1; // ||
} // ||
} // ||
} // ||
else{ // ||
printf("%d \n", n); // ||
n = n + 1; // <<<<<============================================================================
x = n; //
a = 1; //
}
}
}
Problem:
The problem is that when I run it it stops on number 113383 and has problems with it. I even let it run for more than 5 minutes but it did not do anything. I even tried to run the same number in my python program which test input number and it had it in no time.
I tried to start with n = 113384 and it worked and stopped again on 134378.
Is number 113383 anyhow different in C or is there a flaw in my code.
Please help if you can.
Thank you very much
Try declaring the variable as a "long int" this could be due to the maximum size of an int witch is –32,767 to 32,767
Related
I am working on project euler #14 :
Question:
The following iterative sequence is defined for the set of positive integers:
n → n/2 (n is even)
n → 3n + 1 (n is odd)
Using the rule above and starting with 13, we generate the following sequence:
13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.
Which starting number, under one million, produces the longest chain?
NOTE: Once the chain starts the terms are allowed to go above one million.
Problem:
When I run this code, the first for loop runs as expected. But then the variable num seems to not increment in the for loop and stays on 2 (which isn't even in the perameters of num I gave to start out with), giving the output:
2
0
1
1
repeating over and over again. Not sure why this is happening and can't find anything online.
Code:
#include <stdio.h>
int main() {
int maxcount = 0;
for (int num = 5; num < 2000000; num++) {
printf("%d\n0\n\n", num);
int count = 0;
while (num >= 1) {
count++;
if (num == 2) {
num = 1;
printf("1\n%d\n\n", count);
}
if (num > 1) {
if (num % 2 == 0) {
num = num / 2;
printf("%d\n%d\n\n", num, count);
}
else {
num = (3 * num) + 1;
printf("%d\n%d\n\n", num, count);
}
}
if (num == 1) {
break;
}
}
if (count > maxcount) {
maxcount = count;
}
}
printf("%d", maxcount);
return 0;
}
You need to introduce a new variable. You are doing:
for (int num = 5; num < 2000000; num++) {
/* collatz stuff, which modifies num, and eventually
causes it to become 1
*/
}
so when the num++ portion of the for loop runs, num becomes 2.
What you want is
for (int start = 5 ; start < 2000000 ; start++) {
int num = start;
/* collatz stuff, which modifies num */
}
since the variable start is never modified by the loop body, it will keep going up in sequence by 1, without interference.
In the while loop, you change the value of the loop variable (num).
You start with num = 5, and the inner while loop then follows Collatz's rules and gets to 1, at which point the while-loop ends.
Then the for-loop ends, and num is incremented to 2 by num++, and the next iteration of the loop begins.
In the second iteration, the while-loop immediately sees num == 2, so it sets num = 1, and the while loop ends. Then the for-loop ends, incrementing num to 2, and the cycle continues forever.
As others have said, you just need to leave the loop variable alone and use a different variable in the inner loop.
I have written a program to bubble sort an array of a length of no more than twenty integers whose contents are decided by the user. The problem I am experiencing is that when the sorted array is printed, the second integer in the array is always 0, causing the largest integer within the sorted array to not be printed. Here is my code below:
#include <stdio.h>
int main()
{
int array[20];
int n;
int c;
int d;
float swap;
printf("Please enter how many numbers you want to sort (up to 20):\n\t");
scanf("%d", &n);
if (n >= 2)
{
for (c = 0; c < n; c++)
{
printf("Please enter the next number:\n\t");
scanf("%d", &array[c]);
}
for (c = 0; c < (n - 1); c++)
{
for (d = 0; d < (n - c); d++)
{
if (array[d] > array[d + 1])
{
swap = array[d];
array[d] = array[d + 1];
array[d + 1] = swap;
}
}
}
for (c = 0; c < n; c++)
{
printf("%d\n", array[c]);
}
printf("Here are the results in ascending order:\n");
}
else
{
printf("Since you have fewer than two numbers, they are already sorted!\n");
}
return 0;
}
for (d = 0; d < (n - c); d++)
This is not right. Think about what will happen with six numbers (array elements zero through five inclusive).
The first time through the swapping loop, n will be six and c will be zero. That means that d will take the values zero through five inclusive.
Unfortunately, you are swapping indexes d and d + 1, the latter of which will be arbitrary data (index six) since you haven't filled it in.
Since you're not seeing the last digit but are seeing zero instead, it's likely(a) that the element beyond the last one you're populating is set to zero. That would cause the swap code to swap it and your last element, resulting in what you saw:
0 1 2 3 4 5 6 7 8 9 <-- indexes
<--- you entered ---> remainder -->
3 1 4 1 5 9 0 0 0 0 <-- data
\___/
\
these will swap
What you should be using is:
for (d = 0; d < n - c - 1; d++)
That makes the difference between seeing(b):
1 0 1 3 4 5
and:
1 1 3 4 5 9
(a) Likely, but by no means guaranteed. Since array is a local variable, the value it takes for uninitialised elements will be arbitrary.
If your code is sometimes working, it's because of this - you can get repeatable failure simply by ensuring the array elements are all initialised to zero:
int array[20] = {0};
Then, since it's reproducible, you can make the changes given in this answer to fix it.
(b) As an aside, the reason the 0 is not bubbling all the way down to the bottom in this case is because it's being newly introduced in to the data during the first pass. That means there's one less pass than is needed to fully sort the data.
i have a code that prints out the number of peaks and their given magnitudes. the input is in the form of a single line that contains random integers separated by white space. a peak is only defined to be so when it is directly preceded and followed by a smaller value.
examples:
0 4 18 18 26 40 40 29 25 2 0 //has one peak of magnitude 40.
20 10 20 /*has no peaks, because both 20's are either not
preceded or followed by a smaller number.*/
the code fails to behave correctly when the input data, c, begins with a declining set of numbers.
for example, the input: 9 8 7 6 5 4 returns a peak of "9", when it shouldn't return any magnitude.
another situation where it's behaving incorrectly is when we have the following input: 10 10 10 5 5 5 12 12 12 -1. its returning a magnitude of "10", while again, it shouldn't return any magnitude because it doesn't fulfill the conditions of a peak .
the following is the code:
#include <stdio.h>
int main(void)
{
int a = 0;
int b = 0;
int c = 0;
int counter = 0;
scanf("%d", &c);
printf("Number Magnitude\n");
while (c >= 0){
if ((b > a) && (b > c)) { //to check if we have a peak
counter++;
printf("%4d%11d\n", counter, b);
a = b;
b = c;
scanf("%d", &c);
}
else if ((a < b) && (b == c)) {
b = c;
scanf("%d", &c);
}
else {
a = b;
b = c;
scanf("%d", &c);
}
}
}
i prefer to keep the level of coding as minimum as possible, as i haven't done more than loops and if statements at this stage.
The issue is being caused because you initialize your boundary values to the minimum possible value. Any possible peak value will test positive when compared to that boundary value.
A small change fixes it, both boundary values should be set to a value that tests negative when compared to any possible peak value:
int a = INT_MAX;
int b = INT_MAX;
You will however to detect new lines and reset your values if you want to be able to do multiple lines of input, but I believe this is an existing problem
In that case, you should try to ask the program to mimic what you would to by hand: you must considere 3 value, so you must read 3 values before testing for a peak. And you should always control the return value from scanf to be able to process and end of file or an incorrect input.
Your code could become:
#include <stdio.h>
int main(void)
{
int a = 0;
int b = 0;
int c = 0;
int counter = 0;
int cr;
cr = scanf("%d%d%d", &a,&b,&c);
if (cr != 3) {
printf("Incorrect input\n");
return 1;
}
printf("Number Magnitude\n");
while ((cr > 0) && (c >= 0)) {
if ((b > a) && (b > c)) { //to check if we have a peak
counter++;
printf("%4d%11d\n", counter, b);
a = b;
b = c;
}
else if ((a >= b) || (b != c)) {
a = b;
b = c;
} // nothing to do if a<b and b==c
cr = scanf("%d", &c); // read once outside of the loop
}
return 0;
}
BTW, above code allows multi-line input.
int prime(unsigned long long n){
unsigned val=1, divisor=7;
if(n==2 || n==3) return 1; //n=2, n=3 (special cases).
if(n<2 || !(n%2 && n%3)) return 0; //if(n<2 || n%2==0 || n%3==0) return 0;
for(; divisor<=n/divisor; val++, divisor=6*val+1) //all primes take the form 6*k(+ or -)1, k[1, n).
if(!(n%divisor && n%(divisor-2))) return 0; //if(n%divisor==0 || n%(divisor-2)==0) return 0;
return 1;
}
The code above is something a friend wrote up for getting a prime number. It seems to be using some sort of sieving, but I'm not sure how it exactly works. The code below is my less awesome version. I would use sqrt for my loop, but I saw him doing something else (probably sieving related) and so I didn't bother.
int prime( unsigned long long n ){
unsigned i=5;
if(n < 4 && n > 0)
return 1;
if(n<=0 || !(n%2 || n%3))
return 0;
for(;i<n; i+=2)
if(!(n%i)) return 0;
return 1;
}
My question is: what exactly is he doing?
Your friend's code is making use of the fact that for N > 3, all prime numbers take the form (6×M±1) for M = 1, 2, ... (so for M = 1, the prime candidates are N = 5 and N = 7, and both those are primes). Also, all prime pairs are like 5 and 7. This only checks 2 out of every 3 odd numbers, whereas your solution checks 3 out of 3 odd numbers.
Your friend's code is using division to achieve something akin to the square root. That is, the condition divisor <= n / divisor is more or less equivalent to, but slower and safer from overflow than, divisor * divisor <= n. It might be better to use unsigned long long max = sqrt(n); outside the loop. This reduces the amount of checking considerably compared with your proposed solution which searches through many more possible values. The square root check relies on the fact that if N is composite, then for a given pair of factors F and G (such that F×G = N), one of them will be less than or equal to the square root of N and the other will be greater than or equal to the square root of N.
As Michael Burr points out, the friend's prime function identifies 25 (5×5) and 35 (5×7) as prime, and generates 177 numbers under 1000 as prime whereas, I believe, there are just 168 primes in that range. Other misidentified composites are 121 (11×11), 143 (13×11), 289 (17×17), 323 (17×19), 841 (29×29), 899 (29×31).
Test code:
#include <stdio.h>
int main(void)
{
unsigned long long c;
if (prime(2ULL))
printf("2\n");
if (prime(3ULL))
printf("3\n");
for (c = 5; c < 1000; c += 2)
if (prime(c))
printf("%llu\n", c);
return 0;
}
Fixed code.
The trouble with the original code is that it stops checking too soon because divisor is set to the larger, rather than the smaller, of the two numbers to be checked.
static int prime(unsigned long long n)
{
unsigned long long val = 1;
unsigned long long divisor = 5;
if (n == 2 || n == 3)
return 1;
if (n < 2 || n%2 == 0 || n%3 == 0)
return 0;
for ( ; divisor<=n/divisor; val++, divisor=6*val-1)
{
if (n%divisor == 0 || n%(divisor+2) == 0)
return 0;
}
return 1;
}
Note that the revision is simpler to understand because it doesn't need to explain the shorthand negated conditions in tail comments. Note also the +2 instead of -2 in the body of the loop.
He's checking for the basis 6k+1/6k-1 as all primes can be expressed in that form (and all integers can be expressed in the form of 6k+n where -1 <= n <= 4). So yes it is a form of sieving.. but not in the strict sense.
For more:
http://en.wikipedia.org/wiki/Primality_test
In case the 6k+-1 portion is confusing, note that you can perform some factorization of most forms of 6k+n and some are obviously composite and some need to be tested.
Consider numbers:
6k + 0 -> composite
6k + 1 -> not obviously composite
6k + 2 -> 2(3k+1) --> composite
6k + 3 -> 3(2k+1) --> composite
6k + 4 -> 2(3k+2) --> composite
6k + 5 -> not obviously composite
I've not seen this little trick before, so it's neat, but of limited utility since a sieve of Eratosthenese is more efficient for finding many small prime numbers, and larger prime numbers benefit from faster, more intelligent, tests.
#include<stdio.h>
int main()
{
int i,j;
printf("enter the value :");
scanf("%d",&i);
for (j=2;j<i;j++)
{
if (i%2==0 || i%j==0)
{
printf("%d is not a prime number",i);
return 0;
}
else
{
if (j==i-1)
{
printf("%d is a prime number",i);
}
else
{
continue;
}
}
}
}
#include<stdio.h>
int main()
{
int n, i = 3, count, c;
printf("Enter the number of prime numbers required\n");
scanf("%d",&n);
if ( n >= 1 )
{
printf("First %d prime numbers are :\n",n);
printf("2\n");
}
for ( count = 2 ; count <= n ; )
{
for ( c = 2 ; c <= i - 1 ; c++ )
{
if ( i%c == 0 )
break;
}
if ( c == i )
{
printf("%d\n",i);
count++;
}
i++;
}
return 0;
}
I am trying to create a code that will take the number 2 to 100, and test each for the collatz conjecture.
The goal is that for each number, if it is even, divide it by two, and if it is odd, then multiply it by 3 and add 1.
It prints each step, and each number should stop testing if it reaches 1. Why doesn't it work?
#include <stdio.h>
int main()
{
int number, position;
position == 2;
number == 2;
while (position <= 100)
{
while (number != 1)
{
if (number % 2 == 0)
{
number = number/2;
printf("%d\n", number);
}
else if (number % 2 != 0)
{
number = number*3;
number = number + 1;
printf("%d\n", number);
}
}
position = position + 1;
number = position;
}
}
It prints recurring Os
Fix the == vs =:
position = 2;
number = 2;
Also, the else if is unnecessary. The opposite of even is odd, so a plain else will suffice :-)
You have set position and number with a double equal == (Comparision Operator) instead of using single equal = (Assignment Operator) so that the algorithm is comparing them instead of assigning a value.
The assignment should look like this:
position = 2;
number = 2;
Also you can do it when you first define them:
int number=2, position=2;
Apart from that the code is correct, the only thing to highlight is that you don´t need to use else if because it can just be even or odd so a single else would be enough.
Hope I´ve helped :-)