Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

What is the shortest C expression that is defined to evaluated to false the first time and true for every time after that:

Reference implementation:

bool b = false;  // you get this for free.

(b ? true : b = true, false)  // only this line is measured.
share|improve this question
3  
Since the task description in fact states that it should return true for every time after the initial false, I'd say that solutions that work only a limited time (even if it's 500+ years) don't count as correct solutions. –  Joey Jan 26 '12 at 21:35
add comment

12 Answers

3 chars:

As Keith Randall suggested in a comment, if we can use floats or doubles, this should do the trick:

float b = 0;  // free

b++

Eventually, as b is incremented repeatedly, two things may happen: either the addition overflows (and thus evaluates to HUGE_VAL, which may be infinite or a large positive value) or, more likely, the roundoff step size simply grows larger than one, turning the increment into a no-op. In either case, the expression should continue to evaluate as true.

share|improve this answer
1  
That will happen at ~1/ε en.wikipedia.org/wiki/Machine_epsilon –  BCS Jan 27 '12 at 15:34
    
I think that is valid and I don't think anything smaller is going to work (there are no mutating single char unary operators). OTOH coercion a floating point to bool offends my sensibilities (as well as FP-ops being slower than int-ops). –  BCS Jan 27 '12 at 15:38
    
To be precise, b stops growing at 16777216.0 (=2^24), as there are only 23 bits of mantissa in a float. –  Keith Randall Jan 27 '12 at 21:56
    
BTW: I'm not sure but ++ on a bool might work as well: stackoverflow.com/a/3450554/1343 –  BCS Feb 16 '12 at 19:18
add comment

With:

long long b = 0;

then three characters are enough for many applications:

b++

Evaluates false first and true for a long time thereafter ;-)

share|improve this answer
12  
I'd say it'll be true for a long, long time. –  Kris Harper Jan 26 '12 at 15:47
1  
It evaluates true only 18446744073709551614 times, not forever :-/ –  copy Jan 26 '12 at 15:53
3  
Use a double and it will be true forever! –  Keith Randall Jan 26 '12 at 16:48
1  
And unless you make that unsigned, it is undefined behavior. –  BCS Jan 26 '12 at 18:16
7  
18446744073709551614 times. Assuming we could perform this operation 1 billion times per second, it would take about 585 years. –  Steven Rumbalski Jan 26 '12 at 20:09
show 2 more comments

6 characters

int i = 0; //free
i||i++

OTOH: I like Peter Taylor's solution as it has no branch so it may be faster (depending on compiler details).

p.s. I came up with that after posting the question (honest!).

share|improve this answer
    
After the first time, the left side of the || will be true and short-circuit evaluation will prevent the right side from getting evaluated so nothing gets updated. –  BCS Jan 26 '12 at 21:37
    
Argh, indeed. I take that back :) –  Joey Jan 26 '12 at 21:38
add comment

7 characters

As Peter Taylor suggested, still int a = 2;

!(a/=2)


8 characters (old)

Start with int a = 2;

!(a>>=1)

Another version of this: int b = 0x40000000;

!(b<<=1)
share|improve this answer
    
The first one is portable. The second isn't. But doesn't !(a/=2) work? –  Peter Taylor Jan 26 '12 at 18:32
    
@PeterTaylor yeah, you're right. Thinking too complicated ... –  copy Jan 26 '12 at 19:03
    
The left shift works and is defined if you go with unsigned ints and use 0xD... which I think you can get in a portable way via ~((~0u)>>2). –  BCS Jan 27 '12 at 15:43
    
@BCS thanks for the info, but I'll just leave it at that because the other two versions are shorter anyway. –  copy Jan 27 '12 at 22:08
add comment

9 chars:

b=0;//free
(b&(b=1))

at least if it's valid c (not undefined behavior)

12 chars

(b?b:!(b=1))

this is valid c

share|improve this answer
add comment
int b=1; // for free
!b|(b=0)

bit-wise or works as well since in first trial 0|0 yields 0 and in other trials !0|0 yields !0 which is guaranteed to be true. It is also ANSI-compliant, I've tried the following code with GCC 4.6.1 with -ansi flag:

