views:

123

answers:

6

I have six boolean flags that are independent of each other so there are 64 possible combinations. These flags should determine the value of some string. This string can have seven different values. I think implementing this as a large if-statement is a bad idea so I thought of creating a truth table where each combination determines a specific outcome:

Key            Value
0,0,0,0,0,0 -> "A"
0,0,0,0,0,1 -> "A"
0,0,0,0,1,0 -> "B"
0,0,0,0,1,1 -> "C"
0,0,0,1,0,0 -> "A"
...

This looks remarkably like a dictionary but what would be the best key implementation (in C#)? The smallest possible key would be a byte that I mask the options into. However, this wouldn't improve the readability of my code.

Are there other solutions for this?

+1  A: 

The simplest way:

struct KeyThing
{
  public int a,b,c,d,e,f;
}

The preferred way would be using bitmasks.

leppie
Do you mean `public bool a,b,c,d,e,f`?
Ronald Wildenberg
@Ronald Wildenberg: `bool` could work too.
leppie
+6  A: 

You could represent the 6 bool options as an enum with the FlagsAttribute, and rely on the readability of your enum names.

Edit, for example:

[Flags]
enum MyFlagSet : byte
{
    NoFlags = 0,
    Flag1 = 1 << 0,
    Flag2 = 1 << 1,
    Flag3 = 1 << 2,
    Flag4 = 1 << 3,
    Flag5 = 1 << 4,
    Flag6 = 1 << 5
};

Dictionary MyDictionary = new Dictionary<MyFlagSet, string>()
                          {
                              {MyFlagSet.NoFlags, "Q"},
                              {MyFlagSet.Flag1 | MyFlagSet.Flag2, "A"},
                              {MyFlagSet.Flag3 | MyFlagSet.Flag5 | MyFlagSet.Flag6, "B"}
                          };
luke
Pfew, 64 meaningful names. I already find it difficult to come up with one. If I choose this option, I would still have a problem determining the correct key based on the values of each of the six flags. Unless I assign each flag an int from `1,2,4,8,16,32` and OR them together. This brings me very close to using `byte` or `int` as a key.
Ronald Wildenberg
@Ronald Wildenberg - The powers-of-two-ORed-together option is exactly what the FlagsAttribute is intended to convey. So you would only need six named values rather than 64.
Jeffrey L Whitledge
@Jeffrey - You're right, my mistake. You don't need to think up 64 names. Thanks.
Ronald Wildenberg
If all 64 possibilities will have an associated string, you can also directly cast the enum to an int and simply store the strings in an array. Even if not all 64 possibilities will have names, an array is a good option, with a sentinel value (say, null) indicating that the key isn't mapped. Clear intent is generally more important than performance, but an array lookup is just as clean in my mind (and more concise) than a Dictionary implementation.
Dan Bryant
@Dan - Thanks, that's a useful suggestion. Since the keys are integers from 0 to 63, an array may be a better choice than a Dictionary.
Ronald Wildenberg
A: 

You could create an enum with the FlagsAttribute, which may make your code easier to read, but you will have to make up 64 names!

ShellShock
The FlagsAttribute approach only requires 6 names (or 7, if you want to include no flags set, 0).
luke
A: 

Use a bitmask to create a int and store your values in a regular hash?

ie:
0,0,0,0,0,0 = 0
0,0,0,0,0,1 = 1
0,0,0,0,1,0 = 2

and then hash[0] = "a" and so on

Fredrik Leijon
A: 

If you encapuslate the six-booleans-to-string function into a separate class, then the readability of the code becomes trivially improved regardless of the implementation details. And the implementation can change based on performance needs that arise.

(I am going to make up a name to illustrate.)

public static class RobotEmotionDescriptions
{
    public static string GetDescription(bool isHurting, bool isAwake, 
           bool isBrightlyLit, bool isInQuitePlace, bool isPlayingChess, 
           bool isTumpedOver)
    {
        ... // Details don’t matter.
    }
}

So I think the bitmapped byte would be an excellent first-pass to an implementation.

Jeffrey L Whitledge
A: 

You could represent your bool options as strings, e.g.
“011011”
then just use a Dictionary

(this may be a good option if you wish to let the user change the mappings, as reading strings from a file is easy)

However if you will be using them much, use a flags enum as per Luke’s answer.

Ian Ringrose