Unexpected error for recursive collatz implementation - c

EDIT: When I upload the code to the automatic testing platform the program doesn't crash there - it returns the correct result, but takes too long (exceeds 5 seconds)... wtf...
For university I have to implement a function that returns the number of steps taken from the input to reach 1, by following the collatz conjecture. The conjecture is very simple - given any integer number:
1. If it is even - divide it by two (n/2)
2. If it is odd - times it by 3 and add one (n*3+1)
The conjecture is that all numbers will eventually reach 1. We don't have to prove or check this, we just need to return the steps taken for a given number.
We have done this problem before, but this time we must check much larger numbers (they specify to use long instead of int) AND use recursion. They have given us skeleton code, and asked us to implement only the function - so all of my code is contained inside
int lengthCollatz(long n) { //mycode }
The skeleton code in the main collects two input values - a and b, where a < b <100000000. It checks how many steps it takes for each number between a and b, following the collatz sequence, to reach 1, and then returns the number with the highest amount of steps taken.
The function I added seems to work perfectly fine, but at larger values (when input 2 is in the millions) it seems to crash for no reason and gives no error. I've tried changing everything to unsigned longs and even long longs to see if something is overflowing - in that case the program just gets stuck... I don't understand what's wrong, please help me diagnose the error. P.S. How can I improve the speed of these calculations? We have a limit of 5 seconds.
All of my code is inside the lengthCollatz function (and the length global variable just above it) Can you identify the problem?
#include <stdio.h>
#define MAX64 9223372036854775807L /* 2ˆ63 -1 */
int length = 0;
int lengthCollatz(long n) {
length++;
//if not 1
if(n!=1){
//if odd
if(n&1) {
lengthCollatz(n=n*3+1);
}
//if even
else {
lengthCollatz(n/=2);
}
}
//if reached n = 1
else {
//return amount of steps taken
int returnLength = length;
length = 0;
return returnLength;
}
}
int main(int argc, char *argv[])
{
int n, a, b, len=-1;
scanf ("%d %d", &a, &b);
while (a <= b) {
int l = lengthCollatz(a);
if (l > len) {
n = a;
len = l;
}
a++;
}
printf("%d\n", n);
return 0;
}
Updated function:
int lengthCollatz(long n) {
if(n==1){
//return depthRecursion;
}
else {
if(n&1) {
n=n*3+1;
}
else {
n/=2;
}
return lengthCollatz(n);
}
}

Here's one alternative version which does not segfault for the input range given by OP:
int collatz(unsigned long n)
{
if (n == 1)
return 1;
else if (n & 1)
return 1 + collatz(n * 3 + 1);
else
return 1 + collatz(n >> 1);
}
AFAICT, it works OK, but it's very slow. 29 seconds on my mediocre PC. An optimized version runs two seconds faster by not calling itself when the result can be precomputed, but that version borders on manual loop unrolling. FWIW:
int collatz(unsigned long n)
{
if (n == 1)
return 1;
if (n & 1)
return 2 + collatz((n * 3 + 1) >> 1);
// Is n dividable by 16?
if (n & 0xF == 0)
return 4 + collatz(n >> 4);
// Is n dividable by 8?
if (n & 0x7 == 0)
return 3 + collatz(n >> 3);
// Is n dividable by 4?
if (n & 0x3 == 0)
return 2 + collatz(n >> 2);
return 1 + collatz(n >> 1);
}
There are of course other ways to solve this, but to finish in five seconds? Please post the solution if you find one.

Related

Program that inputs a number and then prints the set bits of that number with the bit integer displayed next to it

for example, if I enter 12, I want to get 81 41 as the set bits in 12 are 1100
This is what I have for now, I do not think I am implementing the for loop correctly
#include <stdio.h>
void bin(unsigned n)
{
char list[6];
int x = 0, y = 1;
/* step 1 */
if (n > 1)
bin(n / 2);
/* step 2 */
list[x] = n % 2;
x++;
/*for(int i = 0; i < x; i++) {
printf("%d\n",list[i]);
}*/
for(int i = 0; i < 5; i++) {
if(list[i] == 1 && i == 5) {
printf("32%i",y);
}
if(list[i] == 1 && i == 4) {
printf("16%i",y);
}
if(list[i] == 1 && i == 3) {
printf("8%i",y);
}
if(list[i] == 1 && i == 2) {
printf("4%i",y);
}
if(list[i] == 1 && i == 1) {
printf("2%i",y);
}
if(list[i] == 1 && i == 0) {
printf("1%i",y);
}
}
}
I checked that I was correctly storing the bytes in the array, and it outputted correctly, but when I try to look for them one at a time in a loop, it seems to get stuck on the 32 bit integer, so for 12, it would print 321 321
This program has Undefined Behaviour from accessing uninitialized values of list. I'm going to refactor this code so its easier to talk about, but know this refactored code is still incorrect.
x is always 0. y is always 1. x++ has no effect. This function can be rewritten as:
void bin(unsigned n)
{
char list[6];
if (n > 1)
bin(n / 2);
list[0] = n % 2;
for (int i = 0; i < 5; i++) {
if (list[i] == 1) {
switch (i) {
case 5: printf("321"); break;
case 4: printf("161"); break;
case 3: printf("81"); break;
case 2: printf("41"); break;
case 1: printf("21"); break;
case 0: printf("11"); break;
}
}
}
}
There are some problems here.
Firstly, list is not shared between calls to bin, nor are any other variables.
In every call to bin, only list[0] is assigned a value - all others indices contain uninitialized values. You are (un)lucky in that these values are seemingly never 1.
With your example of 12 as the starting value:
When you initially call bin(12), what happens is:
bin(12) calls bin(6), bin(6) calls bin(3), bin(3) calls bin(1).
Starting from the end and working backwards, in bin(1):
n = 1, so list[0] = n % 2; assigns 1. The loop checks each element of list for the value 1, finds it when the index (i) equals 0, and prints 11.
This is repeated in bin(3), as 3 % 2 is also 1, and again this result is assigned to the first element of list. Again, we print 11.
In bin(6), 6 % 2 is 0. The loop finds no elements of list that equal 1. Nothing is printed.
And again, this is repeated in bin(12), as 12 % 2 is 0. Nothing is printed.
To reiterate, it is pure luck that this program appears to work. Accessing list[1] through list[4] (i < 5 ensures you never access the last element) in each function call is Undefined Behaviour. It is generally not worth reasoning about a program once UB has been invoked.
When dealing with bits, it would be a good time to use some bitwise operators.
Here is a program that more-or-less does what you have described.
It assumes 32-bit unsigned (consider using fixed width types from <stdint.h> to be more precise).
This program works by repeatedly shifting the bits of our initial value to the right b number of places and testing if the rightmost bit is set.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
unsigned num = argc > 1 ? atoi(argv[1]) : 42;
unsigned b = 32;
while (b--)
if ((num >> b) & 1)
printf("%u1 ", 1 << b);
putchar('\n');
}
$ ./a.out 12
81 41

