Detect -1 without using a conditional statement

Viewed 623

Hi I have been asked this question at school. I can't seem to figure it out.

Write a c program without using any conditional statement (if/else/switch:case/while/for etc.) which outputs :
1535(integer) if input is -1(integer)
else it outputs the input(if not -1)?

Question is suppose to assess my logical skills rather than c programming skills.

4 Answers

Considering:

(question is suppose to assess my logical skills rather than c programming skills)

I assume that language-lawyering like "ternary operators are not a conditional statement" to be against the spirit of the question. So let's tackle this from a completely branchless point of view.

This intuitively feels to me like a job for multiplication, since the "0 swallows everything" and "1 leads to a no-op" properties of the operation would allow us to manage different "paths" at the same time.

In other words, if we had a magic function f() for which f(0) == 1 and f(anything else) == 0, then we could leverage the fact that x * 0 == 0 and x * 1 == x to "combine" both possible answers:

int answer(int v) {
  int f_result = f(v + 1); // Offset the -1 to 0, which becomes 1, anything else becomes 0
  int f_inv = f(f_result); // 1 becomes 0, 0 becomes 1

  return 
     v * f_inv + 
     1535 * f_result;
}

So, all we need now is a f() that returns a 1 for 0, and 0 for anything else.

It's simply the ! unary operator: int f(int v) { return !v; }

I can suggest the following approach

#include <stdio.h>

int main(void) 
{
    const int DEFAULT_VALUE = 1535;
    
    printf( "Enter any number or -1: " );
    
    int n = -1;
    
    scanf( "%d", &n );
    
    printf( "%d\n", ( n == -1 ) * DEFAULT_VALUE + ( n != -1 ) * n );
    
    return 0;
}

The program output might look like

Enter any number or -1: -1
1535

or for example

Enter any number or -1: 10
10

The key statement of the program is the following

printf( "%d\n", ( n == -1 ) * DEFAULT_VALUE + ( n != -1 ) * n );

Logical operators at rescue!

int f(int v)
{
    /*We can detect v=-1 just adding one. Next we compare it with -1 */
    /*boolean contains "1" or "0" */
    bool val= !(-1 && (v+1)); /*=1 for v=-1 */

    /*Finally we operate for both results of val */
    int res =  ((int) val) * 1535 + (int)(!val)*v;

    return res;   
 }
  1. Bitwise NOT transforms (111...1) to (000...0) for -1 (and anything else will be nonzero)
  2. Logical NOT transforms (000....0) to 1 (and anything else to 0)
  3. Multiply by 1535

Here's a full C program that tests all integers:

#include <stdio.h>
#include <limits.h>

int result(int value)
{
    return (!(~value))*1535;
}

void check(int input, int expected)
{
    if (result(input) != expected)
        printf("Result was %d for input %d (expected: %d)\n", result(input), input, expected);
}

int main()
{
    for (int i = INT_MIN; i > -1; ++i)
        check(i, 0);
    for (int i = 0; i < INT_MAX; ++i)
        check(i, 0);

    check(INT_MAX, 0);
    check(-1, 1535);
}

Live Demo


Bonus C++ demo (since the question was originally tagged as such):

Related