自定义排列,对的均等分布

时间:2018-09-26 20:41:40

标签: python language-agnostic permutation combinatorics discrete-mathematics

我一直在玩一个奇怪的问题,已经有几个星期了,似乎无法获得想要的结果。

我想对对象列表进行排列以获得唯一的对。然后以特定方式对它们进行排序,以最大程度地使对象在列表中的任何位置均匀分布。这也意味着,如果一个对象在一对的开始处,则也应该在之后的一对结束时。没有对可以重复。为了澄清,这是一个示例。

列表(A,B,C,D)可能会导致以下结果:

(A,B)
(C,D)
(B,A)
(D,C)
(A,C)
(B,D)
(C,A)
(D,B)
(A,D)
(B,C)
(D,A)
(C,B)

注意,每个字母每2对使用一次,并且字母频繁切换位置。

要获得排列,我使用了python脚本:

perm = list(itertools.permutations(list,2))

给了我12对字母。

然后,我手动排序对,以便尽可能频繁地选择每个字母并尽可能频繁地切换位置。在列表中的任何时候,字母将非常平均地分布。当我解决这个问题的过程时,我知道列表中的哪个位置将停止,但我不知道这对配对的放置顺序有多大影响。

使用4个字母可以更容易实现,因为(4个字母/ 2对)= 2。 我也希望这也适用于奇数排列对。

例如:

A,B.C

A,B,C,D,E

等等。

我已经尝试了许多方法并试图识别模式,尽管有很多方法,但是尤其有很多方法可以解决此问题。可能还没有一个完美的答案。

我还尝试过对字母P(4,4)进行正常排列,或者对5个字母P(5,5)进行了排列,并且尝试了某些排列,将它们组合在一起,然后切碎成对。这似乎是另一条路线,但除非手动进行,否则我似乎无法弄清楚该选择哪对。

感谢您的帮助!也许尝试为我指出正确的方向:)

我最终将尝试将其实现到python中,但是我不一定需要帮助来编写代码。这更多地是关于流程可能是一个问题。

1 个答案:

答案 0 :(得分:3)

“最大均等分布”的含义尚未明确定义。一个给定值的两个幻影之间可以考虑的最大对数。我会留给您展示一下我在此给出的方法相对于此的效果。

对于n个对象,我们有n *(n-1)对。在这些(a, b)对中

  • n具有诸如b =(a + 1)模n的索引
  • n的索引为b =(a + 2)模n

    以此类推。

我们可以生成前1对n相差1,然后生成n对2相差...

对于每个差异,我们通过将差异添加到索引(模n)来生成索引。当我们得到一个已经用于解决这种差异的a时,我们加1 (再次取模n)。这样,我们可以产生具有这种差异的n对。当我们在索引中“滚动”时,我们确定每个值都会定期出现。

def pairs(n):
    for diff in range(1, n):
        starts_seen = set()
        index = 0
        for i in range(n):
            pair = [index]
            starts_seen.add(index)
            index = (index+diff) % n
            pair.append(index)
            yield pair
            index = (index+diff) % n
            if index in starts_seen:
                index = (index+1) % n

pairs2 = list(pair for pair in pairs(2))
print(pairs2)
# [[0, 1], [1, 0]]          

pairs3 = list(pair for pair in pairs(3))
print(pairs3)         
# [[0, 1], [2, 0], [1, 2], 
#  [0, 2], [1, 0], [2, 1]]

pairs4 = list(pair for pair in pairs(4))
print(pairs4)        
# [[0, 1], [2, 3], [1, 2], [3, 0],   <- diff = 1
#  [0, 2], [1, 3], [2, 0], [3, 1],   <- diff = 2
#  [0, 3], [2, 1], [1, 0], [3, 2]]   <- diff = 3

pairs5 = list(pair for pair in pairs(5))
print(pairs5)    
# [[0, 1], [2, 3], [4, 0], [1, 2], [3, 4],
#  [0, 2], [4, 1], [3, 0], [2, 4], [1, 3],
#  [0, 3], [1, 4], [2, 0], [3, 1], [4, 2],
#  [0, 4], [3, 2], [1, 0], [4, 3], [2, 1]]

# A check to verify that we get the right number of different pairs:
for n in range(100):
    pairs_n = set([tuple(pair) for pair in pairs(n)])
    assert len(pairs_n) == n*(n-1)
print('ok')
# ok