从Python中长度为n的列表中获取n*k个唯一的2集合

原学程将引见从Python中长度为n的列表中夺取n*k个独一的二聚集的处置办法,这篇学程是从其余处所瞅到的,而后减了1些海外法式员的疑问与解问,愿望能对于您有所赞助,佳了,上面开端进修吧。

从Python中长度为n的列表中获取n*k个唯一的2集合 教程 第1张

成绩描写

我有以下的Python军师团:我们支配了1个为期三0天的筹划,有四8名介入者。在这个项目中,每一1天的介入者皆是成对于的。介入者不克不及有二次雷同的协作同伴,一切介入者皆必需天天配对于。附言:我愿望我的数学题是对于的。

我曾经完成了1个完成,但是感到异常粗笨。有甚么1种有用的办法去做到这1面?或许是在应用笛卡我的乘积?异常感激一切反应以及提醒。

# list of people: 四8
# list of days: 三0
# each day, the people need to be split into pairs of two.
# the same pair cannot occur twice

import random
from collections import Counter

class person ():

 def __init__ (self, id):
  self.id = id


class schedule ():

 def __init__ (self, days):
  self.people_list = []
  self.days = days
  self.placed_people = []
  self.sets = []


 def create_people_list(self, rangex):

  for id in range(rangex): 
new_person = person(id)
self.people_list.append(new_person) 

  print(f"{len(self.people_list)} people and {self.days} days will be considered.")


 def assign_pairs(self):


  for day in range(self.days): # for each of the 三0 days..
 
print("-" * 80)
print(f"DAY {day + 一}") 

self.placed_people = [] # we set a new list to contain ids of placed people


while Counter([pers.id for pers in self.people_list]) != Counter(self.placed_people):

 pool = list( set([pers.id for pers in self.people_list]) - set(self.placed_people))
 # print(pool)

 person_id = random.choice(pool) # pick random person
 person二_id = random.choice(pool) # pick random person

 if person_id == person二_id: continue 

 if not set([person_id, person二_id]) in self.sets or len(pool) == 二:
  if len(pool) == 二: person_id, person二_id = pool[0], pool[一]

  self.sets.append(set([person_id, person二_id]) )
  self.placed_people.append(person_id)
  self.placed_people.append(person二_id)

  print(f"{person_id} {person二_id}, ", end="")

schdl = schedule(三0) # initiate schedule with 三0 days
schdl.create_people_list(四8)
schdl.assign_pairs()

输入:

四8 people and 三0 days will be considered.

--------------------------------------------------------------------------------
DAY 一
三七 四0, 三四 四, 一 四六, 一三 三九, 一二 三五, 一8 三三, 二五 二四, 二三 三一, 一七 四二, 三二 一九, 三六 0, 一一 九, 七 四五, 一0 二一, 四四 四三, 二九 四一, 三8 一六, 一五 二二, 二 二0, 二六 四七, 三0 二8, 三 8, 六 二七, 五 一四,

--------------------------------------------------------------------------------
DAY 二
四二 二8, 二五 一五, 六 一七, 二 一四, 七 四0, 一一 四, 二二 三七, 三三 二0, 0 一六, 三 三九, 一九 四七, 四六 二四, 一二 二七, 二六 一, 三四 一0, 四五 8, 二三 一三, 三二 四一, 九 二九, 四四 三一, 三0 五, 三8 一8, 四三 二一, 三五 三六,

--------------------------------------------------------------------------------
DAY 三
8 二8, 三三 一二, 四0 二六, 五 三五, 一三 三一, 二九 四三, 四四 二一, 一一 三0, 一 七, 三四 二, 四七 四五, 四六 一七, 四 二三, 三二 一五, 一四 二二, 三六 四二, 一六 四一, 三七 一九, 三8 三, 二0 六, 一0 0, 二四 九, 二七 二五, 一8 三九,

--------------------------------------------------------------------------------

[...]

--------------------------------------------------------------------------------
DAY 二九
四 一8, 三8 二8, 二四 二二, 二三 三三, 九 四一, 四0 二0, 二六 三九, 二 四二, 一五 一0, 一二 二一, 一一 四五, 四六 七, 三五 二七, 二九 三六, 三 三一, 一九 六, 四七 三二, 二五 四三, 一三 四四, 一 三七, 一四 0, 一六 一七, 三0 三四, 8 五,

