Star printing in C the hard way - c

I've started exercising some C and found this nice exercise where I have to print a triangle via input.
for the input 6 it will print
*
**
***
****
*****
******
*****
****
***
**
*
Now, looking at it I thought, well, that's not such a hard task. So I decided to try and write it using recursion, no loops and only 2 variables.
the function should looks like this:
void PrintTriangle(int iMainNumber, int iCurrNumber)
{
//Logic goes here
}
A few hours later I realized this is a lot harder than I thought, since I need to pass enough information for the function to be able to "remember" how much triangles it should print.
So now I decided to ask you if that is even possible.
(remember, no loops, no other functions, only recursion).
EDIT:
This isn't homework, this is out of sheer curiosity. However I probably can't validate for you.
I've managed to get halfway through with this
void PrintTriangle(int iMainNumber, int iCurrNumber)
{
if (iMainNumber == 0)
{
printf("\r\n");
}
else if (iMainNumber == iCurrNumber)
{
printf("\r\n");
PrintTriangle(iMainNumber - 1, 0);
}
else
{
printf("%s", MYCHAR);
PrintTriangle(iMainNumber, iCurrNumber + 1);
}
}
I got stuck trying to create the opposite function, I believe that if I could do it, I would be able to use the fact that iMainNumber and iCurrNumber are positive or negative to navigate through the functions flow.
In other words, when the parameters are negative I would print a descending star in the length of the input minus one, and when the parameters are positive I would print the ascending star in the length of the input.
I've thought about Using a flag, but not instead of 2 integers.
Maybe if I'd add another flag and have 2 integers and a flag then I could solve it, but as I said, I tried to limit myself to 2 integers.
What I'm starting to think is that there is no way to pass the information required to print an ascending star in this method without using more than 2 integers and recursion.
But I'm still not so sure about that, hence the question.

I came up with:
void PrintTriangle(int size, int indent)
{
switch(size) {
case 0:
if (indent > 1) PrintTriangle(size, indent-1);
putchar('*');
break;
case 1:
PrintTriangle(size-1, indent+1);
putchar('\n');
break;
default:
PrintTriangle(1, indent);
PrintTriangle(size-1, indent+1);
PrintTriangle(1, indent);
break; }
}
int main()
{
PrintTriangle(6, 0);
return 0;
}
as a quick first attempt. Seems to do the job.
size is the size of the triangle to print, and indent is the number of extra stars to print before each row of the triangle. size==0 means just print indent stars and no newline (used to print the indent before the triangle)
If you want something a bit more compact, you could rewrite this as:
void PrintTriangle(int size, int indent)
{
if (size <= 0) {
if (indent > 1) PrintTriangle(size, indent-1);
putchar('*');
} else {
if (size > 1) PrintTriangle(1, indent);
PrintTriangle(size-1, indent+1);
if (size > 1) PrintTriangle(1, indent);
else putchar('\n'); }
}

Anything done with loops can be done with recursion with the same number of variables. You just have to tease out what is the state, and pass that updated state in a recursive call, instead of looping.
So let's do it iterativey, first. The input is size, the size of the triangle. Let's have two state variables, lineNumber from 1 to size*2-1 and columnNumber from 1 to size. Note that:
columnsForLine = lineNumber <= size ? lineNumber : size*2 - lineNumber
The iterative version would be like this:
int lineNumber = 1;
int columnNumber = 1;
int size = 6;
while (lineNumber <= size*2-1) {
printf("*");
int columnsForLine = lineNumber <= size ? lineNumber : size*2 - lineNumber;
if (columnNumber == columnsForLine) {
printf("\n");
columnNumber = 1;
lineNumber += 1;
}
else {
columnNumber += 1;
}
}
That does indeed work. Now how to do it recursively? Just tease out where state is being updated and do that as a recursive call:
void recstars(int size, int lineNumber, int columnNumber) {
if (!(lineNumber <= size*2 - 1)) {
return;
}
printf("*");
int columnsForLine = lineNumber <= size ? lineNumber : size*2 - lineNumber;
if (columnNumber == columnsForLine) {
printf("\n");
recstars(size, lineNumber + 1, 1);
}
else {
recstars(size, lineNumber, columnNumber + 1);
}
}
recstars(6, 1, 1);
And voila. Works for any size, e.g. 13.
Note that the code is basically the same, it's just a matter of doing the control flow differently. Also note that this is tail-recursive, meaning a smart compiler would be able to execute the recursive calls without growing the stack for each call.
Hmm if you only want to use 2 variables though, including the input, will be a bit trickier... you can always cheat and stuff all 3 integers into one integer, then unpack it & re-pack it each time. e.g.
void recstars(int state) {
int size = state / 10000;
int lineNumber = (state - size*10000) / 100;
int columnNumber = state - size*10000 - lineNumber*100;
if (!(lineNumber <= size*2 - 1)) {
return;
}
printf("*");
int columnsForLine = lineNumber <= size ? lineNumber : size*2 - lineNumber;
if (columnNumber == columnsForLine) {
printf("\n");
recstars(size*10000 + (lineNumber+1)*100 + 1);
}
else {
recstars(size*10000 + lineNumber*100 + (columnNumber+1));
}
}
recstars(6*10000 + 1*100 + 1);
Seems to work. Is that legit, you think?
Otherwise, the tricky part isn't the recursion, it's just getting the job done with only 2 ints for state. Can you do it iteratively with only 2 integers?