#include <stdio.h>
main () {
  int b=1, i=0;
  for (;i<5;++i)
    printf ("%d",!b|(b=0));
}
share|improve this answer
    
This is undefined behavior. The compiler could evaluate b=0 first and !b later, making it true the first time. –  ugoren Jun 19 '12 at 6:40
add comment

11 10 chars

I can't beat the three char approach, but make it different:

int b = 0;  // free

b?b:0*(b=1) // 11 characters
b||0*(b=1)  // one character less thanks to breadbox
share|improve this answer
    
That wound count as 11 and doesn't work as it is two different expressions. –  BCS Jan 31 '12 at 15:10
    
@BCS I thought the first initialization was for free (so, the chars do not count), and the second one is an expression to be evaluated. I fail to see why wouldn't it work. –  Alpha Jan 31 '12 at 22:36
    
I was summing you were considering the expression in the first line to be the "gives false" and the other to be the "gives true". ---- The expression will evaluate to 1 (i.e. true) every time, including the first. The spec is that the expression is true the first time and false there after. –  BCS Feb 1 '12 at 3:26
    
@BCS Got it! Will update now to reflect your correction and will think a little bit about it. I'll see if I can give it a twist. Thanks! –  Alpha Feb 1 '12 at 5:20
1  
b?b=1:0*(b=1) actually works. –  walpen Jun 17 '12 at 16:35
show 3 more comments

APL (5 or 6)

If I'm only allowed to initialize the variable to 0, it's 6 characters:

A←0    ⍝ free
⊃A←⍴⍴A

How it works: ⍴A is the size of A (which is the empty list the first time around, because 0 is a scalar), so ⍴⍴A is the size of the size of A (which is [0] the first time, because a one-dimensional empty list has zero values in one dimension). This is then assigned to A (A←) and the first element is returned ().

  1. A is 0, ⍴A is [], then A is set to ⍴⍴A which is [0], and the first element is returned (0).
  2. A is [0], ⍴A is [1], then A is set to ⍴⍴A which is [1], and the first element is returned (1).
  3. A is [1], so ⍴A remains [1], so A is set to ⍴⍴A which remains [1] and it returns 1.

If I'm allowed to initialise the variable to anything I want, I can set it to the empty list and drop one of the s to make it 5 characters:

A←⍬    ⍝ free, set to empty list
⊃A←⍴A
share|improve this answer
add comment

9 chars

b=1; //free
!b||(b=0)  

edited: no longer undefined behavior

share|improve this answer
    
that very similar to a=a++ which is undefined –  ratchet freak Jan 26 '12 at 2:46
    
now defined, +3 chars :( –  AShelly Jan 26 '12 at 3:54
add comment
bool b = false; // for free?
b = b?b:!b;
share|improve this answer
add comment

What about this:

bool b = false;

!b+b++
share|improve this answer
1  
I think that is undefined behavior (and it will overflow and reset) –  BCS Feb 16 '12 at 0:14
    
Why do you think so? What exactly is undefined? plusplusing a boolean? Or the priority of post-increment operation? –  Vanuan Feb 16 '12 at 12:26
1  
1) The value depends on order of evaluation which is undefined behavior. 2) Either that will eventually overflow (and both hit undefined behavior as well as return false) or the 3 char solution (b++) works with bool as well: stackoverflow.com/a/3450554/1343 –  BCS Feb 16 '12 at 19:17
    
The answer in the link you provided quotes C++03 standard. Does this standard apply to C99 as well? –  Vanuan Feb 16 '12 at 20:14
1  
I'm reasonably sure that it is undefined in C as well. –  BCS Feb 17 '12 at 0:28
add comment

1 Character

Since you didn't specify which compiler and/or which command line options are to be used, here's my 1 character solution:

bool b = false;

X

Compile with

gcc -DX='(b ? true : b = true, false)'
share|improve this answer
9  
As a general rule, codegolf counts special command-line options towards the score. So this would be 41+ characters. –  Peter Taylor Feb 20 '12 at 22:18
add comment

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.