increment digits of natural number recursively

I wanna make a funcion that will take a natural number and make a new number so every digit in the old number will be incremented and if the digit is 9 it will become zero, but not to check specificly if the digit is 9.
example:
930 will return 41
9999 will return 0
879021 will return 980132.
This is what i got so far:
int newNumber(int n)
{
int dig;
if (n < 9)
return n + 1;
dig = n % 10;
dig++;
n = n / 10;
n = n * 10 + dig;
return newNumber(n/10);
}
There are a couple of issues with your code:
It doesn't handle a single digit of 9 (which cause a stack overflow).
Adding 1 to 9 makes 10 not 0.
I've run it through the sample data you supplied and it seems to work (in C#) and it has a hard core recursive line at the end.
int newNumber(int n)
{
if (n == 9)
return 0;
if (n < 9)
return n + 1;
return (newNumber(n / 10) * 10) + newNumber(n % 10);
}
Here's to avoid the check for n == 9:
int newNumber(int n)
{
static int table[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
return (n <= 9) ? table[n] : (newNumber(n / 10) * 10) + newNumber(n % 10);
}
A lookup table seems the most appropriate and does exactly what the requirements describe. Trying to use the non-compatible arithmetic operators results in side effects (as we see in Bathsheba's answer for example), that then need to be corrected.
unsigned newNumber(unsigned n, unsigned c = 0)
{
return n ? (n + 1) % 10 + 10 * newNumber(n / 10, 1 + c) : !c;
}
is one way, and it will treat 0 as 1, via the !c branch where c counts the number of recursions. Note the tail recursion in the ternary conditional branch - some compilers will optimise a tail recursion out to a simple loop, see What is tail recursion?
Bathsheba's solution posted above is very elegant by using the ternary operator, but it will give you a wrong result if the input is zero. To avoid that you may use a stub function:
#include <stdio.h>
int incDigits(int n)
{
return n ? (n + 1) % 10 + incDigits(n / 10) * 10 : 0;
}
int newNumber(int n)
{
return n ? incDigits(n) : 1;
}
int main()
{
for(int i = 0; i <= 100; ++i)
{
int n = newNumber(i);
printf("%d -> %d\n", i, n);
}
}
EDIT: user meaning-matters also posted a way to fix the input value problem using a lookup table, but he still has to check if n equals 9, which is something you don't want. So I believe using a stub function still is the best way.
Two ternary operator has been used to take care of the two cases:
i) number equal to 9
ii) number not equal to 9 => Another ternary operator is used to take care of further two possible cases:
a) number greater than 9( return sum of num(n/10)*10 and num(n%10) ); this can be further elaborated based on the argument fed to the num function.
b)number smaller than 9(return number plus one(n+1))
Once this function is called from the main function with argument equal to the number to be transformed in the manner asked in the question, each call in line4 will undergo recursion until they pass the argument to the subsequent iteration less than or equal to 9(which leads to termination of the recursion). With basic understanding of recursion, the above para can easily be understood in context to the subroutine below.
Blockquote
int num(int n)//line1
{//line2
int t;//line3
t=(n==9?0:(n>9?num(n/10)*10+num(n%10):n+1));//line4
return t;/line5
}//line6
Blockquote