Using 2 parameters as OP suggested
void PrintTriangle(int iMainNumber, int iCurrNumber) {
if (iMainNumber < 0) { // Row (use negative iMainNumber)
printf("%c", '*');
PrintTriangle(iMainNumber + 1, 0);
if (iMainNumber == -1)
printf("\n");
} else if (iMainNumber > 0) {
if (iCurrNumber < iMainNumber) { // Preceding short lines
if (iCurrNumber > 1)
PrintTriangle(iMainNumber, iCurrNumber - 1);
PrintTriangle(-iCurrNumber, 0);
} else if (iCurrNumber == iMainNumber) {
PrintTriangle(iMainNumber, iCurrNumber - 1); // left
PrintTriangle(iMainNumber, iCurrNumber + 1); // Right
} else { // Subsequent short lines
if ((iCurrNumber - iMainNumber) < iMainNumber)
PrintTriangle(iMainNumber, iCurrNumber + 1);
PrintTriangle(-(iCurrNumber - iMainNumber), 0);
}
}
}
int main() {
PrintTriangle(3,3);
PrintTriangle(6,6);
return 0;
}

From what I have read, most suggestions have already pointed out to pass in any state you need.
However, you really don't need that many branching statements. Most of what you need, you can derive arithmetically. You can calculate the total number of recursions and derive the number of stars from the current recursion count. Also, by separating the portion of the initial invocation from the recursion, you can make usage much simpler.
Just saw that you do not want more than two integers. Consider the below and see if you really want to maintain that preference. If so, you can put the calculation of the total in the recursive portion. I think it would be less readable.
void _print_stars(int height, int total, int current)
{
int stars = current <= height ? current : 2 * height - current;
for (int i = 0; i < stars; i++) { printf("*"); }
printf("\n");
if (current != total)
{
_print_stars(height, total, current + 1);
}
}
void print_stars(int height)
{
int total_recursions = 2 * height - 1;
_print_stars(height, total_recursions, 1);
}

Pure recursion, no loops, calling program 'main()' passes only one parameter:
void PrintTheClms(int width, int stars) {
printf("*");
if stars < width then {
PrintTheClms(width, stars+1);
}
}
void PrintStars(int width) {
PrintTheClms(width, 1);
printf("\n");
}
void PrintTheRows(int size, int indent) {
PrintStars(indent);
if indent < size then {
PrintTheRows(size, indent+1);
PrintStars(indent);
}
}
void PrintTriangle(int size) {
if size > 0 then {
PrintTheRows(size, 1);
}
}
int main() {
PrintTriangle(6);
PrintTriangle(11);
// etc.
return 0;
}
Very simple -- no else clauses, no case constructs, no direction flag. Lots of procs and lots of calls, though.

Related

C Program to calculate sum of numbers X to Y using recursion

