"First time" test

7

1

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.

BCS

Posted 2012-01-26T01:06:40.010

Reputation: 271

4Since 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 – 2012-01-26T21:35:50.183

Answers

11

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.

Ilmari Karonen

Posted 2012-01-26T01:06:40.010

Reputation: 19 513

1

That will happen at ~1/ε http://en.wikipedia.org/wiki/Machine_epsilon

– BCS – 2012-01-27T15:34:10.403

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 – 2012-01-27T15:38:21.567

To be precise, b stops growing at 16777216.0 (=2^24), as there are only 23 bits of mantissa in a float. – Keith Randall – 2012-01-27T21:56:25.593

BTW: I'm not sure but ++ on a bool might work as well: http://stackoverflow.com/a/3450554/1343

– BCS – 2012-02-16T19:18:16.590

10

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!).

BCS

Posted 2012-01-26T01:06:40.010

Reputation: 271

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 – 2012-01-26T21:37:44.603

Argh, indeed. I take that back :) – Joey – 2012-01-26T21:38:18.917

8

With:

long long b = 0;

then three characters are enough for many applications:

b++

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

William Morris

Posted 2012-01-26T01:06:40.010

Reputation: 205

1-1: Does not follow specs true for every time after that. – Thomas Eding – 2012-02-26T11:24:45.117

I flagged it for deletion. – user unknown – 2012-04-17T23:16:31.150

12I'd say it'll be true for a long, long time. – Kris Harper – 2012-01-26T15:47:48.103

1It evaluates true only 18446744073709551614 times, not forever :-/ – copy – 2012-01-26T15:53:29.413

3Use a double and it will be true forever! – Keith Randall – 2012-01-26T16:48:40.703

1And unless you make that unsigned, it is undefined behavior. – BCS – 2012-01-26T18:16:33.113

718446744073709551614 times. Assuming we could perform this operation 1 billion times per second, it would take about 585 years. – Steven Rumbalski – 2012-01-26T20:09:34.213

7

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)

copy

Posted 2012-01-26T01:06:40.010

Reputation: 6 466

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 – 2012-01-27T15:43:51.447

@BCS thanks for the info, but I'll just leave it at that because the other two versions are shorter anyway. – copy – 2012-01-27T22:08:00.720

1The first one is portable. The second isn't. But doesn't !(a/=2) work? – Peter Taylor – 2012-01-26T18:32:56.643

@PeterTaylor yeah, you're right. Thinking too complicated ... – copy – 2012-01-26T19:03:09.837

2

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

ratchet freak

Posted 2012-01-26T01:06:40.010

Reputation: 1 334

1

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

Alpha

Posted 2012-01-26T01:06:40.010

Reputation: 301

That wound count as 11 and doesn't work as it is two different expressions. – BCS – 2012-01-31T15:10:08.320

@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 – 2012-01-31T22:36:33.983

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 – 2012-02-01T03:26:48.897

@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 – 2012-02-01T05:20:46.960

1b?b=1:0*(b=1) actually works. – walpen – 2012-06-17T16:35:29.427

@walpen Thanks! I had completely forgotten about this answer. I've updated based on your comment, reducing out the first b=1 to b, as it would be already 1 in that case, right? (Or is there something else I am overseeing?) – Alpha – 2012-06-18T19:32:37.237

You don't need the ternary operator; b||0*(b=1) would also work. – breadbox – 2012-06-18T22:00:34.013

@breadbox Updated! Thanks! – Alpha – 2012-06-18T22:23:41.840

1

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));
}

Mehmet Emre

Posted 2012-01-26T01:06:40.010

Reputation: 11

This is undefined behavior. The compiler could evaluate b=0 first and !b later, making it true the first time. – ugoren – 2012-06-19T06:40:07.627

1

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

marinus

Posted 2012-01-26T01:06:40.010

Reputation: 30 224

0

9 chars

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

edited: no longer undefined behavior

AShelly

Posted 2012-01-26T01:06:40.010

Reputation: 4 281

that very similar to a=a++ which is undefined – ratchet freak – 2012-01-26T02:46:45.977

now defined, +3 chars :( – AShelly – 2012-01-26T03:54:21.837

0

bool b = false; // for free?
b = b?b:!b;

Pete Wilson

Posted 2012-01-26T01:06:40.010

Reputation: 101

0

What about this:

bool b = false;

!b+b++

Vanuan

Posted 2012-01-26T01:06:40.010

Reputation: 101

1I think that is undefined behavior (and it will overflow and reset) – BCS – 2012-02-16T00:14:25.110

Why do you think so? What exactly is undefined? plusplusing a boolean? Or the priority of post-increment operation? – Vanuan – 2012-02-16T12:26:31.763

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: http://stackoverflow.com/a/3450554/1343
  • – BCS – 2012-02-16T19:17:17.933

    The answer in the link you provided quotes C++03 standard. Does this standard apply to C99 as well? – Vanuan – 2012-02-16T20:14:08.940

    1I'm reasonably sure that it is undefined in C as well. – BCS – 2012-02-17T00:28:32.640

    -3

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

    celtschk

    Posted 2012-01-26T01:06:40.010

    Reputation: 4 650

    9As a general rule, codegolf counts special command-line options towards the score. So this would be 41+ characters. – Peter Taylor – 2012-02-20T22:18:56.437