如何有效地检测4个整数变量的对称性?

时间:2017-03-13 09:50:29

标签: c++ c performance integer symmetry

我想在4个整数变量i,j,kl中找到对称性。 对称性是:

  1. 所有四个数字相等:XXXX,
  2. 三个数字相等:XXXY,XXYX,XYXX,YXXX
  3. 两对相等的数字:XXYY,XYXY,XYYX,......
  4. 一对相等数字和两个不同数字:XXYZ,XYXZ,XYZX,......
  5. 所有数字都不同。
  6. 所有变量都在某个非连续范围内运行。我使用嵌套的if else语句。第一个if检查所有变量的不等式。如果没有,那么我有案例1.下一个if检查是否有任何相等的对。如果没有,那么情况5.下一个if检查三个相等的数字。如果为真,则为情况2.否则,最后一个if检查两对相等的数字。如果是,则为案例3,否则为案例4.

      if(!(i==j && j==k && k==l)){
        if(i==j || i==k || i==l || j==k || j==l || k==l){
         if((i==j && j==k) || (i==j && j==l) || (i==k && k==l) || (j==k && k==l)){            ...//do something
         }else{
        if((i==j && k==l) || (i==k && j==l) || (i==l && j==k)){ 
    ...//do something
        }else{
         ...//do something
        }           
      }
         }else{
         ...//do something  
         } 
     }else{
      ...//do something
     }  
    

    这样做有更好的方法吗?我的意思是更好的表现,因为我必须进行数百万次的测试。

3 个答案:

答案 0 :(得分:9)

与samgak类似的想法,但不需要外部表。只计算所有比赛的总和

int count = (i==j) + (i==k) + (i==l) + (j==k) + (j==l) + (k==l);

switch做以下选择

switch (count){
case 0: //All differenct
case 1: //One same
case 2: //Two different pairs
case 3: //Three same
case 6: //All are same
}

同样,如前所述,在某些情况下,您当前的代码可能会更快。特别是如果最常见的情况是所有元素相等的情况。

答案 1 :(得分:5)

如果你能买得起一个小的(64字节)查找表,你可以测试每对值,并为你用作表格索引的数字中的每个比较设置一个位,例如:

int classifySymmetries(int i, int j, int k, int l)
{
     return table[(i == j) |
                  ((i == k) << 1) |
                  ((i == l) << 2) |
                  ((j == k) << 3) |
                  ((j == l) << 4) |
                  ((k == l) << 5)];
}

然后切换返回值。您可以使用现有代码生成表,通过替换每个比较的位测试,或生成满足0到63的每个位模式的虚拟i j k l值。

这种方法需要不断进行6次比较。请记住,排序4个值需要4到5个比较(有4个!= 24个可能的排序,每个比较产生1位信息)。但是你必须根据排序值进行测试。

使用查找表是否胜过当前方法将取决于值的分布以及内存访问时间等其他因素,您应该进行分析以确认。

答案 2 :(得分:0)

更好的方法是使用地图:

#include <iostream>
#include <map>
using namespace std;


int main()
{
    int i, j, k, l;
    cin >> i >> j >> k >> l;

    std::map<int, int> count;

    int outcomes[5] = { 0, 0, 0, 0, 0 };

    // Store the values in the map
    count[i]++;
    count[j]++;
    count[k]++;
    count[l]++;

    // tally types of outcome according to the map
    for(typename std::map<int, int>::iterator iter = count.begin(); iter != count.end(); ++iter)
    {
        outcomes[iter->second] ++;
    }

    // print out "1 of a kind" count, up to "4 of a kind"
    // this is just for visualization
    for (int i = 1; i <= 4; ++i)
    {
        cout << i << " of a kind = " << outcomes[i] << endl;
    }

    // your bit here, it checks on just the "outcomes" array
    if(outcomes[4] > 0) // 4 of a kind
    {
    }
    else if(outcomes[3] > 0) // 3 of a kind
    {
    }
    else if(outcomes[2] > 1) // two pair
    {
    }
    else if(outcomes[2] > 0) // one pair
    {
    }
    else // singles only
    {
    }

    cin.ignore();
    cin.get();

    return 0;
}

如果你想将它扩展到超过4种选择,这种方法也会更具扩展性。