I have below code which works fine.
#include<stdio.h>
int calculateSum(int);
int main() {
int num;
int result;
printf("Input number = ");
scanf("%d", &num);
result = calculateSum(num);
printf("\nResult from 1 to %d = %d", num, result);
return (0);
}
int calculateSum(int num) {
int res;
if (num == 1) {
return (1);
}
else {
res = num + calculateSum(num - 1);
}
return (res);
}
Input number = 5
Result from 1 to 5 = 15
Now I am trying to give the program 2 inputs, from and to numbers.
Example: first input = 5, second = 8 and result should be = 26 (5 + 6 + 7 + 8)
Any ideas of how to go about this? failing thus far.
int calculateSum(int fromNum, int toNum) {
int res;
if (fromNum == toNum) {
return (fromNum);
}
else {
res = fromNum + calculateSum((fromNum + 1), toNum);
}
return (res);
}
At the moment, you are hard-coding 1 as the terminating point of the recursion.
What you need is to be able to use a different value for that, and the following pseudo-code shows how to do it:
def calculateSum(number, limit):
if number <= limit:
return limit
return number + calculateSum(number - 1, limit)
For efficiency, if you break the rules and provide a limit higher than the starting number, you just get back the number. You could catch that and return zero but I'll leave that as an exercise if you're interested.
It should be relatively easy for you to turn that into real code, using your own calculateSum as a baseline.
I should mention that this is a spectacularly bad use case for recursion. In general, recursion should be used when the solution search space reduces quickly (such as a binary search halving it with each recursive level). Unless your environment does tail call optimisation, you're likely to run out of stack space fairly quickly.
Instead of stopping when you reach 1, stop when you reach from.
int calculateSum(from, to) {
if (to == from) {
return from;
} else {
return to + calculateSum(from, to-1);
}
}
change 1 to from:
int calculateSum(int from,int to) {
int res;
if (to== from) {
return (from);
}
else {
res = to+ calculateSum(from,to - 1);
}
return (res);
}
You can use ternary operator.
int calculateSum(int from, int to) {
return from == to ? from : from + calculateSum(from + 1, to);
}

what does "not all control paths return a valueā€¯ mean in this program? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I wrote a code that takes inputs until an EOF integer (999999 in this case) is typed. Then it sorts the numbers and searches for our needle (an integer) in that array of integers (called haystack). Now I am facing a problem in my searching algorithm. While compiling it shows me a warning:
'search': not all control paths return a value
I think it means that the function might not return anything in some cases but the problem is that i can't think of any such case. I even checked my program with a lot of values and it always gave me the correct output. Can anyone help me figure out where the problem lies. I was use some windows native tools compiler for this.
Also if anyone has seen the CS50 pset3 find problem which is related to this, I used the same search function there too but while compiling the code in CS50 IDE the program never showed whether it found the needle in haystack. It only arranged them in increasing order and then stopped after that.
#include <stdio.h>
#include "cs50.h"
#include <stdlib.h>
bool search(int value, int values[], int n);
void sort(int values[], int n);
// maximum amount of hay
#define MAX 65536
int main(int argc, string argv[])
{
// ensure proper usage
if (argc != 2)
{
printf("Usage: ./find needle\n");
return -1;
}
// remember needle
int needle = atoi(argv[1]);
// fill haystack
int size;
int haystack[MAX];
for (size = 0; size < MAX; size++)
{
// wait for hay until EOF
printf("\nhaystack[%i] = ", size);
int straw = GetInt();
if (straw == 999999)
{
break;
}
// add hay to stack
haystack[size] = straw;
}
printf("\n");
// sort the haystack
sort(haystack, size);
// try to find needle in haystack
if (search(needle, haystack, size))
{
printf("\nFound needle in haystack!\n\n");
return 0;
}
else
{
printf("\nDidn't find needle in haystack.\n\n");
return 1;
}
}
/**
* Returns true if value is in array of n values, else false.
*/
bool search(int value, int values[], int n)
{
/* TODO: implement a searching algorithm */
int first = 0;
int last = n;
int middle = (first + last) / 2;
while (first + 1 < last)
{
if (value == values[middle])
{
return true;
break;
}
if (value == values[first])
{
return true;
break;
}
if (value == values[last])
{
return true;
break;
}
if (value < values[middle])
{
last = middle;
middle = (first + last) / 2;
}
if (value > values[middle])
{
first = middle;
middle = (first + last) / 2;
}
}
if (first + 1 >= last)
{
return false;
}
}
/**
* Sorts array of n values.
*/
void sort(int values[], int n)
{
// TODO: implement an O(n^2) sorting algorithm
for (int j = 1; j < n; j++)
{
for (int i = 0; i < (n - 1); i++)
{
if( values[i + 1] < values[i])
{
int b = values[i + 1];
values[i + 1] = values[i];
values[i] = b;
}
}
}
for (int k = 0; k < n; k++)
{
printf("haystack[%d] = %d ", k, values[k]);
}
}
The compiler does not execute your code. It does not do value tracking. While you can reason about the values of variables and expressions, this is generally an unsolvable problem for the compiler.
Your compiler tells you that it doesn't know what to return from search when control reaches the function's closing }.
BTW, it is a bad idea to write a function named sort, since the C Standard Library contains a function with the same name.

