-1

I have a bunch of variables that can essentially be represented by 4 bits. Where it would be something like:

0000 1100 0110 1010

and so on. Now I have to take 2 of these and combine them in some unique way to get an output. Example:

If I have 0000 and 1100 (1100 and 0000 would be the same), I want to get some unique decimal or binary and later on I can simply have a select statement to return what I want.

I'd rather not have a ton of statements if possible. Like:

if (a = 0000 and b = 0000) or (a = 0000 and b = 0000)
if (a = 0000 and b = 0001) or (a = 0001 and b = 0000)
if (a = 0000 and b = 0011) or (a = 0011 and b = 0000)
if (a = 0000 and b = 0111) or (a = 0111 and b = 0000)
if (a = 0000 and b = 1111) or (a = 1111 and b = 0000)
if (a = 0000 and b = 0010) or (a = 0010 and b = 0000)
if (a = 0000 and b = 0110) or (a = 0110 and b = 0000)
if (a = 0000 and b = 1110) or (a = 1110 and b = 0000)
if (a = 0000 and b = 0100) or (a = 0100 and b = 0000)
if (a = 0000 and b = 1100) or (a = 1100 and b = 0000)
if (a = 0000 and b = 1000) or (a = 1000 and b = 0000)
if (a = 0000 and b = 1010) or (a = 1010 and b = 0000)
if (a = 0000 and b = 0101) or (a = 0101 and b = 0000)
if (a = 0000 and b = 1001) or (a = 1001 and b = 0000)
if (a = 0000 and b = 1011) or (a = 1011 and b = 0000)

....

if (a = 1010 and b = 0000) or (a = 0000 and b = 1010)
if (a = 1010 and b = 0001) or (a = 0001 and b = 1010)
if (a = 1010 and b = 0011) or (a = 0011 and b = 1010)
if (a = 1010 and b = 0111) or (a = 0111 and b = 1010)
if (a = 1010 and b = 1111) or (a = 1111 and b = 1010)
if (a = 1010 and b = 0010) or (a = 0010 and b = 1010)
if (a = 1010 and b = 0110) or (a = 0110 and b = 1010)
if (a = 1010 and b = 1110) or (a = 1110 and b = 1010)
if (a = 1010 and b = 0100) or (a = 0100 and b = 1010)
if (a = 1010 and b = 1100) or (a = 1100 and b = 1010)
if (a = 1010 and b = 1000) or (a = 1000 and b = 1010)
if (a = 1010 and b = 1010) or (a = 1010 and b = 1010)
if (a = 1010 and b = 0101) or (a = 0101 and b = 1010)
if (a = 1010 and b = 1001) or (a = 1001 and b = 1010)
if (a = 1010 and b = 1011) or (a = 1011 and b = 1010)

....

if (a = 1111 and b = 0000) or (a = 0000 and b = 1111)
if (a = 1111 and b = 0001) or (a = 0001 and b = 1111)
if (a = 1111 and b = 0011) or (a = 0011 and b = 1111)
if (a = 1111 and b = 0111) or (a = 0111 and b = 1111)
if (a = 1111 and b = 1111) or (a = 1111 and b = 1111)
if (a = 1111 and b = 0010) or (a = 0010 and b = 0000)
if (a = 1111 and b = 0110) or (a = 0110 and b = 0000)
if (a = 1111 and b = 1110) or (a = 1110 and b = 0000)
if (a = 1111 and b = 0100) or (a = 0100 and b = 1111)
if (a = 1111 and b = 1100) or (a = 1100 and b = 1111)
if (a = 1111 and b = 1000) or (a = 1000 and b = 1111)
if (a = 1111 and b = 1010) or (a = 1010 and b = 1111)
if (a = 1111 and b = 0101) or (a = 0101 and b = 1111)
if (a = 1111 and b = 1001) or (a = 1001 and b = 1111)
if (a = 1111 and b = 1011) or (a = 1011 and b = 1111)

Any ideas?

Matt
  • 7,049
  • 7
  • 50
  • 77
  • Why not save all these four representation in an array and then make an recursive call over it ? – zenwraight Sep 18 '17 at 00:28
  • To get all the combinations – zenwraight Sep 18 '17 at 00:28
  • @zenwraight essentially, the output is somewhat random. For, example...If a = 1111 and b = 1111 it could be 10 and then maybe a = 0000 and b = 0000 could also be 10. I just kinda want a way to reduce it down to at least get a unique value for ( a and b) and ( b and a), this will at least bring down the number of if statements at least. Right now theres 256. It would bring it down to about 70 just because of duplicate outputs. Not sure if they makes sense.... – Matt Sep 18 '17 at 00:39
  • @zenwraight In a way, I'm trying to say if (a = 1100 and b = 1111) or (a = 1111 and b = 1100) would be 28, but (a = 1110 and b = 1111) or (a = 1111 and b = 1110) would be 29. Basically some arithmetic that would make it unique based off the 256 different combos, but the same when reversed. – Matt Sep 18 '17 at 00:44

2 Answers2

2

Create an array of the 70 output values, and a 2D array of the output index associated with each combination of a and b, like this:

output = [10,20,7,11...]          // 70 values
combis = [[1,5,68,4,5,5,2,50...],
          [5,45,69,24,5,3,14...],
          ...
          [26,1,26,2,65,23,1...]] // 16x16 indexes
return output[combis[a][b]]

This keeps the output values seperate from the combinations which lead to certain output, and may be more logical and easier to maintain.

You can list 16x16 indexes with duplicates for a:b and b:a, or have a triangular 2D array and switch a and b if b is greater than a:

output = [10,20,7,11...]          // 70 values
combis = [[1],
          [2,45],
          [6,14,2],
          ...
          [26,1,26,2,65,23,1...]] // 1+2+3+...+16 indexes
if (b > a) return output[combis[b][a]]
else return output[combis[a][b]]

Depending on the language you use, the size of the lookup tables may have a significant effect on the speed of the algorithm. While writing the JavaScript code example for this answer I found that one lookup in a large table was much slower than a two-lookup method using smaller tables, with an unexpected threshold around 200 elements. So if speed is important, you should probably code several versions, e.g. with a flat array instead of a 2D array, and compare their speed.

1

You could build an operator table and use a and b to index it:

result = functors[a][b](a, b);

If the operators are commutative, you'd only have to set up 16*16/2 functors if you order a and b before doing the call:

result = (a < b ? functors[a][b](a, b) : functors[b][a](a, b));
yacc
  • 2,915
  • 4
  • 19
  • 33