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

How to detect symmetries in 4 integer variables efficiently?

本文关键字:对称 变量 整数 有效地 检测 4个      更新时间:2023-10-16

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

  1. 所有四个数字都是相等的:xxxx,
  2. 三个数字相等:xxxy,xxyx,xyxx,yxxx
  3. 两对相等的数字:xxyy,xyxy,xyyx,...
  4. 一对相等的数字和两个不同的数字:xxyz,xyxz,xyzx,...
  5. 所有数字都是不同的。

所有变量在某个非连续范围内运行。如果其他语句,我使用嵌套。第一个如果检查所有变量的不等式。如果没有,则我有案例1。下一个检查是否有任何相等的对。如果不是,则为案例5。下一个如果检查三个相等的数字。如果为true,则为情况2。否则,最后一个如果检查两对相等的数字。如果为true,则为案例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
 }  

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

与samgak相似的想法,但无需外部表。只需计算所有匹配的总和

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

和DO 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
}

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

如果您负担得起一个小(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位信息)。但是然后,您必须根据其上排序的值进行测试。

是否使用查找表击败您当前的方法是否取决于值的分布和其他因素(例如内存访问时间),您应该介绍以确认。

一种更好的方法是使用地图:

#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个选择之外,则这种方法也将更加可扩展。