Using recursion to print strings in C

Let me start with saying I am not looking for someone to do this for me. I am hoping for a hint or suggestion.
I know there is a smarter way to do this. Code is posted below. I am trying to print an outline. My code works up to a depth of 3. (The depth is the number of subsections - so 3 would be section 1, section 1.A, and section 1.A.1). It also works for a width (number of sections and each type of subsection) of 26, where it is capped. However, to get a larger depth, it would involve many more loops. Not only is that terrible code, it also freezes up the terminal I'm working on.
I believe recursion would make it much nicer, but I'm struggling to grasp the idea when using a string (I understand when it is a number).Thanks!
#include <stdio.h>
int sec(int width, int snum) {
char section[100];
sprintf(section, "Section ");
printf("%s %i", section, snum);
return 0;
}
int ssec_num(int width, int i) {
char num[100];
sprintf(num, "%i", i);
printf(".%s", num);
}
int ssec_let(int width, char z) {
char let[100];
sprintf(let, ".%c", z);
printf("%s", let);
}
int main(int argc, char* argv[]) {
int depth = atoi(argv[1]);
int width = atoi(argv[2]);
int sec_int=1;
int sec_wid = width;
int let_wid;
int num_int;
int num_dep;
int num_wid;
int dep;
char z = 'A';
while(sec_wid > 0) {
sec(width, sec_int);
let_wid = width;
dep = depth-1;
printf("\n");
while(dep > 0) {
while(let_wid > 0) {
num_wid = width;
num_int = 1;
sec(width, sec_int);
ssec_let(let_wid, z);
printf("\n");
num_dep = depth-2;
while(num_dep > 0) {
while(num_wid > 0) {
sec(width, sec_int);
ssec_let(let_wid, z);
ssec_num(width, num_int);
num_wid--;
num_int++;
printf("\n");
num_dep--;
}
}
let_wid --;
z++;
}
dep --;
}
sec_int++;
sec_wid--;
z = 'A';
}
}
If depth is 3 and width is 2 then it would be
Section 1
Section 1.A
Section 1.A.1
Section 1.A.2
Section 1.B
Section 1.B.1
Section 1.B.2
Section 2
Section 2.A
Section 2.A.1
Section 2.A.2
Section 2.B
Section 2.B.1
Section 2.B.2
The algorithm you described uses a width to declare how many times each (sub)section is repeated. This kind of repetition you can achieve with a loop.
The algorithm also uses a depth to determine how many (sub)sections you have. Here is the tricky part, and you can use recursion to solve it. A recursive function is basically a function that calls itself a limited number of times. There must always be a condition to stop the recursion, otherwise the function would call itself until the call stack overflows, abnormally stopping the program execution.
For your problem, you can have a function that receives a counter, that determines at with (sub)section depth it currently is. It would loop width times (as described above) and call itself depth times, until the counter reaches the value of depth. This way, you'll have a function that has a depth number of (sub)sections, each with a width number of items.
As you need to print the (sub)sections at the previous depths, you can use a buffer to store the section values at each depth, like int buffer[MAX_DEPTH];, with #define MAX_DEPTH 100 to set the maximum depth your program supports.
Then you'll have something like
#include <stdio.h>
#define MAX_DEPTH 100
void print_section(const int *const buffer, const int current_depth) {
// print all the (sub)section values stored at the buffer so far
// use a loop like for (i = 0; i <= current_depth; i++)
}
void recursive(int *const buffer, const int current_depth,
const int depth, const int width) {
if (current_depth < depth) {
// continue recursion
int current_width;
for (current_width = 1; current_width <= width; current_width++) {
buffer[current_depth] = current_width;
print_section(buffer, current_depth);
recursive(buffer, current_depth + 1, depth, width);
}
}
// else stop recursion
}
int main(int argc, char* argv[]) {
// ...
int buffer[MAX_DEPTH];
recursive(buffer, 0, depth, width);
return 0;
}
You'll also need some extra logic to determine when to print a letter or a number at each (sub)section depth.
EDIT: To print the (sub)section title just use the following
void print_section(const int *const buffer, const int current_depth) {
int i;
printf("Section ");
for (i = 0; i <= current_depth; i++) {
printf(i == 0 ? "%i" : ".%i", buffer[i]);
}
printf("\n");
}

