No Ifs, Ands, or Elses: Swap Numbers Brain Teaser
Somebody recently explained to me a brain teaser they were given during an interview:
Should interviewers be asking brain teasers like this? Perhaps not. People don’t always do their most lateral thinking during interviews they may see as high pressure.
For the purposes of this article, who cares! Brain teasers are fun, so let’s see how we can solve this one.
First, let’s start off with the obvious implementation that isn’t allowed (since it uses an if statement):
function swap(n) { if (n == 5) { return 7; } return 5; }
Now we just need to do that a dozen or so times without the use of an if statement. These are the solutions some others came up with (consider these to be pseudo-code):
Group Solutions
Group Solution 1: XOR
function swap(n) { // XOR to toggle the second bit. return xor(n, 2); }
Group Solution 2: Array Lookup
function swap(n) { return [7, 0, 5][n - 5]; }
Group Solution 3: Substring
function swap(n) { return parse("705".charAt(n - 5)); }
Group Solution 4: Negative Distance
function swap(n) { return 12 - n; }
Group Solution 5: Division
function swap(n) { return 35 / n; }
Group Solution 6: Dictionary / Hashmap
function swap(n) { return {5: 7: 7: 5}[n]; }
Group Solution 7: Modulus
function swap(n) { return 7 - (n % 5); // Or: return (7 % n) + 5; }
My Solutions
Whew, that was a lot of ideas. But we can go even further. Here are some ideas I had:
My Solution 8: Ternary
function swap(n) { return n == 5 ? 7 : 5; }
My Solution 9: Switch
function swap(n) { switch (n) { case 5: return 7; default: return 5; } }
My Solution 10: Try Catch
function swap(n) { try { const x = 1 / (n - 5); } catch { return 7; } return 5; }
My Solution 11: Pivot Around Zero
function swap(n) { // This equation reduces to the same // formula as the 4th solution. return -(n - 6) + 6; }
My Solution 12: Digits of Pi
function swap(n) { // Remember, this is pseudo-code, // so we'll assume this function exists. return DigitOfPi(156 + n); }
My Solution 13: Missing Side of Triangle
function swap(n) { // a^2 + b^2 = c^2 return sqrt(74 - n * n); }
My Solution 14: Threads
function swap(n) { thread1 = new Thread(() => { Thread.Sleep(5); r = 7; }); thread2 = new Thread(() => { Thread.Sleep(7); r = 5; }); thread1.Start(); thread2.Start(); Thread.Sleep(n + 1); return r; }
My Solution 15: Sine Wave
function swap(n) { // I don't feel like figuring out the constants. return a * sin(n * b + c) + d; }
My Solution 16: Code Generation
function swap(n) { const Get5 = () => 7; const Get7 = () => 5; return eval("Get" + n + "()"); }
My Solution 17: While Loop
function swap(n) { while (n == 5) { return 7; } return 5; }
My Solution 18: For Loop
function swap(n) { for (let i = 6; i < n;) { return 5; } return 7; }
My Solution 19: Filter Values
function swap(n) { return [5, 7].First(x => x != n); }
My Solution 20: Count Pixels
function swap(n) { // The "5" would take up more pixels than "7". const canvas = new Canvas(4, 4); return CountPixels(DrawText( n.ToString(), canvas)); }
Solution 21: Count Intersections
function swap(n) { // The diagonal line cross "5" 3 times // and "7" 1 time. const degrees = 45; return 4 + CountIntersections(degrees, DrawText(n.ToString())); }
Solution 22: Factorial String Length
function swap(n) { return (factorial(n).ToString().Length - 3.5) * -2 + 6; }
Solution 23: Bit Masking
function swap(n) { return 7 - (n & 2); }
Summary of Techniques
That seems like a lot of solutions, but there are just a few techniques used:
Bit Manipulation. This involves noting that there is a similarity or difference in particular bits of each number. In particular, the second least significant bit (2, aka 0x00000010).
Used by these solutions: XOR, Bit Masking
Collection Lookups. This involves using the number as a key/index to find the corresponding number in a collection.
Used by: Array Lookup, Substring, Dictionary / Hashmap
Math Equations. This involves finding a numeric equation that converts each number into its counterpart.
Used by: Negative Distance, Division, Modulus, Pivot Around Zero, Missing Side of Triangle, Sine Wave
Control Flow Statements. These are really if statements in disguise. They allow you to use a statement to conditionally change the flow of code.
Used by: Ternary, Switch, Try Catch, While Loop, For Loop
Timing. This uses some element of time to determine the outcome. This is essentially a very specialized control flow statement (a very inefficient one).
Used by: Threads
Code Generation. This is another very specialized control flow statement. We’re using string manipulation to determine the code we want to execute.
Used by: Code Generation
Filtering. This is akin to a collection lookup, but it’s not exactly using an index or key. Instead, the values are the focus, and equality is used to determine the output.
Used by: Filter Values
Visual. These rely on some aspect of the input that can be represented visually (e.g., as pixels). These are some of the least straightforward solutions, as they rely on a specific representation of a number (even particular fonts and formatting could impact these).
Used by: Count Pixels, Count Intersections
Composite Solutions. These are really combining several other techniques into one. For example, the digits of pi is a combination of math equations and collection lookups (since pi is essentially a collection of digits).
Used by: Digits of Pi, Factorial String Length
Not bad! We came up with 9 unique types of solutions. If you really want a challenge, try to think of even more!
(And I really hope interviewers are not using this sort of question during an interview.)