I have a contrived example to demonstrate the request for a specific functionality - I wonder if anyone has a clever trick to do this.
The following is a problem one encounters quite frequently:
"Print a series of numbers; print a space between them, and a carriage return (but no space) at the end.
The obvious solution is to make the last (or first) statement a special case. I was pondering ways to make this more efficient/compact.
brute force:
for(ii=0; ii<4; ii++) {
printf("%d", ii);
if(ii<3) printf(" "); else printf("\n");
}
Note that this involves two evaluations of a condition.
unrolling:
for(ii=0; ii<3; ii++) {
printf("%d ", ii):
}
printf("%d\n", ii);
Leverages the fact that ii will be incremented one last time as we leave the loop.
functionality I would like
ii = 0;
while(1) {
printf("%d", ii);
ii++;
if(ii<3) printf(" ");
else {printf("\n"); break;}
}
And I was wondering if it's possible to make this work inside the for statement. I tinkered a bit, and found that the following works (somewhat to my surprise... it did need the parentheses, and it quite unreadable between the ?: and the , operators - see http://codepad.org/wFa2YwCg):
for(ii=0; (ii<3)?(printf("%d ",ii),1):(printf("%d\n",ii),0);ii++);
I am essentially turning the evaluate this condition part of the for loop into a execute this statement for most of the loop, and this other one for the last pass statement.
I was wondering if there is a better way to do this - both efficient, and readable?
[In many ways this question should be closed as it's opinion based.]
This problem crops up often. I always opt for a solution that minimises the instructions in the iterative part.
{ /*don't pollute the outer scope with ii*/
int ii;
for (ii = 0; ii < 3; ++ii/*I've always preferred this to ii++*/) {
printf("%d ", ii);
}
printf("%d\n", ii);
}
Ternaries, if statements etc. just obfuscate things. In my opinion.
I have used the following type of construct for this situation. It is not more efficient (still has a condition at each iteration), but I like it because it results in a single printf:
char *sep = " ";
for(ii=0; ii<4; ii++) {
if ( ii == 3 )
sep = "\n";
printf( "%d%s", ii, sep );
}
"Brute force" and ternary condition solution have the same complexity, but the second one is less "readable".
You can do a simple method print:
void print() {
int i = 0;
for(i=0; i != size - 1; ++i) {
printf("%i ",i);
}
printf("%i\n", i);
}
I think it is efficient and readable too.
In this way you reduce cyclomatic complexity of your alghotitm.
For both readability and performance, I think the following code can be used:
for (ii = 0;; ii++)
{
printf("%d", ii);
(ii < 3) ? (putchar(' ')) : ({ putchar('\n'); break; });
}
Actually, the above code is similar to your last code. It is readable, and it still has one conditional evaluation in each increment.
int numberoftimes = 4
if numberoftimes > 1
{
for(ii=0; ii<numberoftimes - 1; ii++)
{
printf("%d ", ii);
}
}
printf("%d\n", numberoftimes - 1);
Either you test every time in the loop, or you test once first...
Here's a way that requires a separate initialization pass, but that has a slightly cleaner for loop. Array sepsarray holds the separators you want (in this example, commas so you can see them). The last element of sepsarray is followed by a '\0' that terminates the loop.
#include <stdio.h>
#define MAXNUM 5
//print up to this
void main() {
char sepsarray[256] = {0}; //256=arbitrary max size
int i;
char *seps=sepsarray;
for(i=0;i<MAXNUM;++i) sepsarray[i]=','; //fill in the separators
sepsarray[i]='\n'; //the last separator
for(i=0; printf("%d%c",i,*seps++),*seps; i++) /* pretend to do nothing */ ;
}
Output:
0,1,2,3,4,5
Hardly IOCCC material, but hey... :)
Related
I need to print the following pattern using a single for-loop without if statements.
1
21
321
I first tried to understand the logic and coded it using 2 for loops:
for (int i = 0 ; i <= num; i++) {
int temp = i;
for (int j = 0; j < i; j++){
printf("%d", temp);
temp--;
}
printf("\n");
}
However, I have no clue on how to approach this without a for loop AND no if statements.
Any hints/tips would be greatly appreciated.
Make a loop that will print integer 321 three times.
Modify loop print statement to print remainder of 321 divided by 10. Each line will now print 1.
After print statement, multiply divider by 10, so that after each loop iteration divider is 10 times bigger.
You can store the previous line and use it to produce new one. Here's naive implementation, working for up to 9 lines.
int main()
{
int num = 3;
char buffer[100] = {0};
char temp_buffer[200] = {0};
for (int i = 1 ; i <= num; i++) {
sprintf(temp_buffer, "%d%s", i, buffer);
printf("%s\n", temp_buffer);
strcpy(buffer, temp_buffer);
}
return 0;
}
Try to write loops as close to the most trivial/canonical form as possible:
for(int i=0; i<n; i++)
That means: avoid iterating starting from 1, avoid comparing with <=, avoid down-counting loops. There's a place for all of these things but avoid them when you can for the sake of readability and keeping things simple. As a bonus, readable loops are very often also fast loops.
In this case 2 for loops isn't a bad idea. You can consider the output a matrix of sorts, then have an outer for loop for "rows" and the inner one for "columns".
Write the outer for loop in the canonical form I showed above where n would be your maximum, such as 3.
Write the inner for loop so that it iterates from zero up to "rows" - the outer loop iterator. However, you don't want to write 0, 10 and so on so you should also compensate for this by adding + 1. So the upper limit condition of the inner loop could be cols < (rows+1).
Then when printing in the inner loop (assuming you took my advise to make it up-counting), print descending by starting at your max value rows+1 then subtract the current value. That is (rows+1) - cols.
Change new line in the outer loop, after printing each row, like you are already doing.
Result:
#include <stdio.h>
#define MAX 5
int main (void)
{
for(int rows=0; rows<MAX; rows++)
{
for(int cols=0; cols<(rows+1); cols++)
printf("%d",(rows+1)-cols);
printf("\n");
}
}
I produced this:
---------------------
*-------------------*
**-----------------**
***---------------***
****-------------****
*****-----------*****
******---------******
*******-------*******
********-----********
*********---*********
**********-**********
*********---*********
********-----********
*******-------*******
******---------******
*****-----------*****
****-------------****
***---------------***
**-----------------**
*-------------------*
But I was not satisfied with the first line. I wanted to exclude it, so I made a new one that excludes i=0 with a if-conditional wrapper around the for-loop. I was wondering if somebody knows a cleaner solution. (FYI, this was a test question, and my solution was very sloppy. I am practicing cleaner methods for this (stupid pyramid programming).
Code
Have a look at the comment // I want to exclude i=0 by using algebra in the for loop. Anybody with an idea?
#include <stdio.h>
#include <stdlib.h>
int main(void) {
/* Pyramid Size */
int n = 10;
/* Take care of the top */
for (int i=0;i<n;i++) {
for (int j=0;j<i;j++)
printf("*");
if (i != 0) { // I want to exclude i=0 by using algebra in the for loop
for (int j=0;j<=n*2-i*2;j++) {
printf("-");
}
}
for (int j=0;j<i;j++)
printf("*");
printf("\n");
}
/* Take care of the bottom */
for (int i=n;i>0;i--) {
for (int j=0;j<i;j++)
printf("*");
for (int j=0;j<=n*2-i*2;j++) {
printf("-");
}
for (int j=0;j<i;j++)
printf("*");
printf("\n");
}
}
Just start the loop from 1 instead of 0. Or, alternatively replace < by <= in the loop for j.
Note also that at the middle your stars don't meet completely, there's still a gap between them. Is this an intended behavior?
I guess you wonder why this "trick" is only required at the beginning, while at the bottom of your modern-art painting there's no empty line. This type of "miracles" is called off-by-one error. You should check your code carefully for boundary cases to see if it performs as designed.
Can you start i from 1?
/* Take care of the top */
for (int i=1;i<n;i++) {
I am starting to teach myself C and am trying to build a group of useful functions and programs for future reference. If relevant, this is C99.
Here is my most recent iteration of the program. At the output, I want to get the prime factorization of a number n. As is, however, I get a list of all factors, and no factors are repeated. I included some print statements to try and debug, and have found that the error is with the recursion, but can't figure out how to interpret it further. I previously tried making the recursive function of type int, but had difficulties getting it to work with the array p.
n is the number that I am trying to factor
p is an array for storing the found primes
j is an index for p
c is the number that I am testing as a divisor to n
I am aware that there are probably more efficient ways to declare p to save memory, but since this is mainly for reference, memory is not a huge concern.
I found these questions but don't think that they answer my question
finding greatest prime factor using recursion in c :This question is about crashing code. Mine compiles, runs, and produces reasonably sensible output, I'm just wondering why the output isn't what I expect.
is there ever a time you would not use recursion? [closed] :This indicates that recursion is not a good choice for prime factorization- I don't know, but suspect that this would also apply to C. Since this is for reference, I don't think it is a huge issue. If you disagree, please explain why.
My main questions are these:
Why does the output show all factors of n?
Why does it not repeat the prime factors?
What do I have to do to fix it?
#include <stdio.h>
#define NELEMS(x) (sizeof(x) / sizeof((x)[0]))
void factors(int n, int p[], int j) {
/// if n is divisible by c, store c, and continue with n/c
int c;
for (c=2; c < n; c++) {
if (c > n) break;
if (n%c == 0) {
p[j] = c;
printf("%d has been added to p \t", c);
printf("n has been reduced to %d \t", n/c);
printf("j is %d \n", j);
j++;
if (n == c) break;
factors(n/c, p, j);
}
}
}
int main() {
/// set up number to factor, and array to hold factors
int n = 24;
int p[n/2];
int i=0;
for (i=0; i<NELEMS(p); i++) {
p[i]=0;
}
int j = 0;
factors(n, p, j);
printf("the prime factors of %d are:\n",n);
for (i=0; i<NELEMS(p); i++) {
printf("%d \n", p[i]);
}
}
You have already been told in comments that this algorythm is poor, which is an evidence here. And you really should learn to use a debugger: running this through a debugger immediately shows where the problems are.
That being said, your main problem here is what to do when the recursive functions return?. You failed to ask yourself this question which is a must in recursion, and simply continue in sequence, which is plain wrong because you will reuse a number that has already been processed in the recursive calls. So you must add a return line immediately after recursively calling factors.
Once this is done, there is another minor problem (that a debugger would make evident), you only search factors strictly lesser that n. So you miss the last prime factor...
With those 2 immediate fixes, your code becomes:
void factors(int n, int p[], int j) {
/// if n is divisible by c, store c, and continue with n/c
int c;
for (c=2; c <= n; c++) {
if (c > n) break;
if (n%c == 0) {
p[j] = c;
printf("%d has been added to p \t", c);
printf("n has been reduced to %d \t", n/c);
printf("j is %d \n", j);
j++;
if (n == c) break;
factors(n/c, p, j);
return;
}
}
}
But IMHO p[j] = c; should become *p = c; and factors(n/c, p, j); should become factors(n/c, p+1, j);. Said differently you pass directly a pointer to the next slot.
Edit It occurs to me that the smallest factor of n is guaranteed to be prime, so I have edited the answer accordingly.
Why does the output show all factors of n?
Because you test if c is a factor of n and add it to the array p whether c is prime or not. Then you carry on testing numbers above c, even multiples of c.
Why does it not repeat the prime factors?
Because when you find a number c that is a factor, you don't necessarily inspect it to find out if it is a compound number itself.
After adding c to p, you need to recursively call factor on (n / c) and then stop.
Here is roughly what you need (but not tested or even compiled)
int factorise(int n, int p[], int j)
{
int factorsFound = 0;
for (c = 2 ; c * c <= n && factorsFound == 0 ; ++ c)
{
if (n % c == 0)
{
p[j] = c;
factorsFound = factorise(n / c, p, j + 1) + 1;
}
}
if (factorsFound == 0) // n is prime
{
p[j] = n;
factorsFound = 1;
}
return factorsFound;
}
Also in a real solution, you probably want to pass the size of p so that you can detect if you run out of space.
Just for fun, since nobody else has posted it yet, here is a non recursive solution. It's actually the same as above but the recursion has been transformed into a loop.
int factorise(int number, int p[])
{
int j = 0;
for (int c = 2, int n = number ; n > 1 ; )
{
if (n % c = 0)
{
p[j++] = c;
n = n / c;
}
else
{
c++;
}
}
return j;
}
I disagree with some of Lundin's comments about recursion. Recursion is a natural way of breaking a problem down into easier subtasks but in C it is undeniably less efficient, especially in terms of stack space and in this particular case, the non recursive version is simpler.
From This answer:
why does recursion cause stackoverflow so much more than loops do
Because each recursive call uses some space on the stack. If your recursion is too deep, then it will result in StackOverflow, depending upon the maximum allowed depth in the stack.
When using recursion, you should be very careful and make sure that you provide a base case. A base case in recursion is the condition based on which the recursion ends, and the stack starts to unwind. This is the major reason of recursion causing StackOverflow error. If it doesn't find any base case, it will go into an infinite recursion, which will certainly result in error, as Stack is finite only.
-
It appears that your for is in the way, c will increment, and wont check that same value again.
For instance, if the input is 8, we want (2,2,2) and not (2,4).
I would recommend replacing your if (c%n ==0) by a while, don't forget to replace the value of n in that while, you don't want to loop in that.
This appears to be a good answer :
int primes(int nbr, int cur)
{
if (cur > nbr)
return (0);
else
{
if (nbr % cur == 0 && isprime(cur) == 1)
{
printf("%d\n", cur);
return (primes(nbr / cur, 2));
}
return (primes(nbr, cur + 1));
}
}
Call that function with cur = 2 in your main
I want to print the combination of any 3 letters without using nested for loop in C programming ?
Following is the code for the combination of 3 letters "ABC".
I can execute the program by using 3 for loops.
But I dont want that. I want to do it by only one for loop and in a non-recursive way.But I am not getting any logic.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i=0,j=0;
char b[10],a[] = "ABC";
strcpy(b,a);
while(i < 3)
{
b[j]=a[i];
if(i==0)
{
b[j+1]=a[i+1];
b[j+2]=a[i+2];
printf("\n%s",b);
b[j+1]=a[i+2];
b[j+2]=a[i+1];
printf("\n%s",b);
}else if(i==1)
{
b[j+1]=a[i+1];
b[j+2]=a[i-1];
printf("\n%s",b);
b[j+1]=a[i-1];
b[j+2]=a[i+1];
printf("\n%s",b);
}else
{
b[j+1]=a[i-1];
b[j+2]=a[i-2];
printf("\n%s",b);
b[j+1]=a[i-2];
b[j+2]=a[i-1];
printf("\n%s",b);
}
i++;
}
getch();
return 0;
}
If you know it's always going to be a length of three, you can use pre-generation to minimise complexity and/or code. Pre-generation is the act of moving complex calculations from run time to compile time or even before hand, and it can be very productive for complex calculations.
One example (though a little contrived) is to write a program to calculate all possible unsigned 64-bit factorials (there's only about ninety of them) then have that program generate the source code (lookup table and function) that can do the lookup to get them. The complexity of generating the table is done once, long before compilation of the program that will use it.
This means that a factorial operation in the program that uses it, changes from being a possibly time consuming series of multiplications to something more akin to one multiplication and an addition (the table lookup).
Applying that same method to permutations (though the generation of the lookup table was done in my head since it's not that complex) will give you code like:
#include <stdio.h>
// The permutations.
static int perm3[] = { 0,1,2, 0,2,1,
1,0,2, 1,2,0,
2,0,1, 2,1,0 };
int main (void) {
int i;
char x[] = {'a', 'b', 'c'};
// Permute using the table to get indexes.
for (i = 0; i < sizeof(perm3) / sizeof(perm3[0]); i += 3)
printf ("%c %c %c\n", x[perm3[i]], x[perm3[i+1]], x[perm3[i+2]]);
return 0;
}
Now, some people may consider that "cheating" but I'll be honest here, some of the fastest programs you can write will cheat in this manner :-)
The problem you are asking is based of algorithm concept Backtracking
Here is the function
void permute(char *a, int i, int n)
{
int j;
if (i == n)
printf("%s\n", a);
else
{
for (j = i; j <= n; j++)
{
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j)); //backtrack
}
}
}
call this from main()
int main()
{
char a[] = "ABC";
permute(a, 0, 2); // first param is array,2nd is starting index and 3rd is ending index
return 0;
}
Wolfram alpha is having mathematical concept behind these type of problem.Basically we try all the solutions one by one and then backtrack by reverting those changes to original one and then again try out different solution.To understand clearly check this.
http://mathworld.wolfram.com/Permutation.html
This question already has answers here:
for loop missing initialization
(6 answers)
Closed 2 years ago.
Not long ago, I stumbled across a very interesting innovation in a for loop (or maybe it is nothing new but I've been living in a cave?). Please take a look and explain to me why the initialize gap is empty? Of course, that's the part of the program which works. I would grateful for any revelation:)
void rzad_zn(char ch, int i, int j)
{
int pom;
pom = i;
for(; i<=j; i++)
{
printf("%d ", i);
}
printf("\n");
for(; pom<=j; pom++)
{
printf("%c ", ch);
}
printf("\n");
}
The for loop has three components, all of which are optional, as in this is a valid loop as well:
for (;;) { }
Though it is an infinite loop unless something calls break.
Any combination of arguments may be used, even compound ones like:
for (int i = 0, j = 0; i < j; ++i) { ... }
Where you can declare multiple variables, or use the comma operator in the other parts to join together several operations if necessary.