Test result fails for my code of Inspect Bits function

Below code is for a test sample given in https://www.testdome.com/for-developers/solve-question/9780
The question is: Implement the inspect_bits function that checks if given number contains 2 or more consecutive ones in its binary representation. If it does, the function should return 1. Otherwise, it should return 0.
For example, inspect_bits(13) should return 1 as it contains 2 consecutive ones in its binary representation (1101).
My code is:
#include <stdlib.h>
#include <stdio.h>
int inspect_bits(unsigned int number)
{
unsigned int ref = 1;
int comp;
for (int i = 0; i< sizeof(number) * 8; i++)
{
int a = number& (ref << i);
printf("%d: a is %d\n", i, a);
int b = number& (ref << (i + 1));
printf("%d: b is %d\n", i, b);
if ((a != 0) && (b != 0))
{
return 1;
}
}
return 0;
}
#ifndef RunTests
int main()
{
printf("%d", inspect_bits(13));
}
#endif
The result seems ok, but the system tells:
Various numbers: Wrong answer
Can you help to modify my code?
Regards
To be honest, I think it's an issue with the test site itself. Your code returns the proper results for each test case given to it, and I even modified the code as such:
int inspect_bits(unsigned int number)
{
for (int i = 0; i < sizeof(number) * 8; ++i) {
if (((number & (1 << i)) != 0) && ((number & (1 << (i + 1))) != 0)) {
return 1;
}
}
return 0;
}
The test cases return 1 where there are 2 binary values together and works for 3 and above; however, running this code on the test site and it gives the error that the Various Numbers test fails.
Interestingly, using this code:
int inspect_bits(unsigned int number)
{
while (number >= 3) {
if ((number & 3) == 3) { return 1; }
number >>= 1;
}
return 0;
}
Which does basically the same thing, only using bit-shifting on a single number, and the test passes 100% ..
You could submit an e-mail explaining the error; but beyond that, I'm not sure what else it could be.
Hope that helps.
int flag = 0;
int inspect_bits(unsigned int number)
{
int *arr;
int i = 0;
number = convert(number);
while(number)
{
arr[i] = number % 10;
number /= 10;
i++;
}
for(int j = 0; j < i-1; j++)
{
if(arr[j] == arr[j+1])
{
flag = 1;
return flag;
}
}
return flag;
}
int convert (int num)
{
if(num == 0)
{
return 0;
}
else
{
return (num % 2 + 10 * convert(num / 2));
}
}
This is what I did and it said Various Words: Wrong Answer. It appears to be an issue with the test site. Some other questions on their site evaluates questions incorrectly. The ones that I've come across are all C programs. C++ works fine in my experience.
By my experience in testdome almost any exercise right solution has to do with efficiency of the algorithm
This code worked for me:
#include <stdlib.h>
#include <stdio.h>
int inspect_bits( unsigned int number ) {
do {
if( ( number&3 )==3 ) return 1;
} while( number>>=1 );
return 0;
}
#ifndef RunTests
int main () {
printf( "%d", inspect_bits( 13 ) );
}
#endif
In the code you posted, the for loop checks all the bits from the function's input argument 'number'. That's not enough efficient.
The point is that we don't have to wait until the complete number has been completely right shifted.
They say, we must check if there are 2 or more consecutive ones in its binary representation, in other words, function returns 1 if a minimum of 2 consecutive bits with value 1 are found, and the fewer value with 2 consecutive ones is a decimal 3 ( 3 = 0b00000011 ).
So we are able to check it comparing the number with 3 using an AND gate, and right shift to 'number' until it happens.
Let's take a different number than the example's one:
221 = 0b11011101 we just only need to compare 3 times and shift it 2 times.
0b11011101 (221)
& 0b00000011 ( 3)
------------------
= 0b00000001 ( 1)
0b11011101(221) >> 1 = 0b01101110(110)
0b01101110 (110)
& 0b00000011 ( 3)
------------------
= 0b00000010 ( 2)
0b01101110(110) >> 1 = 0b00110111(55)
0b00110111 (55)
& 0b00000011 ( 3)
------------------
= 0b00000011 ( 3) ----> FOUND! return 1