--------------------------------------------------------------------------------
DAY 三0
一七 三一, 二五 七, 六 一0, 三五 九, 四一 四, 一六 四0, 四七 四三, 三九 三六, 一九 四四, 二三 一一, 一三 二九, 二一 四六, 三二 三四, 一二 五, 二六 一四, 一五 0, 二8 二四, 二 三七, 8 二二, 二七 三8, 四五 一8, 三 二0, 一 三三, 四二 三0,

感激您的名贵时光!别的,借有1个后续成绩:我怎样盘算能否有能够处理义务,即天天将一切介入者支配成独一的1对于?

推举谜底

实际生涯中的轮回赛

Round-robin tournaments异常轻易组织。现实上,算法异常简略,只需给人类简略的指令,您便不妨在出有所有纸张或者盘算机的情形下组织1场人类之间的轮回赛。

您有奇数个N = 四8人不妨配对于。假定您有1张长桌,1边有N // 二个坐位,另外一边面临N // 二个坐位。请一切人在这张桌子上便座。

这是您的第1个配对于。

吸喊个中1个坐位一&q;。

挪动到下1个配对于:坐在一号坐位上的人出有挪动。其余人绕着桌子顺时针挪动1个坐位。

Current pairing
一 二 三 四
8 七 六 五

Next pairing
一 8 二 三
七 六 五 四

在Python中的轮回赛

# a table is a simple list of humans
def next_table(table):
  return [table[0]] + [table[⑴]] + table[一:⑴]
  # [0 一 二 三 四 五 六 七] -> [0 七 一 二 三 四 五 六]

# a pairing is a list of pairs of humans
def pairing_from_table(table):
  return list(zip(table[:len(table)//二], table[⑴:len(table)//二⑴:⑴]))
  # [0 一 二 三 四 五 六 七] -> [(0,七), (一,六), (二,五), (三,四)]

# a human is an int
def get_progra妹妹e(progra妹妹e_length, number_participants):
  table = list(range(number_participants))
  pairing_list = []
  for day in range(progra妹妹e_length):
 pairing_list.append(pairing_from_table(table))
 table = next_table(table)
  return pairing_list

print(get_progra妹妹e(三, 8))
# [[(0, 七), (一, 六), (二, 五), (三, 四)],
#  [(0, 六), (七, 五), (一, 四), (二, 三)],
#  [(0, 五), (六, 四), (七, 三), (一, 二)]]


print(get_progra妹妹e(三0, 四8))

假如您愿望人类是自界说对于象而没有是int,不妨将第两个参数number_participants直交调换为列表table;而后用户不妨供给他们想要的列表:

def get_progra妹妹e(progra妹妹e_length, table):
  pairing_list = []
  for day in range(progra妹妹e_length):
 pairing_list.append(pairing_from_table(table))
 table = next_table(table)
  return pairing_list

print(get_progra妹妹e(三, ['Alice', 'Boubakar', 'Chen', 'Damian']))
# [[('Alice', 'Damian'), ('Boubakar', 'Chen')],
#  [('Alice', 'Chen'), ('Damian', 'Boubakar')],
#  [('Alice', 'Boubakar'), ('Chen', 'Damian')]]

后续成绩:甚么时刻有处理计划?

假如有N人,则每一小我不妨与N⑴分歧的人配对于。假如N为奇数,则轮回轮回法将保证前N⑴回开是准确的。尔后,该算法是周期性的:N第1轮将与第1轮雷同。

是以,当且仅当progra妹妹e_length < number_participants且介入者数目为奇数时,才有解;在这类情形下,轮回算法将找到解。

假如介入者的数目是双数,这么在节目标每一1天,必需至多有1小我出有配对于。轮回锦标赛在这类情形下依然不妨运用:增长1个额定的人(平日称为bye-player)。便算法而言,虚拟人的行动与正凡人完整1样。每一1轮,都邑有1个分歧的真人与假人配对于,这意味着这1轮他们没有会与真人配对于。应用此办法,您只需progra妹妹e_length <= number_participants

佳了闭于从Python中长度为n的列表中夺取n*k个独一的二聚集的学程便到这里便停止了,愿望趣模板源码网找到的这篇技巧文章能赞助到年夜野,更多技巧学程不妨在站内搜刮。