スタックのすべての可能な pop のリストを生成してから、シミュレートできます。
ただし、重複が発生する可能性があります。各スタックに要素が 2 つしかない場合を考えてみてください。a が c にプッシュされ、b が d にプッシュされる場合、それらがプッシュされる順序は関係ありません。
def simulate(steps):
source={'a':range(4),'b':range(4,8)}
res = {'c':"",'d':""};
for i,step in enumerate(steps):
res[step[1]]+=str(source[step[0]].pop())
# this is what each stack will look like
return res['c']+'-'+res['d']
def steps(a_left,b_left):
ret = []
if a_left>0:
substeps = steps(a_left-1,b_left)
ret.extend( [ x + [('a','c')] for x in substeps] )
ret.extend( [ x + [('a','d')] for x in substeps] )
if b_left>0:
substeps = steps(a_left,b_left-1)
ret.extend( [ x + [('b','c')] for x in substeps] )
ret.extend( [ x + [('b','d')] for x in substeps] )
if(len(ret)==0):
return [[]]
return ret;
そして結果:
>>> [x for x in steps(1,1)]
[[('b', 'c'), ('a', 'c')], [('b', 'd'), ('a', 'c')], [('b', 'c'), ('a', 'd')], [
('b', 'd'), ('a', 'd')], [('a', 'c'), ('b', 'c')], [('a', 'd'), ('b', 'c')], [('
a', 'c'), ('b', 'd')], [('a', 'd'), ('b', 'd')]]
>>> [simulate(x) for x in steps(1,1)]
['73-', '3-7', '7-3', '-73', '37-', '7-3', '3-7', '-37']
>>> len(set([simulate(x) for x in steps(4,4)]))
5136
ターゲット スタックが 1 つだけの 2 つのスタックを考えると、一意のスタックの数は (2*n)!/(n!)^2 でわかります。これは、「A」が 4 個、「B」が 4 個の 8 個の要素の順列の数と同じです。次に、それらをサブセットに分割することで、それらを個々のスタックに割り当てることができます。スタックごとに N 個の一意の番号を持つサブセットの数は 2^(2^n) になります。
(2^(2*n))/((2*n)!/(n!)^2)
ただし、これらをより効率的に生成する方法はわかりません。