Optimizing I/O(Output) in C code + a loop

I have a code which reads around (10^5) int(s) from stdin and then after performing ## i output them on stdout. I have taken care of the INPUT part by using "setvbuf" & reading lines using "fgets_unlocked()" and then parsing them to get the required int(s).
I have 2 issues which i am not able to come over with:
1.) As i am printing int(s) 5 million on stdout its taking lot of time : IS THERE ANY WAY TO REDUCE THIS( i tried using fwrite() but the o/p prints unprintable characters due to the reason using fread to read into int buffer)
2.) After parsing the input for the int(s) say 'x' i actually find the no of divisors by doing %(mod) for the no in a loop.(See in the code below): Maybe this is also a reason for my code being times out:
Any suggestions on this to improved.
Many thanks
This is actually a problem from http://www.codechef.com/problems/PD13
# include <stdio.h>
# define SIZE 32*1024
char buf[SIZE];
main(void)
{
int i=0,chk =0;
unsigned int j =0 ,div =0;
int a =0,num =0;
char ch;
setvbuf(stdin,(char*)NULL,_IOFBF,0);
scanf("%d",&chk);
while(getchar_unlocked() != '\n');
while((a = fread_unlocked(buf,1,SIZE,stdin)) >0)
{
for(i=0;i<a;i++)
{
if(buf[i] != '\n')
{
num = (buf[i] - '0')+(10*num);
}
else
if(buf[i] == '\n')
{
div = 1;
for(j=2;j<=(num/2);j++)
{
if((num%j) == 0) // Prob 2
{
div +=j;
}
}
num = 0;
printf("%d\n",div); // problem 1
}
}
}
return 0;
}
You can print far faster than printf.
Look into itoa(), or write your own simple function that converts integers to ascii very quickly.
Here's a quick-n-dirty version of itoa that should work fast for your purposes:
char* custom_itoa(int i)
{
static char output[24]; // 64-bit MAX_INT is 20 digits
char* p = &output[23];
for(*p--=0;i/=10;*p--=i%10+0x30);
return ++p;
}
note that this function has some serious built in limits, including:
it doesn't handle negative numbers
it doesn't currently handle numbers greater than 23-characters in decimal form.
it is inherently thread-dangerous. Do not attempt in a multi-threaded environment.
the return value will be corrupted as soon as the function is called again.
I wrote this purely for speed, not for safety or convenience.
Version 2 based on suggestion by #UmNyobe and #wildplasser(see above comments)
The code execution took 0.12 seconds and 3.2 MB of memory on the online judge.
I myself checked with 2*10^5 int(input) in the range from 1 to 5*10^5 and the execution took:
real 0m0.443s
user 0m0.408s
sys 0m0.024s
**Please see if some more optimization can be done.
enter code here
/** Solution for the sum of the proper divisor problem from codechef **/
/** # author dZONE **/
# include <stdio.h>
# include <math.h>
# include <stdlib.h>
# include <error.h>
# define SIZE 200000
inline int readnum(void);
void count(int num);
int pft[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709};
unsigned long long int sum[SIZE];
int k = 0;
inline int readnum(void)
{
int num = 0;
char ch;
while((ch = getchar_unlocked()) != '\n')
{
if(ch >=48 && ch <=57)
{
num = ch -'0' + 10*num;
}
}
if(num ==0)
{
return -1;
}
return num;
}
void count(int num)
{
unsigned int i = 0;
unsigned long long tmp =0,pfac =1;
int flag = 0;
tmp = num;
sum[k] = 1;
for(i=0;i<127;i++)
{
if((tmp % pft[i]) == 0)
{
flag =1; // For Prime numbers not in pft table
pfac =1;
while(tmp % pft[i] == 0)
{
tmp =tmp /pft[i];
pfac *= pft[i];
}
pfac *= pft[i];
sum[k] *= (pfac-1)/(pft[i]-1);
}
}
if(flag ==0)
{
sum[k] = 1;
++k;
return;
}
if(tmp != 1) // For numbers with some prime factors in the pft table+some prime > 705
{
sum[k] *=((tmp*tmp) -1)/(tmp -1);
}
sum[k] -=num;
++k;
return;
}
int main(void)
{
int i=0,terms =0,num = 0;
setvbuf(stdin,(char*)NULL,_IOFBF,0);
scanf("%d",&terms);
while(getchar_unlocked() != '\n');
while(terms--)
{
num = readnum();
if(num ==1)
{
continue;
}
if(num == -1)
{
perror("\n ERROR\n");
return 0;
}
count(num);
}
i =0;
while(i<k)
{
printf("%lld\n",sum[i]);
++i;
}
return 0;
}
//Prob 2 Is your biggesr issue right now.... You just want to find the number of divisors?
My first suggestion will be to cache your result to some degree... but this requires potentially twice the amount of storage you have at the beginning :/.
What you can do is generate a list of prime numbers before hand (using the sieve algorithm). It will be ideal to know the biggest number N in your list and generate all primes till his square root. Now for each number in your list, you want to find his representation as product of factors, ie
n = a1^p1 * a1^p2 *... *an^pn
Then the sum of divisors will be.
((a1^(p1+1) - 1)/(a1 - 1))*((a2^(p2+1) - 1)/(a2-1))*...*((an^(pn+1) - 1)/(an-1))
To understand you have (for n = 8) 1+ 2 + 4 + 8 = 15 = (16 - 1)/(2 - 1)
It will drastically improve the speed but integer factorization (what you are really doing) is really costly...
Edit:
In your link the maximum is 5000000 so you have at most 700 primes
Simple decomposition algorithm
void primedecomp(int number, const int* primetable, int* primecount,
int pos,int tablelen){
while(pos < tablelen && number % primetable[pos] !=0 )
pos++;
if(pos == tablelen)
return
while(number % primetable[pos] ==0 ){
number = number / primetable[pos];
primecount[pos]++;
}
//number has been modified
//too lazy to write a loop, so recursive call
primedecomp(number,primetable,primecount, pos+1,tablelen);
}
EDIT : rather than counting, compute a^(n+1) using primepow = a; primepow = a*primepow;
It will be much cleaner in C++ or java where you have hashmap. At the end
primecount contains the pi values I was talking about above.
Even if it looks scary, you will create the primetable only once. Now this algorithm
run in worst case in O(tablelen) which is O(square root(Nmax)). your initial
loop ran in O(Nmax).

