How do I write this C expression in J?
Asked Answered
M

2

6

How do I write this C expression in J? (where x is input integer, and a is temporary variable)

((a= ~x & (~x >> 1)) ^= a ? 0 : (a ^ (a & (a - 1))) | (a ^ (a & (a - 1))) << 1);

.

Edit:

In a more readable form:

    int a = (~x) & ((~x) >> 1);
    if (a == 0) return 0;
    int b = a ^ (a & (a - 1));
    return b | (b << 1);
Mitran answered 29/9, 2010 at 22:33 Comment(4)
How do we find the bastard that wrote it in the first place?Passing
Its not a homework, but it was 1 challenge. After solving it I just figured, that i have not played with J for a long time, and forgot its syntax. Thought some here would.Mitran
This expression results in undefined behavior. The subexpression ((a= ~x & (~x >> 1)) ^= a makes two unsequenced modifications to a. The "more readable form" does not result in undefined behavior, so it is not the same thing.Aftmost
@GMan a real bastard would never write if (a == 0) ..Clammy
Z
5

Without testing, the basic transcription would be something like this:

Shift =: (33 b.)
And   =: (17 b.)
Not   =: (26 b.)
Xor   =: (22 b.)
Or    =: (23 b.)

BastardFunction =: 3 : 0
  a =. (Not y) And (_1 Shift (Not y))
  if. a do.
    b =. a  Xor (a And a - 1)
    (1 Shift b) Or b
  else.
    0
  end.
)

But there could be a smarter approach.

Zilla answered 30/9, 2010 at 0:38 Comment(4)
Hmmm, I don't get 0 very often... That is to say, never.Zilla
Validated for values 0-9. I get the same result as the simplified form.Zilla
(2^31)-3, (2^31)-2, and (2^31)-1 will all return 0.Zilla
Validated for values 0 through 99, identical results in C and J.Zilla
C
3

Here is a small analyzis (of the "readable form" version):

usnigned int nx = ~x;   // I suppose it's unsigned 
int a = nx & (nx >> 1); 
// a will be 0 if there are no 2 consecutive "1" bits.
// or it will contain "1" in position N1 if nx had "1" in positions N1 and N1 + 1
if (a == 0) return 0;   // we don't have set bits for the following algorithm
int b = a ^ (a & (a - 1));  
// a - 1 : will reset the least 1 bit and will set all zero bits (say, NZ) that were on smaller positions
// a & (a - 1) : will leave zeroes in all (NZ + 1) LSB bits (because they're only bits that has changed
// a ^ (a & (a - 1)) : will cancel the high part, leaving only the smallest bit that was set in a
// so, for a = 0b0100100 we'll obtain a power of two: b = 0000100
return b | (b << 1);    
// knowing that b is a power of 2, the result is b + b*2 => b*3

It seems that the algorithm is looking for the first 2 (starting from LSB) consecutive 0 bits in the x variable. If there aren't any, then the result is 0. If they are found, say on position PZ, then the result will contain two set bits: PZ and PZ+1.

Clammy answered 30/9, 2010 at 0:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.