Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to simplify/optimize a piece of code that looks at combinations of conditions?

I have a piece of code that I want to optimize for readability and performance and coolness. Right now I have this ugly looking thing:

if      ( cond1 &&  cond2 &&  cond3 && !cond4)
{
     // do something 
}
else if ( cond1 &&  cond2 && !cond3 &&  cond4)
{
    // do something 
}
else if ( cond1 && !cond2 &&  cond3 &&  cond4)
{
   // do something 
}
else if (!cond1 &&  cond2 &&  cond3 &&  cond4)
{
    // do something 
}
else
{
    // do something 
}

where cond1, cond2, cond3 and cond4 are booleans that have been initialized prior to the block of code above. I want to make this faster, less ugly and more cool.

I'm thinking about doing this:

int val = (cond1 ? 0 : 1) + 2 * (cond2 ? 0 : 1) + 4 * (cond3 ? 0 : 1) + 8 * (cond4 ? 0 : 1);
if (val == 8)
{
    // do something
}
else if (val == 4)
{
    // do something 
}
else if (val == 2)
{
    // do something
}
else if (val == 1)
{
    // do something
}
else
{
    // do something 
}

Does that work or are there flaws? Is there a better way? What is the typical way of achieving the desired result when looking through different combinations of multiple conditions?

like image 966
user3537336 Avatar asked Apr 18 '14 21:04

user3537336


People also ask

How do you optimize your code?

Optimize Program Algorithm For any code, you should always allocate some time to think the right algorithm to use. So, the first task is to select and improve the algorithm which will be frequently used in the code. 2. Avoid Type Conversion Whenever possible, plan to use the same type of variables for processing.

What is optimize code in Visual Studio?

You set the Optimize option from Build properties page for your project in Visual Studio. Optimize also tells the common language runtime to optimize code at run time. By default, optimizations are disabled. Specify Optimize+ to enable optimizations.

What do you mean by code optimization?

Definition and Properties Code optimization is any method of code modification to improve code quality and efficiency. A program may be optimized so that it becomes a smaller size, consumes less memory, executes more rapidly, or performs fewer input/output operations.


1 Answers

One way or another you want to get your values into bit flags. That is you want a bit set or not in an integer type for every condition. Then every 4-bit value in your case represents one of your above ANDed conditions. After that, you can use a switch statement. It's arguably more readable, and the compiler can often optimize it into a jump table. That is, it will just offset your program counter by some value in a lookup table or something of the sort, and you no longer need to check every combination of values. In this way your checking for ANDed cases becomes constant time rather than linear, that is if you added 4 more flags and there were now 256 combinations rather than 16 than this method would be just as fast in a big-oh way. Alternatively, if you don't trust the compiler to make the switch statement a jump table you can do it yourself using the flags value as an index to an array of function pointers. It's also probably worth noting that the ORed enum case values are folded or pre-computed at compile-time.

  enum {
    C1 = 0x1,
    C2 = 0x2,
    C3 = 0x4,
    C4 = 0x8
  };

  unsigned flags = 0;
  flags |= cond1 ? C1 : 0x0;
  flags |= cond2 ? C2 : 0x0;
  flags |= cond3 ? C3 : 0x0;
  flags |= cond4 ? C4 : 0x0;

  switch (flags) {
    case 0: // !cond1 && !cond2 && !cond3 && !cond4
      // do something
      break;
    case C1: //  cond1 && !cond2 && !cond3 && !cond4
      // do something
      break;
    case C2: // !cond1 &&  cond2 && !cond3 && !cond4
      // do something
      break;
    case C1 | C2: //  cond1 &&  cond2 && !cond3 && !cond4
      // do something
      break;
    case C3: // !cond1 && !cond2 &&  cond3 && !cond4
      // do something
      break;
    case C1 | C3: //  cond1 && !cond2 &&  cond3 && !cond4
      // do something
      break;
    case C2 | C3: // !cond1 &&  cond2 &&  cond3 && !cond4
      // do something
      break;
    case C1 | C2 | C3: //  cond1 &&  cond2 &&  cond3 && !cond4
      // do something
      break;
    case C4: // !cond1 && !cond2 && !cond3 &&  cond4
      // do something
      break;
    case C1 | C4: //  cond1 && !cond2 && !cond3 &&  cond4
      // do something
      break;
    case C2 | C4: // !cond1 &&  cond2 && !cond3 &&  cond4
      // do something
      break;
    case C1 | C2 | C4: //  cond1 &&  cond2 && !cond3 &&  cond4
      // do something
      break;
    case C3 | C4: // !cond1 && !cond2 &&  cond3 &&  cond4
      // do something
      break;
    case C1 | C3 | C4: //  cond1 && !cond2 &&  cond3 &&  cond4
      // do something
      break;
    case C2 | C3 | C4: // !cond1 &&  cond2 &&  cond3 &&  cond4
      // do something
      break;
    case C1 | C2 | C3 | C4: //  cond1 &&  cond2 &&  cond3 &&  cond4
      ; // do something
  };

Also, this covers all the combinations. If you just need some subset feel free to remove some of the cases. The compiler is very good at optimizing switch statements. It's probably faster than any clever special-case arithmetic trick you could roll yourself.

  enum {
    C1 = 0x1,
    C2 = 0x2,
    C3 = 0x4,
    C4 = 0x8
  };

  unsigned flags = 0;
  flags |= cond1 ? C1 : 0x0;
  flags |= cond2 ? C2 : 0x0;
  flags |= cond3 ? C3 : 0x0;
  flags |= cond4 ? C4 : 0x0;

  switch (flags) {
    case C1 | C2 | C3: //  cond1 &&  cond2 &&  cond3 && !cond4
      // do something
      break;
    case C1 | C2 | C4: //  cond1 &&  cond2 && !cond3 &&  cond4
      // do something
      break;
    case C1 | C3 | C4: //  cond1 && !cond2 &&  cond3 &&  cond4
      // do something
      break;
    case C2 | C3 | C4: // !cond1 &&  cond2 &&  cond3 &&  cond4
      // do something
      break;
    default:
      // do something
      ;
  };
like image 113
Apriori Avatar answered Nov 13 '22 05:11

Apriori