【问题标题】:creating 3 pairs made from +6 objects where each pair has unique & unrepeated objects创建由 +6 个对象组成的 3 对,其中每对具有唯一且不重复的对象
【发布时间】:2020-10-27 04:06:47
【问题描述】:

我有一个长度可能为 6 或更多(+6 光子/伽马)的可能对象列表,我需要从该列表中制作 3 对(3 个π介子)。这些对都需要具有唯一的对象,并且一旦成对,任何伽玛都不能重复使用。

例如如果 pion1 由 gamma1(在代码中:ig1)和 gamma2 (ig2) 制成,则 pions2 和 pions3 必须由 gammas3、4、5、6 等的所有可能组合制成(可能超过 6伽马,但我只关心总共 3 个π介子),等等。

我尝试按以下方式执行下几个 for 循环:

int n_g = 8; // n_g >= 6
boolean hasDVPi0P = false;
for (int ig1 = 0; ig1 < n_g-5 && !hasDVPi0P ; ig1++) {
    for (int ig2 = ig1+1; ig2 < n_g-4 && !hasDVPi0P ; ig2++) {
        for (int ig3 = ig2+1; ig3 < n_g-3 && !hasDVPi0P ; ig3++) {
            for (int ig4 = ig3+1; ig4 < n_g-2 && !hasDVPi0P ; ig4++) {
                for (int ig5 = ig4+1; ig5 < n_g-1 && !hasDVPi0P ; ig5++) {
                    for (int ig6 = ig5+1; ig6 < n_g && !hasDVPi0P ; ig6++) {
                        System.out.println("(" + ig1 + "," + ig2 + ") , (" + ig3 + "," + ig4 + ") , (" + ig5 + "," + ig6 + ")");
                        }
                    }
                }
        }
    }
}  

这让我得到以下输出:

(0,1) , (2,3) , (4,5)
(0,1) , (2,3) , (4,6)
(0,1) , (2,3) , (4,7)
(0,1) , (2,3) , (5,6)
(0,1) , (2,3) , (5,7)
(0,1) , (2,3) , (6,7)
(0,1) , (2,4) , (5,6)
(0,1) , (2,4) , (5,7)
(0,1) , (2,4) , (6,7)
(0,1) , (2,5) , (6,7)
(0,1) , (3,4) , (5,6)
(0,1) , (3,4) , (5,7)
(0,1) , (3,4) , (6,7)
(0,1) , (3,5) , (6,7)
(0,1) , (4,5) , (6,7)
(0,2) , (3,4) , (5,6)
(0,2) , (3,4) , (5,7)
(0,2) , (3,4) , (6,7)
(0,2) , (3,5) , (6,7)
(0,2) , (4,5) , (6,7)
(0,3) , (4,5) , (6,7)
(1,2) , (3,4) , (5,6)
(1,2) , (3,4) , (5,7)
(1,2) , (3,4) , (6,7)
(1,2) , (3,5) , (6,7)
(1,2) , (4,5) , (6,7)
(1,3) , (4,5) , (6,7)
(2,3) , (4,5) , (6,7)

最初认为是正确的直到我检查了 n_g=6,这让我明白了

(0,1) , (2,3) , (4,5)

这显然是错误的输出。我尝试通过以下方式找到 6 gamma 的所有唯一可能对:

n_g=6;
for(int ig1 = 0; ig1 < n_g-1; ig1++) {
    for(int ig2 = ig1+1; ig2 < n_g; ig2++) {
        System.out.print("(" + ig1 + "," + ig2 + ") ");
    }
    System.out.println("");
}

这给了我

(0,1) (0,2) (0,3) (0,4) (0,5) 
(1,2) (1,3) (1,4) (1,5) 
(2,3) (2,4) (2,5) 
(3,4) (3,5) 
(4,5)

有没有人知道我将如何用 6 个 for 循环编辑第一个代码段以获得 3 对 pions,如果 gamma 用于 1 个 pion,它不会再次重复?对中的顺序确实很重要,这意味着如果一对是 (0,1),那么对 (1,0) 是不同的并且不可互换。

