Tell me more ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Need to print out:

0
-1
1
-2
2
-3
3
-4
4
...

Write the code below for this case:

for(int i=0;i<=4;i++){
    for(int k=-i;;k=Math.abs(i)){
        process(k);
        if(i==k)break;
    }
}

Is there any way to optimize this algorithm? (process method can only be called once in a loop)

share|improve this question
Your restriction about only calling process once is pretty arbitrary. Why? – David Grayson Jul 25 '12 at 15:42
Looks like a code golf or project Euler puzzle? ;) – msanford Jul 25 '12 at 21:12

migrated from stackoverflow.com Jul 25 '12 at 18:23

10 Answers

up vote 6 down vote accepted
for (int i=0; i!=-5;i = i<0 ? -i : -(i+1)) {
  process(i);
}
share|improve this answer
1  
Though this works, the actual structure of the for loop leaves the result a little ambiguous don't you think? – NominSim Jul 25 '12 at 14:43
@NominSim: Not sure what you mean. Do you mean it is hard to read? – Vaughn Cato Jul 25 '12 at 14:44
Meh, I can't really nit pick too much since this is essentially a carbon copy of my answer, but if I were to look at this loop (which ends with a process(4); and wanted to loop to 6 instead, it would be less than intuitive to change the i!=-5 to i!=-7. – NominSim Jul 25 '12 at 14:50
1  
@NominSim: I agree. I'm assuming the OP's question is purely academic though. The restriction that process() only occur once seems artificial, and a good compiler will produce equivalent instructions anyway, so there's really no point in trying to optimize it for speed. I'm left thinking that the goal is just to make a cute short loop that behaves equivalently to the original code. – Vaughn Cato Jul 25 '12 at 14:56

If only need to print out those values why don't you just do this?

for (int i=0;i<=4;i++){
     if(i!=0){
          System.out.println(i*(-1));
     }
     System.out.println(i);
}
share|improve this answer

Printing 0 separately, then replacing the inner loop with two print statements would definitely reduce the number of instructions executed. Given how expensive printing is, though, it's not really an "optimization;" the execution time would not change.

share|improve this answer
thanks for answer,I edited my question,process method can only be called once in a loop,any way to optimize this? – Zenofo Jul 25 '12 at 14:10
1  
Well, eliminate the Math.abs(i) call -- it does nothing, as i is always non-negative. Also the test if (i==0) is likely to be a bit more efficient than if (i==k). But all of these are tiny, inconsequential optimizatons: surely you have better things to worry about! – Ernest Friedman-Hill Jul 25 '12 at 14:18
print 0
for(i = 0; i < 5; i++) {
    print i
    print -i
}
share|improve this answer

Based on your edit, and the criteria that process can only be called once, you can do this:

for (int i = 0; Math.abs(i) < 5; i = i < 0 ? -i : -i - 1){
    process(i);
}
share|improve this answer
Interesting!but has a bug,for (int i = 0; i <=4 ; i++){..,lastest number is -5 – Zenofo Jul 25 '12 at 14:23
Whoops you are right, since i is now in the range of -4 to 4, you have to account for both sides of the range, edited to reflect that. (Or you can do int i; for(i = 0; i < 4; i++){...} then process(i)) – NominSim Jul 25 '12 at 14:28
@GermannArlington This will perform the functionality that the OP wants, it won't "blow up". I had the variable change inside the loop for clarity, but I will move it within the for declaration for peace of mind. – NominSim Jul 25 '12 at 14:55

How about this:

int8_t i = 0;
while(i != -5)
{
    process(i);
    i = -i + (i <= 0);
}
share|improve this answer

Seeing you edited your answer I'm going to suggest this.

process(i=0)
for (int i=1;i<=4;i++){
     process(i*(-1));
     if(i < 0){ 
          i=i*(-1);
     }
     else{
          i=i*(-1) -1;
     }
}

EDIT: Sorry missed the proper order.

share|improve this answer
Also if you really want to process 0 in the same for loop you can just wrap those two if statements within another if statement and check if its 0 and if it is skip those two if statements. – Flo Jul 25 '12 at 14:18
This prints in the opposite order the OP wants (i.e. 1 before -1) – NominSim Jul 25 '12 at 14:19
@NominSim You're right. Please see my edit. – Flo Jul 25 '12 at 14:21
i = 0;
j = 5;
while (i>-j) {
    process(i);
    if (i>=0) {
        i=-i;
        i--;
    }
    else {
        i=-i;
    }
}
share|improve this answer

You have measured this and found it not to be good enough, right? The next thing to do is to look at why the generated code isn't good enough, which I can't do because I know nothing about your compiler, environment, etcetera. So I'm going to guess that the call to Math.abs is the worst thing you do.

for (int i=0;i<=4;i++){
    for (int k=-i;
          k <= i;
          k = k + i + i) // this sets k = i on the first update, and puts k
                         // past the termination condition on the second
    {
       process(k);
    }
}

I am thoroughly curious about why your process function must be called only once per iteration.

share|improve this answer

process method can only be called once in a loop

I'll assume it must be called once, and exactly once. I'll also assume that the statement implies that there must be a loop of some sort.

Now, time to cheat!

int main()
{
    do
    {
        process(0);
        printf("-1\n1\n-2\n2\n-3\n3\n-4\n4\n");
    } while (false);
    return 0;
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.