A MinMax problem without terms and conditions

Posted by StuffonmyMind on September 25, 2021

Found a really interesting problem on Codewars today ! Gonna discuss the solution

You got two numbers and you have to find either the Min or the Max of that number depending on the symbol < or > you got as input BUT you have to do this without if / ?: / switch / while / for which is basically everything conditional

In the end you have a function that goes like this

solve(2, 1, '>') => 2
solve(2, 1, '<') => 1

Now we have two conditions that we have to resolve without using conditional statements or Irony

  • Is a > b or vice versa
  • Should I calculate Min or Max depending on < or >

We can solve the first problem using Bitshift and the fact that integers are of 32 bits

1
2
// if a > b 0 else -1
int value = (a-b) >> 31;

If a > b then a-b would be positive which would make the value 0 whereas the diff being negative would make the value -1 while telling us that actually b > a

We the solve the second we gonna to look at how the symbols in ASCII

1
2
3
60 -  <
61 -  =
62 -  >

There is an = symbol between < & > so to mimic a - b we just gotta the passed ascii symbol with = and do some math mumbo jumbo to make sure that > gives 0 & < gives -1.

The math basically makes sure that 1 returned for > gets converted to 0 and -1 remains the same

1
2
// if `>` 0 else -1
int operation = (symbol - '=' - 1) / 2

Now all that is left is to combine these conditions into a mega condition

  • If a > b and Symbol = > then return A (0, 0) Or Vice versa (-1, -1)
  • If a > b and Symbol = < then return B (0, -1) Or vice versa (-1, 0)

Which is actually just an XOR gate where we just produce a 0 when both inputs match else it’s 1, now to convert this boolean into our actual MinMax result we convert our inputs to a List and treat our bool as the Index

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Puzzle {
    public static int solve(int a, int b, char symbol) {
        /*
        Since integers are 32 bits
        Doing an Right Bit Shift by 31
            - Negative values -> -1 
            - Positive values -> 0
        */
        // if a > b 0 else -1
        int value = (a-b) >> 31;
        // if `>` 0 else -1
        int operation = (c - '=' - 1) / 2 ;
        // if a > b and ` >` return a else b
        int index = (value ^ operation) * -1;
        // Expression that gives us 0 or 1 to pick a or b.
        return new int[]{a, b}[index];
    }
}

Neat !

There’s a whole lot more on https://www.codewars.com/kata/61211f9d27e72200567dfd3d/solutions/java

1
2
3
4
5
public class Puzzle {
  public static int solve(int a, int b, char symbol) {
    return a + (b - a & (b - a ^ symbol << 30) >> 31);
  }
}