【问题讨论】:

    标签: java for-loop combinatorics


    【解决方案1】:

    我建议将其分为两个步骤。

    1. 查找所有元素对(顺序很重要)。
    2. 查找所有对的组合(顺序无关紧要)。

    如果你想分析,我整理了一个示例程序。

    我做的第一件事是创建一个简单的Pair 类来跟踪对、比较值并打印它们:

    public class Pair {
      Integer one;
      Integer two;
      
      public Pair(Integer one, Integer two)
      {
        this.one = one;
        this.two = two;
      }
      
      public boolean hasNoMatchingValues(Pair other)
      {
        return !this.one.equals(other.one) && !this.one.equals(other.two) && !this.two.equals(other.one) && !this.two.equals(other.two);
      }
      
      public static boolean hasNoMatchingValues(Pair...values)
      {
        for(int i = 0; i < values.length - 1; i++)
        {
          for(int j = i + 1; j < values.length; j++)
          {
            if(!values[i].hasNoMatchingValues(values[j]))
              return false;
          }
        }
        return true;
      }
      
      @Override
      public String toString()
      {
        return "(" + one + ", " + two + ")";
      }
    }
    

    在此之后,我使用以下代码查找所有对,然后将它们匹配到 3 的组合中:

    import java.util.ArrayList;
    import java.util.List;
    
    public class PairCombinations
    {
      public static void main(String[] args)
      {
        //Builds the list of unique objects
        List<Integer> objectList = new ArrayList<>();
        for(int i = 0; i < 8; i++)
          objectList.add(i);
    
        //Finds all pairs and adds them to pairsList
        List<Pair> pairsList = new ArrayList<>();
        for(int i = 0; i < objectList.size() - 1; i++)
        {
          for(int j = i + 1; j < objectList.size(); j++)
          {
            pairsList.add(new Pair(objectList.get(i), objectList.get(j)));
            pairsList.add(new Pair(objectList.get(j), objectList.get(i)));
          }
        }
        
        //Loop three times since you want three combinations. Can be adjusted to a recursive form.
        List<List<Pair>> allCombos = new ArrayList<>();
        for(int i = 0; i < pairsList.size() - 2; i++)
        {
          for(int j = i + 1; j < pairsList.size() - 1; j++)
          {
            for(int k = j + 1; k < pairsList.size(); k++)
            {
              Pair one = pairsList.get(i), two = pairsList.get(j), three = pairsList.get(k);
              if(Pair.hasNoMatchingValues(one, two, three))
              {
                List<Pair> combos = new ArrayList<>();
                combos.add(one);
                combos.add(two);
                combos.add(three);
                allCombos.add(combos);
              }
            }
          }
        }
        
        //Print the results
        for(List<Pair> combo : allCombos)
          System.out.println(combo);
      }
    }
    

    如果您有任何问题,请告诉我。

    【讨论】:

    • 我用 i
    • @Illari 如果i &lt;6 肯定总是有第 0 个元素,因为总共只有 6 个元素,所以 3 对 2 总是使用所有元素。不过,i &lt; 8 的结果很奇怪。让我稍微更新一下代码。我调整了一些重复值检查的可伸缩性。我肯定会在最后得到结果,例如 [(7, 2), (6, 3), (5, 4)] 没有第 0 个元素。
    • @Tom Hunter,关于第 0 个物体,你是对的,我一直忘记循环从 0 bc 开始在我写下 gamma1-6 的笔记中,它让我忘记了......这是不过,这样一个引人入胜的答案。你介意我问一下你背后的想法吗?
    • @Illari 隔离顺序执行的流程步骤是我的主要想法。弄清楚哪些步骤会改变数据,了解数据在每个步骤结束时的外观,并组织每个流程以在该步骤处理数据。更容易将数据视为每个变形步骤之后的样子,并尝试隔离在该状态下对其进行处理,而不是考虑可能需要几个变形步骤才能达到的最终结果。您的场景是一个很好的案例,可以将 Pairs 抽象为它们自己的数据状态。
    【解决方案2】:

    如果有人想查看带有嵌套 for 循环的版本,以及认为 (0,1) 与 (1,0) 相同的版本。这是一个比两个类的答案稍微简单的版本,我认为如果有人来寻找一种以稍微不同的方式配对的方法,他们可能会受益。

    int n_g = 6;
    boolean hasDVPi0P = false;
    for (int ig1 = 0; ig1 < n_g && !hasDVPi0P ; ig1++) {
        for (int ig2 = 0; ig2 < n_g && !hasDVPi0P ; ig2++) {
            for (int ig3 = 0; ig3 < n_g && !hasDVPi0P ; ig3++) {
                for (int ig4 = 0; ig4 < n_g && !hasDVPi0P ; ig4++) {
                    for (int ig5 = 0; ig5 < n_g && !hasDVPi0P ; ig5++) {
                        for (int ig6 = 0; ig6 < n_g && !hasDVPi0P ; ig6++) {
                            if( true
                                && ig1<ig2 && ig3<ig4 && ig5<ig6 // different photons in each pair
                                && ig1<ig3 && ig1<ig5 && ig3<ig5 // unique first photon from each pair
                                && ig2!=ig3 && ig2!=ig4 && ig2!=ig5 && ig2!=ig6 // clean up rest of pairs below
                                && ig3!=ig4 && ig3!=ig5 && ig3!=ig6
                                && ig4!=ig5 && ig4!=ig6
                                ){
                                System.out.println("(" + ig1 + "," + ig2 + ") , (" + ig3 + "," + ig4 + ") , (" + ig5 + "," + ig6 + ")\n");
                            }
                        }
                    }
                }
            }
        }
    }
    

    当然,您可以更改 int n_g = 6,但此方法保留嵌套的 for 循环并使用 if 语句来处理对,可以根据您可能需要的任何条件对其进行修改。

    这最终对我来说是最有用的,因为另一个答案虽然很广泛,但创建了完全独立的类。我需要保持对 3 对的检查相当包含并且比其他答案中提供的要短。

    【讨论】:

      猜你喜欢
      • 2021-11-06
      • 1970-01-01
      • 2023-02-04
      • 2017-05-07
      • 1970-01-01
      • 2019-06-14
      • 2021-09-05
      • 2023-02-22
      • 2022-07-20
      相关资源
      最近更新 更多