পাইথন, 302 287 বাইট
ডেড পসসাম ইতিমধ্যে একটি সংক্ষিপ্ত পাইথোনিক সমাধান পোস্ট করেছে, তাই আমি অতিরিক্ত কুডোস যাওয়ার সিদ্ধান্ত নিয়েছি। এই সমাধানটি সমস্ত অনুমতিগুলি উত্পন্ন করে না । এটি বরং একটি বৃহত্তর স্ট্রিংয়ের ক্রমশক্তি সূচকটি দ্রুত গণনা করতে পারে; এটি একটি খালি স্ট্রিং সঠিকভাবে পরিচালনা করে।
from math import factorial as f
from itertools import groupby as g
def p(t,b=''):
if len(t)<2:return 0
z,b=0,b or sorted(t)
for i,c in enumerate(b):
w=b[:i]+b[i+1:]
if c==t[0]:return z+p(t[1:],w)
if i<1 or c!=b[i-1]:
n=f(len(w))
for _,v in g(w):n//=f(len(list(v)))
z+=n
পরীক্ষার কোড:
def lexico_permute_string(s):
''' Generate all permutations of `s` in lexicographic order '''
a = sorted(s)
n = len(a) - 1
while True:
yield ''.join(a)
for j in range(n-1, -1, -1):
if a[j] < a[j + 1]:
break
else:
return
v = a[j]
for k in range(n, j, -1):
if v < a[k]:
break
a[j], a[k] = a[k], a[j]
a[j+1:] = a[j+1:][::-1]
def test_all(base):
for i, s in enumerate(lexico_permute_string(base)):
rank = p(s)
assert rank == i, (i, s, rank)
print('{:2} {} {:2}'.format(i, s, rank))
print(repr(base), 'ok\n')
for base in ('AAB', 'abbbbc'):
test_all(base)
def test(s):
print('{!r}\n{}\n'.format(s, p(s)))
for s in ('ZZZ', 'DCBA', 'a quick brown fox jumps over the lazy dog'):
test(s)
আউটপুট
0 AAB 0
1 ABA 1
2 BAA 2
'AAB' ok
0 abbbbc 0
1 abbbcb 1
2 abbcbb 2
3 abcbbb 3
4 acbbbb 4
5 babbbc 5
6 babbcb 6
7 babcbb 7
8 bacbbb 8
9 bbabbc 9
10 bbabcb 10
11 bbacbb 11
12 bbbabc 12
13 bbbacb 13
14 bbbbac 14
15 bbbbca 15
16 bbbcab 16
17 bbbcba 17
18 bbcabb 18
19 bbcbab 19
20 bbcbba 20
21 bcabbb 21
22 bcbabb 22
23 bcbbab 23
24 bcbbba 24
25 cabbbb 25
26 cbabbb 26
27 cbbabb 27
28 cbbbab 28
29 cbbbba 29
'abbbbc' ok
'ZZZ'
0
'DCBA'
23
'a quick brown fox jumps over the lazy dog'
436629906477779191275460617121351796379337
নন-গল্ফ করা সংস্করণ:
''' Determine the rank (lexicographic index) of a permutation
The permutation may contain repeated items
Written by PM 2Ring 2017.04.03
'''
from math import factorial as fac
from itertools import groupby
def lexico_permute_string(s):
''' Generate all permutations of `s` in lexicographic order '''
a = sorted(s)
n = len(a) - 1
while True:
yield ''.join(a)
for j in range(n-1, -1, -1):
if a[j] < a[j + 1]:
break
else:
return
v = a[j]
for k in range(n, j, -1):
if v < a[k]:
break
a[j], a[k] = a[k], a[j]
a[j+1:] = a[j+1:][::-1]
def perm_count(s):
''' Count the total number of permutations of sorted sequence `s` '''
n = fac(len(s))
for _, g in groupby(s):
n //= fac(sum(1 for u in g))
return n
def perm_rank(target, base):
''' Determine the permutation rank of string `target`
given the rank zero permutation string `base`,
i.e., the chars in `base` are in lexicographic order.
'''
if len(target) < 2:
return 0
total = 0
head, newtarget = target[0], target[1:]
for i, c in enumerate(base):
newbase = base[:i] + base[i+1:]
if c == head:
return total + perm_rank(newtarget, newbase)
elif i and c == base[i-1]:
continue
total += perm_count(newbase)
base = 'abcccdde'
print('total number', perm_count(base))
for i, s in enumerate(lexico_permute_string(base)):
rank = perm_rank(s, base)
assert rank == i, (i, s, rank)
#print('{:2} {} {:2}'.format(i, s, rank))
print('ok')
সম্পর্কিত lexico_permute_string
নারায়ণ পান্ডিতার কারণে এই অ্যালগরিদমটি https://en.wikedia.org/wiki/ পরিমিতি # জেনারেশন_ ইন_লেক্সিকোগ্রাফিক_ অর্ডার থেকে
সিকোয়েন্সের লিক্সোগ্রাফিক ক্রমে পরবর্তী ক্রমান্বয়ে উত্পাদন করতে a
- বৃহত্তম সূচক জে যেমন একটি [জে] <ক [জে + 1] সন্ধান করুন। যদি এরকম কোনও সূচক না থাকে তবে অনুক্রমটি হ'ল শেষ অনুমান perm
- জে এর চেয়ে বৃহততম সূচক কে সন্ধান করুন যা একটি [জে] <ক [কে]।
- একটি [জে] এর মান একটি [কে] এর সাথে অদলবদল করুন।
- চূড়ান্ত উপাদানটিকে [j + 1] থেকে চূড়ান্ত উপাদান a [n] সহ উল্টো করুন।
এফডাব্লুআইডাব্লু, আপনি এখানে এখানে ফাংশনটির একটি টীকাযুক্ত সংস্করণ দেখতে পারেন ।
FWIW, এখানে বিপরীত ফাংশন।
def perm_unrank(rank, base, head=''):
''' Determine the permutation with given rank of the
rank zero permutation string `base`.
'''
if len(base) < 2:
return head + ''.join(base)
total = 0
for i, c in enumerate(base):
if i < 1 or c != base[i-1]:
newbase = base[:i] + base[i+1:]
newtotal = total + perm_count(newbase)
if newtotal > rank:
return perm_unrank(rank - total, newbase, head + c)
total = newtotal
# Test
target = 'a quick brown fox jumps over the lazy dog'
base = ''.join(sorted(target))
rank = perm_rank(target, base)
print(target)
print(base)
print(rank)
print(perm_unrank(rank, base))
আউটপুট
a quick brown fox jumps over the lazy dog
aabcdeefghijklmnoooopqrrstuuvwxyz
436629906477779191275460617121351796379337
a quick brown fox jumps over the lazy dog
এবং এখানে একটি ফাংশন যা আমি বিকাশের সময় লিখেছিলাম perm_unrank
যা সাবকাউন্টগুলির ভাঙ্গন দেখায়।
def counts(base):
for i, c in enumerate(base):
newbase = base[:i] + base[i+1:]
if newbase and (i < 1 or c != base[i-1]):
yield c, perm_count(newbase)
for h, k in counts(newbase):
yield c + h, k
def show_counts(base):
TAB = ' ' * 4
for s, t in counts(base):
d = len(s) - 1
print('{}{} {}'.format(TAB * d, s, t))
# Test
base = 'abccc'
print('total number', perm_count(base))
show_counts(base)
আউটপুট
a 4
ab 1
abc 1
abcc 1
ac 3
acb 1
acbc 1
acc 2
accb 1
accc 1
b 4
ba 1
bac 1
bacc 1
bc 3
bca 1
bcac 1
bcc 2
bcca 1
bccc 1
c 12
ca 3
cab 1
cabc 1
cac 2
cacb 1
cacc 1
cb 3
cba 1
cbac 1
cbc 2
cbca 1
cbcc 1
cc 6
cca 2
ccab 1
ccac 1
ccb 2
ccba 1
ccbc 1
ccc 2
ccca 1
cccb 1