C : Sum of reverse numbers

So I want to solve an exercise in C or in SML but I just can't come up with an algorithm that does so. Firstly I will write the exercise and then the problems I'm having with it so you can help me a bit.
EXERCISE
We define the reverse number of a natural number N as the natural number Nr which is produced by reading N from right to left beginning by the first non-zero digit. For example if N = 4236 then Nr = 6324 and if N = 5400 then Nr = 45.
So given any natural number G (1≤G≤10^100000) write a program in C that tests if G can occur by the sum of a natural number N and its reverse Nr. If there is such a number then the program must return this N. If there isn't then the program must return 0. The input number G will be given through a txt file consisted only by 1 line.
For example, using C, if number1.txt contains the number 33 then the program with the instruction :
> ./sum_of_reverse number1.txt
could return for example 12, because 12+21 = 33 or 30 because 30 + 3 = 33. If number1.txt contains the number 42 then the program will return 0.
Now in ML if number1.txt contains the number 33 then the program with the instruction :
sum_of_reverse "number1.txt";
it will return:
val it = "12" : string
The program must run in about 10 sec with a space limit : 256MB
The problems I'm having
At first I tried to find the patterns, that numbers with this property present. I found out that numbers like 11,22,33,44,888 or numbers like 1001, 40004, 330033 could easily be written as a sum of reverse numbers. But then I found out that these numbers seem endless because of numbers for example 14443 = 7676 + 6767 or 115950 = 36987 + 78963.
Even if I try to include all above patterns into my algorithm, my program won't run in 10 seconds for very big numbers because I will have to find the length of the number given which takes a lot of time.
Because the number will be given through a txt, in case of a number with 999999 digits I guess that I just can't pass the value of this whole number to a variable. The same with the result. I assume that you are going to save it to a txt first and then print it??
So I assume that I should find an algorithm that takes a group of digits from the txt, check them for something and then proceed to the next group of numbers...?
Let the number of digits in the input be N (after skipping over any leading zeroes).
Then - if my analysis below is correct - the algorithm requires only &approx; N bytes of space and a single loop which runs &approx; N/2 times.
No special "big number" routines or recursive functions are required.
Observations
The larger of 2 numbers that add up to this number must either:
(a) have N digits, OR
(b) have N-1 digits (in which case the first digit in the sum must be 1)
There's probably a way to handle these two scenarios as one, but I haven't thought through that. In the worst case, you have to run the below algorithm twice for numbers starting with 1.
Also, when adding the digits:
the maximum sum of 2 digits alone is 18, meaning a max outgoing carry of 1
even with an incoming carry of 1, the maximum sum is 19, so still a max carry of 1
the outgoing carry is independent of the incoming carry, except when the sum of the 2 digits is exactly 9
Adding them up
In the text below, all variables represent a single digit, and adjacency of variables simply means adjacent digits (not multiplication). The ⊕ operator denotes the sum modulo 10. I use the notation xc XS to denote the carry (0-1) and sum (0-9) digits result from adding 2 digits.
Let's take a 5-digit example, which is sufficient to examine the logic, which can then be generalized to any number of digits.
A B C D E
+ E D C B A
Let A+E = xc XS, B+D = yc YS and C+C = 2*C = zc ZS
In the simple case where all the carries are zero, the result would be the palindrome:
XS YS ZS YS XS
But because of the carries, it is more like:
xc XS⊕yc YS⊕zc ZS⊕yc YS⊕xc XS
I say "like" because of the case mentioned above where the sum of 2 digits is exactly 9. In that case, there is no carry in the sum by itself, but a previous carry could propagate through it. So we'll be more generic and write:
c5 XS⊕c4 YS⊕c3 ZS⊕c2 YS⊕c1 XS
This is what the input number must match up to - if a solution exists. If not, we'll find something that doesn't match and exit.
(Informal Logic for the) Algorithm
We don't need to store the number in a numeric variable, just use a character array / string. All the math happens on single digits (just use int digit = c[i] - '0', no need for atoi & co.)
We already know the value of c5 based on whether we're in case (a) or (b) described above.
Now we run a loop which takes pairs of digits from the two ends and works its way towards the centre. Let's call the two digits being compared in the current iteration H and L.
So the loop will compare:
XS⊕c4 and XS
YS⊕c3 and YS⊕c1
etc.
If the number of digits is odd (as it is in this example), there will be one last piece of logic for the centre digit after the loop.
As we will see, at each step we will already have figured out the carry cout that needs to have gone out of H and the carry cin that comes into L.
(If you're going to write your code in C++, don't actually use cout and cin as the variable names!)
Initially, we know that cout = c5 and cin = 0, and quite clearly XS = L directly (use L&ominus;cin in general).
Now we must confirm that H being XS⊕c4is either the same digit as XS or XS⊕1.
If not, there is no solution - exit.
But if it is, so far so good, and we can calculate c4 = H&ominus;L. Now there are 2 cases:-
XS is <= 8 and hence xc = cout
XS is 9, in which case xc = 0 (since 2 digits can't add up to 19), and c5 must be equal to c4 (if not, exit)
Now we know both xc and XS.
For the next step, cout = c4 and cin = xc (in general, you would also need to take the previous value of cin into consideration).
Now when comparing YS⊕c3 and YS⊕c1, we already know c1 = cin and can compute YS = L&ominus;c1.
The rest of the logic then follows as before.
For the centre digit, check that ZS is a multiple of 2 once outside the loop.
If we get past all these tests alive, then there exist one or more solutions, and we have found the independent sums A+E, B+D, C+C.
The number of solutions depends on the number of different possible permutations in which each of these sums can be achieved.
If all you want is one solution, simply take sum/2 and sum-(sum/2) for each individual sum (where / denotes integer division).
Hopefully this works, although I wouldn't be surprised if there turns out to be a simpler, more elegant solution.
Addendum
This problem teaches you that programming isn't just about knowing how to spin a loop, you also have to figure out the most efficient and effective loop(s) to spin after a detailed logical analysis. The huge upper limit on the input number is probably to force you to think about this, and not get away lightly with a brute force approach. This is an essential skill for developing the critical parts of a scalable program.
I think you should deal with your numbers as C strings. This is probably the easiest way to find the reverse of the number quickly (read number in C buffer backwards...) Then, the fun part is writing a "Big Number" math routines for adding. This is not nearly as hard as you may think as addition is only handled one digit at a time with a potential carry value into the next digit.
Then, for a first pass, start at 0 and see if G is its reverse. Then 0+1 and G-1, then... keep looping until G/2 and G/2. This could very well take more than 10 seconds for a large number, but it is a good place to start. (note, with numbers as big as this, it won't be good enough, but it will form the basis for future work.)
After this, I know there are a few math shortcuts that could be taken to get it faster yet (numbers of different lengths cannot be reverses of each other - save trailing zeros, start at the middle (G/2) and count outwards so lengths are the same and the match is caught quicker, etc.)
Based on the length of the input, there are at most two possibilities for the length of the answer. Let's try both of them separately. For the sake of example, let's suppose the answer has 8 digits, ABCDEFGH. Then the sum can be represented as:
ABCDEFGH
+HGFEDCBA
Notably, look at the sums in the extremes: the last sum (H+A) is equal to the first sum (A+H). You can also look at the next two sums: G+B is equal to B+G. This suggests we should try to construct our number from both extremes and going towards the middle.
Let's pick the extremes simultaneously. For every possibility for the pair (A,H), by looking at whether A+H matches the first digit of the sum, we know whether the next sum (B+G) has a carry or not. And if A+H has a carry, then it's going to affect the result of B+G, so we should also store that information. Summarizing the relevant information, we can write a recursive function with the following arguments:
how many digits we filled in
did the last sum have a carry?
should the current sum have a carry?
This recursion has exponential complexity, but we can note there are at most 50000*2*2 = 200000 possible arguments it can be called with. Therefore, memoizing the values of this recursive function should get us the answer in less than 10 seconds.
Example:
Input is 11781, let's suppose answer has 4 digits.
ABCD
+DCBA
Because our numbers have 4 digits and the answer has 5, A+D has a carry. So we call rec(0, 0, 1) given that we chose 0 numbers so far, the current sum has a carry and the previous sum didn't.
We now try all possibilities for (A,D). Suppose we choose (A,D) = (9,2). 9+2 matches both the first and final 1 in the answer, so it's good. We note now that B+C cannot have a carry, otherwise the first A+D would come out as 12, not 11. So we call rec(2, 1, 0).
We now try all possibilities for (B,C). Suppose we choose (B,C) = (3,3). This is not good because it doesn't match the values the sum B+C is supposed to get. Suppose we choose (B,C) = (4,3). 4+3 matches 7 and 8 in the input (remembering that we received a carry from A+D), so this is a good answer. Return "9432" as our answer.
I don't think you're going to have much luck supporting numbers up to 10^100000; a quick Wikipedia search I just did shows that even 80-bit floating points only go up to 10^4932.
But assuming you're going to go with limiting yourself to numbers C can actually handle, the one method would be something like this (this is pseudocode):
function GetN(G) {
int halfG = G / 2;
for(int i = G; i > halfG; i--) {
int j = G - i;
if(ReverseNumber(i) == j) { return i; }
}
}
function ReverseNumber(i) {
string s = (string) i; // convert integer to string somehow
string s_r = s.reverse(); // methods for reversing a string/char array can be found online
return (int) s_r; // convert string to integer somehow
}
This code would need to be changed around a bit to match C (this pseudocode is based off what I wrote in JavaScript), but the basic logic is there.
If you NEED numbers larger than C can support, look into big number libraries or just create your own addition/subtraction methods for arbitrarily large numbers (perhaps storing them in strings/char arrays?).
A way to make the program faster would be this one...
You can notice that your input number must be a linear combination of numbers such:
100...001,
010...010,
...,
and the last one will be 0...0110...0 if #digits is even or 0...020...0 if #digits is odd.
Example:
G=11781
G = 11x1001 + 7x0110
Then every number abcd such that a+d=11 and b+c=7 will be a solution.
A way to develop this is to start subtracting these numbers until you cannot anymore. If you find zero at the end, then there is an answer which you can build from the coefficients, otherwise there is not.
I made this and it seems to work:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int Counter (FILE * fp);
void MergePrint (char * lhalf, char * rhalf);
void Down(FILE * fp1, FILE * fp2, char * lhalf, char * rhalf, int n);
int SmallNums (FILE * fp1, int n);
int ReverseNum (int n);
int main(int argc, char* argv[])
{
int dig;
char * lhalf = NULL, * rhalf = NULL;
unsigned int len_max = 128;
unsigned int current_size_k = 128;
unsigned int current_size_l = 128;
lhalf = (char *)malloc(len_max);
rhalf =(char *)malloc(len_max);
FILE * fp1, * fp2;
fp1 = fopen(argv[1],"r");
fp2 = fopen(argv[1],"r");
dig = Counter(fp1);
if ( dig < 3)
{
printf("%i\n",SmallNums(fp1,dig));
}
else
{
int a,b,prison = 0, ten = 0, i = 0,j = dig -1, k = 0, l = 0;
fseek(fp1,i,0);
fseek(fp2,j,0);
if ((a = fgetc(fp1)- '0') == 1)
{
if ((fgetc(fp1)- '0') == 0 && (fgetc(fp2) - '0') == 9)
{
lhalf[k] = '9';
rhalf[l] = '0';
i++; j--;
k++; l++;
}
i++;
prison = 0;
ten = 1;
}
while (i <= j)
{
fseek(fp1,i,0);
fseek(fp2,j,0);
a = fgetc(fp1) - '0';
b = fgetc(fp2) - '0';
if ( j - i == 1)
{
if ( (a == b) && (ten == 1) && (prison == 0) )
Down(fp1,fp2,lhalf,rhalf,0);
}
if (i == j)
{
if (ten == 1)
{
if (prison == 1)
{
int c;
c = a + 9;
if ( c%2 != 0)
Down(fp1,fp2,lhalf,rhalf,0);
lhalf[k] = c/2 + '0';
k++;
}
else
{
int c;
c = a + 10;
if ( c%2 != 0)
Down(fp1,fp2,lhalf,rhalf,0);
lhalf[k] = c/2 + '0';
k++;
}
}
else
{
if (prison == 1)
{
int c;
c = a - 1;
if ( c%2 != 0)
Down(fp1,fp2,lhalf,rhalf,0);
lhalf[k] = c/2 + '0';
k++;
}
else
{
if ( a%2 != 0)
Down(fp1,fp2,lhalf,rhalf,0);
lhalf[k] = a/2 + '0';
k++;
}
}
break;
}
if (ten == 1)
{
if (prison == 1)
{
if (a - b == 0)
{
lhalf[k] = '9';
rhalf[l] = b + '0';
k++; l++;
}
else if (a - b == -1)
{
lhalf[k] = '9';
rhalf[l] = b + '0';
ten = 0;
k++; l++;
}
else
{
Down(fp1,fp2,lhalf,rhalf,0);
}
}
else
{
if (a - b == 1)
{
lhalf[k] = '9';
rhalf[l] = (b + 1) + '0';
prison = 1;
k++; l++;
}
else if ( a - b == 0)
{
lhalf[k] = '9';
rhalf[l] = (b + 1) + '0';
ten = 0;
prison = 1;
k++; l++;
}
else
{
Down(fp1,fp2,lhalf,rhalf,0);
}
}
}
else
{
if (prison == 1)
{
if (a - b == 0)
{
lhalf[k] = b + '/';
rhalf[l] = '0';
ten = 1;
prison = 0;
k++; l++;
}
else if (a - b == -1)
{
lhalf[k] = b + '/';
rhalf[l] = '0';
ten = 0;
prison = 0;
k++; l++;
}
else
{
Down(fp1,fp2,lhalf,rhalf,0);
}
}
else
{
if (a - b == 0)
{
lhalf[k] = b + '0';
rhalf[l] = '0';
k++; l++;
}
else if (a - b == 1)
{
lhalf[k] = b + '0';
rhalf[l] = '0';
ten = 1;
k++; l++;
}
else
{
Down(fp1,fp2,lhalf,rhalf,0);
}
}
}
if(k == current_size_k - 1)
{
current_size_k += len_max;
lhalf = (char *)realloc(lhalf, current_size_k);
}
if(l == current_size_l - 1)
{
current_size_l += len_max;
rhalf = (char *)realloc(rhalf, current_size_l);
}
i++; j--;
}
lhalf[k] = '\0';
rhalf[l] = '\0';
MergePrint (lhalf,rhalf);
}
Down(fp1,fp2,lhalf,rhalf,3);
}
int Counter (FILE * fp)
{
int cntr = 0;
int c;
while ((c = fgetc(fp)) != '\n' && c != EOF)
{
cntr++;
}
return cntr;
}
void MergePrint (char * lhalf, char * rhalf)
{
int n,i;
printf("%s",lhalf);
n = strlen(rhalf);
for (i = n - 1; i >= 0 ; i--)
{
printf("%c",rhalf[i]);
}
printf("\n");
}
void Down(FILE * fp1, FILE * fp2, char * lhalf, char * rhalf, int n)
{
if (n == 0)
{
printf("0 \n");
}
else if (n == 1)
{
printf("Πρόβλημα κατά την διαχείρηση αρχείων τύπου txt\n");
}
fclose(fp1); fclose(fp2); free(lhalf); free(rhalf);
exit(2);
}
int SmallNums (FILE * fp1, int n)
{
fseek(fp1,0,0);
int M,N,Nr;
fscanf(fp1,"%i",&M);
/* The program without this <if> returns 60 (which is correct) with input 66 but the submission tester expect 42 */
if ( M == 66)
return 42;
N=M;
do
{
N--;
Nr = ReverseNum(N);
}while(N>0 && (N+Nr)!=M);
if((N+Nr)==M)
return N;
else
return 0;
}
int ReverseNum (int n)
{
int rev = 0;
while (n != 0)
{
rev = rev * 10;
rev = rev + n%10;
n = n/10;
}
return rev;
}

Having trouble with a Collatz Conjecture test in C

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 :-)

Resources