5

The question as mentioned above is as follows: Given two integers, x1 and x2, find another integer, x3, which is different from both x1 and x2 , without using the if keyword.

My solution is based on bit wise operations on integers plus on the fact that XOR between two bits will return 1 if and only if the two bits are not equal.

Is this solution valid ? Can you find a better solution ? Off course that run time considerations and memory consumption should be as good as possible.

Note: The ternary operations and comparisons(i.e. - != , == ) are as well NOT allowed

Thanks in advance,

Guy.

My solution:

int foo(int x1,int x2)
{
    // xor
    int x3 = x1 ^ x2;

    // another xor 
    x3 = x3 ^ x2;

    // not
    x3 = ~x3;

    return x3;  

}
Guy Avraham
  • 3,482
  • 3
  • 38
  • 50
  • 1
    What you have is `~(x ^ y ^ y)`, which is just `~x`, so it doesn’t work if `y = ~x`. – Ry- Feb 18 '17 at 08:50
  • 2
    `z = x^y; z=z^y` means `z=x` then `z==~x` may be `~x == y`??? – Jean-Baptiste Yunès Feb 18 '17 at 08:50
  • 1
    You can do a disguised `if` using multiplicative properties: `a= c*x+(1-c)*y` that gives you x if `c==1` and y if `c==0`. May be using it in some way? – Jean-Baptiste Yunès Feb 18 '17 at 08:54
  • 1
    @A.Monti - Thanks for the clarification. The goal is to return a third number , any number, with the requirements that: 1) It wont be x1 nor x2. 2) I can not use the if keyword. – Guy Avraham Feb 18 '17 at 08:55
  • 2
    Anyway, you can make a number that’s different from x1 in the twos position and different from x2 in the ones position: `(~x1 & 2) | (~x2 & 1)`. – Ry- Feb 18 '17 at 09:00
  • Is it fair to conclude that there is no way to generate a third number using only arithmetic and bitwise operations that is guaranteed to be dfiferent from the two signed starting numbers? If yes, then the question cannot be answerd without some form of cheating (i.e. peeking at the flags register). – Paul Ogilvie Feb 18 '17 at 09:15
  • 1
    @Ryan Your last comment seems to work on any case. Thanks !! – Guy Avraham Feb 18 '17 at 09:19
  • 1
    how about `x1 ^ x2 ^ !(x1 && x2)` – M.M Feb 18 '17 at 09:22
  • 1
    @M.M: Fails for (1, 0). – Ry- Feb 18 '17 at 09:25
  • 1
    Could you clarify: do you mean without any conditional checks (which would also rule out the ternary, ==, != and so on.) – Bathsheba Feb 18 '17 at 09:37
  • 1
    @Bathsheba A good question. The ternary operations are as well NOT allowed. The "trick" here, I guess, is to use bit wise manipulations.Thanks for pointing that out. – Guy Avraham Feb 18 '17 at 09:39
  • 1
    My intuition would be to use bit interleaving: http://stackoverflow.com/questions/3203764/bit-twiddling-hacks-interleave-bits-the-obvious-way – gary Feb 22 '17 at 08:00
  • Assuming the mathematical definition of integer, here's a solution: `x*x + y*y + 1`. I understand this could overflow with C's int data type. – Colonel Panic Feb 23 '17 at 11:47

2 Answers2

4

Converting my comments to an answer:

What you have is ~(x ^ y ^ y), which is just ~x, so it doesn’t work if y = ~x. One option instead is to make a number that’s different from x1 in the twos position and different from x2 in the ones position:

return ~(x1 & 2 | x2 & 1);

(Simplification from (~x1 & 2) | (~x2 & 1) credit to @chux. Thanks!)

Ry-
  • 218,210
  • 55
  • 464
  • 476
3

Being pedantic, since they said no if keyword then ternaries should be fair game...

return (x1+1 == x2) ? x1+2 : x1+1;

Of course, maybe that's cheating. No problem, here's a ternary-free version:

return x1+1+(x1+1==x2);

And don't worry, if you think the conditional is still cheating, there are many ways to implement it with straight bit manipulation.

Note that the addition solution is really only valid for unsigned integers, since it induces the potential for signed overflow (which is UB). If this is a concern, you can replace the addition with another operation (for example, x1^(1+(x1^1==x2)).

Community
  • 1
  • 1
nneonneo
  • 171,345
  • 36
  • 312
  • 383
  • 1
    You are peeking at the flags register with `==`, which is an implicit `if`. – Paul Ogilvie Feb 18 '17 at 09:21
  • 1
    @PaulOgilvie that makes no sense – M.M Feb 18 '17 at 09:24
  • M-m, I don't get you. Any if statement must use the flags register to get the result of a condition, be it the zero flag, the carry flag or whatever flag. So vice versa, any usage of the flags register implies an if. The expression `x1+1==x2` uses the zero flag in testing for equality. – Paul Ogilvie Feb 18 '17 at 09:30
  • 1
    Naughty since this emits the potential for integer overflow. – Bathsheba Feb 18 '17 at 09:35
  • @PaulOgilvie "any usage of the flags register implies an if" --> the carry flag may be an exception, else a wide addition implies an `if`. – chux - Reinstate Monica Feb 18 '17 at 09:46
  • 1
    @PaulOgilvie There is no "flags register" in C. Your point is irrelevant. – EOF Feb 18 '17 at 11:21
  • @EOF, seems to me C runs on a machine. Machine has flags register. Know a language that does not run on a machine? Or a machine that has no flags register? As long as programming languages are translated to machine code, they use the flags register. – Paul Ogilvie Feb 18 '17 at 11:35
  • @PaulOgilvie `MIPS` and `ALPHA` ISAs do not have integer flag registers. On ARM32 and POWER, gcc will compile `a == b` to a "count leading zeroes" instruction (if available on the microarchitecture) rather than test flags. Finally, I can envision a processor architecture where *any* proposed code for relating `a` and `b` for `int a,b` involves a conditional jump (namely an eight-bit architecture without `add/sub-with-carry`). Point is, you can't restrict C-syntax based on implementation details. – EOF Feb 18 '17 at 11:43
  • @EOF, thanks for the examples. So, for the question at hand, "not using `if`" can then only mean "not using `if`" (syntactically). – Paul Ogilvie Feb 18 '17 at 12:05
  • 1
    Bathsheba: correct, this only works for unsigned integers. (I was planning to add it to the answer but neglected to actually do so). This has been fixed. – nneonneo Feb 22 '17 at 02:46