UVA's 3n+1 wrong answer although the test cases are correct . . .?

UVA problem 100 - The 3n + 1 problem
I have tried all the test cases and no problems are found.
The test cases I checked:
1 10 20
100 200 125
201 210 89
900 1000 174
1000 900 174
999999 999990 259
But why I get wrong answer all the time?
here is my code:
#include "stdio.h"
unsigned long int cycle = 0, final = 0;
unsigned long int calculate(unsigned long int n)
{
if (n == 1)
{
return cycle + 1;
}
else
{
if (n % 2 == 0)
{
n = n / 2;
cycle = cycle + 1;
calculate(n);
}
else
{
n = 3 * n;
n = n + 1;
cycle = cycle+1;
calculate(n);
}
}
}
int main()
{
unsigned long int i = 0, j = 0, loop = 0;
while(scanf("%ld %ld", &i, &j) != EOF)
{
if (i > j)
{
unsigned long int t = i;
i = j;
j = t;
}
for (loop = i; loop <= j; loop++)
{
cycle = 0;
cycle = calculate(loop);
if(cycle > final)
{
final = cycle;
}
}
printf("%ld %ld %ld\n", i, j, final);
final = 0;
}
return 0;
}
The clue is that you receive i, j but it does not say that i < j for all the cases, check for that condition in your code and remember to always print in order:
<i>[space]<j>[space]<count>
If the input is "out of order" you swap the numbers even in the output, when it is clearly stated you should keep the input order.
Don't see how you're test cases actually ever worked; your recursive cases never return anything.
Here's a one liner just for reference
int three_n_plus_1(int n)
{
return n == 1 ? 1 : three_n_plus_1((n % 2 == 0) ? (n/2) : (3*n+1))+1;
}
Not quite sure how your code would work as you toast "cycle" right after calculating it because 'calculate' doesn't have explicit return values for many of its cases ( you should of had compiler warnings to that effect). if you didn't do cycle= of the cycle=calculate( then it might work?
and tying it all together :-
int three_n_plus_1(int n)
{
return n == 1 ? 1 : three_n_plus_1((n % 2 == 0) ? (n/2) : (3*n+1))+1;
}
int max_int(int a, int b) { return (a > b) ? a : b; }
int min_int(int a, int b) { return (a < b) ? a : b; }
int main(int argc, char* argv[])
{
int i,j;
while(scanf("%d %d",&i, &j) == 2)
{
int value, largest_cycle = 0, last = max_int(i,j);
for(value = min_int(i,j); value <= last; value++) largest_cycle = max_int(largest_cycle, three_n_plus_1(value));
printf("%d %d %d\r\n",i, j, largest_cycle);
}
}
Part 1
This is the hailstone sequence, right? You're trying to determine the length of the hailstone sequence starting from a given N. You know, you really should take out that ugly global variable. It's trivial to calculate it recursively:
long int hailstone_sequence_length(long int n)
{
if (n == 1) {
return 1;
} else if (n % 2 == 0) {
return hailstone_sequence_length(n / 2) + 1;
} else {
return hailstone_sequence_length(3*n + 1) + 1;
}
}
Notice how the cycle variable is gone. It is unnecessary, because each call just has to add 1 to the value computed by the recursive call. The recursion bottoms out at 1, and so we count that as 1. All other recursive steps add 1 to that, and so at the end we are left with the sequence length.
Careful: this approach requires a stack depth proportional to the input n.
I dropped the use of unsigned because it's an inappropriate type for doing most math. When you subtract 1 from (unsigned long) 0, you get a large positive number that is one less than a power of two. This is not a sane behavior in most situations (but exactly the right one in a few).
Now let's discuss where you went wrong. Your original code attempts to measure the hailstone sequence length by modifying a global counter called cycle. However, the main function expects calculate to return a value: you have cycle = calculate(...).
The problem is that two of your cases do not return anything! It is undefined behavior to extract a return value from a function that didn't return anything.
The (n == 1) case does return something but it also has a bug: it fails to increment cycle; it just returns cycle + 1, leaving cycle with the original value.
Part 2
Looking at the main. Let's reformat it a little bit.
int main()
{
unsigned long int i=0,j=0,loop=0;
Change these to long. By the way %ld in scanf expects long anyway, not unsigned long.
while (scanf("%ld %ld",&i,&j) != EOF)
Be careful with scanf: it has more return values than just EOF. Scanf will return EOF if it is not able to make a conversion. If it is able to scan one number, but not the second one, it will return 1. Basically a better test here is != 2. If scanf does not return two, something went wrong with the input.
{
if(i > j)
{
unsigned long int t=i;i=j;j=t;
}
for(loop=i;loop<=j;loop++)
{
cycle=0;
cycle=calculate(loop );
if(cycle>final)
{
final=cycle;
}
}
calculate is called hailstone_sequence_length now, and so this block can just have a local variable: { long len = hailstone_sequence_length(loop); if (len > final) final = len; }
Maybe final should be called max_length?
printf("%ld %ld %ld\n",i,j,final);
final=0;
final should be a local variable in this loop since it is separately used for each test case. Then you don't have to remember to set it to 0.
}
return 0;
}

Resources