这是一个家庭作业问题,但我已经研究了一段时间,我不明白我做错了什么。任何帮助将不胜感激。
根据以下规则计算N晚餐客人可以围绕圆桌安排自己的方式:
最初,所有客人都坐在圆桌旁,没有空座位。为了鼓励对话,主持人要求每位客人站起来,然后坐在三把椅子中的一把:原来的椅子,一个在左边,一个在右边。
所有客人都必须坐下。
有多少种不同的晚餐客人安排?
如果任何客人的主席号码因一种安排而异,则两种安排不同。
ABCD与DABC不同。但是,没有人可以移动超过两个地方, I.E BCAD将无效,因为A移动了两个位置。
部分解决方案是:
3 guests can sit in 6 different ways
4 guests can sit in 9 different ways
5 guests can sit in 13 different ways
6 guests can sit in 20 different ways
7 guests can sit in 31 different ways
我的代码最多可容纳5位客人,但对于6位客人,我有19种不同的安排。 7位客人,我有28个安排。我猜我的逻辑有些东西,但我无法理解。
这是我的代码:
def dinner_party_arrangements(N):
import itertools
if N > 10:
return('This function is not built for N > 10.')
else:
import math
result=math.factorial(N)
baseL=[]
main=list(range(N))
L=list(range(N+1))
L.remove(0)
combos=(list(itertools.permutations(L)))
for stuff in combos:
baseL.append(stuff)
for guests in baseL:
resultL=list(guests)
#looks at single tuple
for num in main:
a=num
b=num+1
c=num+2
if resultL[num] == a or resultL[num] == b or resultL[num] == c:
pass
else:
result=(result-1)
break
if N<3:
return(result)
else:
return(result+N)
答案 0 :(得分:1)
以下是您的代码的重构版本,以便更好地理解:
import itertools
import math
def dinner_party_arrangements(N):
assert N <= 10, 'This function is not built for N > 10.'
result = math.factorial(N)
if N < 3:
return result
for guests in itertools.permutations(range(1, N+1)):
for num in range(N):
if guests[num] not in (num, num+1, num+2):
result -= 1
break
return result+N
我认为问题在于你没有管理&#34; edge&#34;,即位置0可以被客人1(没有改变),客人2,(右邻居)或客人N占用(最后一个,左边的邻居)。桌面上的最后一个位置也是如此。因此,以下方法可行(将import
放在一边):
def dinner_party_arrangements(N):
assert N <= 10, 'This function is not built for N > 10.'
if N < 3:
return math.factorial(N)
allguests = list(itertools.permutations(range(1,N+1)))
result = len(allguests)
for guests in allguests:
for num in range(N):
if guests[num] not in (N if num==0 else num, num+1, 1 if num==N-1 else num+2):
result -= 1
break
return result
另请注意,我不会在N> 2中使用factorial;我只计算正确的排列数。
更好的是,以下使用了排列函数的惰性:
def dinner_party_arrangements(N):
assert N <= 10, 'This function is not built for N > 10.'
if N < 3:
return math.factorial(N)
result = 0
for guests in itertools.permutations(range(1,N+1)):
for num in range(N):
if guests[num] not in (N if num==0 else num, num+1, 1 if num==N-1 else num+2):
break
else:
result += 1
return result
最后,这是一个递归解决方案。与你(和其他人)的方法相反,我不会产生每一个排列,然后消除错误的排列;我从头开始创建解决方案。另外,我使用基于0的编号,这对我来说更自然:
def dinner(gst):
assert gst > 2 # alogorith doesn't work for < 3 people
res = [] # result, the list of all possible combinations
def sub(current, pers):
if pers == gst: # base case of recursion; no more person to sit
res.append(current) # found one combo, add it to result
return # and stop here
for offset in (-1, 0, +1): # for each move (left, stay, right)
newpos = (pers + offset) % gst # compute new position
if current[newpos] is None: # seat is not yet taken
newcurrent = current[:] # create a copy of current (incomplete) combination
newcurrent[newpos] = pers # sit person pos at position newpos
sub(newcurrent, pers + 1) # and recurse for the other persons
sub([None]*gst, 0) # initialize a combi
return res
然后
for i in range(3, 8):
combos = dinner(i)
print(i, "guests can sit in", len(combos), "ways", combos)
产量
3 guests can sit in 6 ways [[1, 2, 0], [2, 1, 0], [0, 1, 2], [0, 2, 1], [1, 0, 2], [2, 0, 1]]
4 guests can sit in 9 ways [[1, 2, 3, 0], [3, 1, 2, 0], [3, 2, 1, 0], [0, 1, 2, 3], [0, 1, 3, 2], [0, 2, 1, 3], [1, 0, 2, 3], [1, 0, 3, 2], [3, 0, 1, 2]]
5 guests can sit in 13 ways [[1, 2, 3, 4, 0], [4, 1, 2, 3, 0], [4, 1, 3, 2, 0], [4, 2, 1, 3, 0], [0, 1, 2, 3, 4], [0, 1, 2, 4, 3], [0, 1, 3, 2, 4], [0, 2, 1, 3, 4], [0, 2, 1, 4, 3], [1, 0, 2, 3, 4], [1, 0, 2, 4, 3], [1, 0, 3, 2, 4], [4, 0, 1, 2, 3]]
6 guests can sit in 20 ways [[1, 2, 3, 4, 5, 0], [5, 1, 2, 3, 4, 0], [5, 1, 2, 4, 3, 0], [5, 1, 3, 2, 4, 0], [5, 2, 1, 3, 4, 0], [5, 2, 1, 4, 3, 0], [0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 5, 4], [0, 1, 2, 4, 3, 5], [0, 1, 3, 2, 4, 5], [0, 1, 3, 2, 5, 4], [0, 2, 1, 3, 4, 5], [0, 2, 1, 3, 5, 4], [0, 2, 1, 4, 3, 5], [1, 0, 2, 3, 4, 5], [1, 0, 2, 3, 5, 4], [1, 0, 2, 4, 3, 5], [1, 0, 3, 2, 4, 5], [1, 0, 3, 2, 5, 4], [5, 0, 1, 2, 3, 4]]
7 guests can sit in 31 ways [[1, 2, 3, 4, 5, 6, 0], [6, 1, 2, 3, 4, 5, 0], [6, 1, 2, 3, 5, 4, 0], [6, 1, 2, 4, 3, 5, 0], [6, 1, 3, 2, 4, 5, 0], [6, 1, 3, 2, 5, 4, 0], [6, 2, 1, 3, 4, 5, 0], [6, 2, 1, 3, 5, 4, 0], [6, 2, 1, 4, 3, 5, 0], [0, 1, 2, 3, 4, 5, 6], [0, 1, 2, 3, 4, 6, 5], [0, 1, 2, 3, 5, 4, 6], [0, 1, 2, 4, 3, 5, 6], [0, 1, 2, 4, 3, 6, 5], [0, 1, 3, 2, 4, 5, 6], [0, 1, 3, 2, 4, 6, 5], [0, 1, 3, 2, 5, 4, 6], [0, 2, 1, 3, 4, 5, 6], [0, 2, 1, 3, 4, 6, 5], [0, 2, 1, 3, 5, 4, 6], [0, 2, 1, 4, 3, 5, 6], [0, 2, 1, 4, 3, 6, 5], [1, 0, 2, 3, 4, 5, 6], [1, 0, 2, 3, 4, 6, 5], [1, 0, 2, 3, 5, 4, 6], [1, 0, 2, 4, 3, 5, 6], [1, 0, 2, 4, 3, 6, 5], [1, 0, 3, 2, 4, 5, 6], [1, 0, 3, 2, 4, 6, 5], [1, 0, 3, 2, 5, 4, 6], [6, 0, 1, 2, 3, 4, 5]]
我希望这会有所帮助。
答案 1 :(得分:0)
这是我的方法。对于大n来说,它确实很慢,但它确实有效。
from itertools import permutations
def arrange( n ):
# First, place all your guests (0 - n) into an array
positions = range( n )
arrangements = 0
# Iterate over every possible arrangement of guests
for arrangement in permutations( positions ):
# begin by assuming the iteration is "valid", that is, no guest
# hopped more than one spot
is_valid = True
# Now iterate over all your guests
for i in range( n ):
# If the guest moved more than one spot, this permutation is
# invalid and we can throw it out
pos_dif = abs( arrangement.index( i ) - positions.index( i ) )
if pos_dif > 1 and pos_dif != n-1:
is_valid = False
break
# Otherwise, the iteration is valid and we can increment our count
if is_valid:
arrangements += 1
return arrangements
答案 2 :(得分:0)
我的方法类似于上面的帖子:
def mydin(n):
import itertools
initial_table = range(n)
poss_tables = set(itertools.permutations(initial_table))
validTables = []
for table in poss_tables:
if isValid(initial_table,table):
validTables.append(table)
print len(validTables)
return len(validTables)
def isValid(initial_table,arrangement):
size = initial_table[-1]
for i in range(len(initial_table)):
if i == size:
if arrangement[i] in (initial_table[i-1],initial_table[i],initial_table[0]):
continue
else:
return False
elif arrangement[i] in [initial_table[i-1],initial_table[i],initial_table[i+1]]:
continue
else:
return False
return True
for n in range(3,11):
mydin(n)
对于我的输出我得到了
6
9
13
20
31
49
78
125