Bir set verildi
{0, 1, 2, 3}
Alt kümeleri nasıl üretebilirim:
[set(),
{0},
{1},
{2},
{3},
{0, 1},
{0, 2},
{0, 3},
{1, 2},
{1, 3},
{2, 3},
{0, 1, 2},
{0, 1, 3},
{0, 2, 3},
{1, 2, 3},
{0, 1, 2, 3}]
Yanıtlar:
Python itertools
sayfasının tam olarak bunun powerset
için bir tarifi vardır :
from itertools import chain, combinations
def powerset(iterable):
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
Çıktı:
>>> list(powerset("abcd"))
[(), ('a',), ('b',), ('c',), ('d',), ('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd'), ('a', 'b', 'c'), ('a', 'b', 'd'), ('a', 'c', 'd'), ('b', 'c', 'd'), ('a', 'b', 'c', 'd')]
Başlangıçta bu boş diziyi beğenmezseniz, 0 uzunluklu bir kombinasyondan kaçınmak için range
ifadeyi değiştirebilirsiniz range(1, len(s)+1)
.
s = list(iterable)
gerekli?
__len__
uygulanmaları gerekmez ; powerset((n for n in range(3)))
liste sarmadan deneyin .
powerset(range(3))
cezası çalışacak bile olmadans = list(iterable)
.
İşte bir güç seti için daha fazla kod. Bu sıfırdan yazılmıştır:
>>> def powerset(s):
... x = len(s)
... for i in range(1 << x):
... print [s[j] for j in range(x) if (i & (1 << j))]
...
>>> powerset([4,5,6])
[]
[4]
[5]
[4, 5]
[6]
[4, 6]
[5, 6]
[4, 5, 6]
Mark Rushakoff'un yorumu burada uygulanabilir: "Başlangıçta bu boş tuple'ı beğenmezseniz, on." 0 uzunluklu bir kombinasyondan kaçınmak için range ifadesini range (1, len (s) +1) olarak değiştirebilirsiniz. " benim durumlar dışında değiştirmek for i in range(1 << x)
için for i in range(1, 1 << x)
.
Bu yıllara dönersek, şimdi şöyle yazacağım:
def powerset(s):
x = len(s)
masks = [1 << i for i in range(x)]
for i in range(1 << x):
yield [ss for mask, ss in zip(masks, s) if i & mask]
Ve sonra test kodu şöyle görünecektir:
print(list(powerset([4, 5, 6])))
Kullanımı yield
, tüm sonuçları tek bir bellek parçasında hesaplamanıza gerek olmadığı anlamına gelir. Ana döngünün dışındaki maskeleri önceden hesaplamanın değerli bir optimizasyon olduğu varsayılır.
Hızlı bir cevap arıyorsanız, Google'da "python güç seti" aradım ve şunu buldum: Python Güç Seti Oluşturucu
İşte o sayfadaki koddan bir kopyala-yapıştır:
def powerset(seq):
"""
Returns all the subsets of this set. This is a generator.
"""
if len(seq) <= 1:
yield seq
yield []
else:
for item in powerset(seq[1:]):
yield [seq[0]]+item
yield item
Bu şu şekilde kullanılabilir:
l = [1, 2, 3, 4]
r = [x for x in powerset(l)]
Şimdi r, istediğiniz tüm öğelerin bir listesidir ve sıralanabilir ve yazdırılabilir:
r.sort()
print r
[[], [1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 4], [1, 3], [1, 3, 4], [1, 4], [2], [2, 3], [2, 3, 4], [2, 4], [3], [3, 4], [4]]
[[][]]
uzunluk kontrolü için durumları ayırmayı düzeltmek için yukarıdaki kod geri dönecektirif len(seq) == 0: yield [] elif len(seq) == 1: yield seq yield []
Güç kümesinde bir iyileştirme var:
def powerset(seq):
"""
Returns all the subsets of this set. This is a generator.
"""
if len(seq) <= 0:
yield []
else:
for item in powerset(seq[1:]):
yield [seq[0]]+item
yield item
Daha önce bir cevap eklediğimi biliyorum, ancak yeni uygulamamı gerçekten seviyorum. Girdi olarak bir küme alıyorum, ama aslında herhangi bir yinelenebilir olabilir ve girdinin güç kümesi olan bir dizi küme geri dönüyorum. Bu yaklaşımı seviyorum çünkü güç kümesinin matematiksel tanımıyla ( tüm alt kümelerin kümesi ) daha uyumlu .
def power_set(A):
"""A is an iterable (list, tuple, set, str, etc)
returns a set which is the power set of A."""
length = len(A)
l = [a for a in A]
ps = set()
for i in range(2 ** length):
selector = f'{i:0{length}b}'
subset = {l[j] for j, bit in enumerate(selector) if bit == '1'}
ps.add(frozenset(subset))
return ps
Cevabınızda gönderdiğiniz çıktıyı tam olarak istiyorsanız, şunu kullanın:
>>> [set(s) for s in power_set({1, 2, 3, 4})]
[{3, 4},
{2},
{1, 4},
{2, 3, 4},
{2, 3},
{1, 2, 4},
{1, 2},
{1, 2, 3},
{3},
{2, 4},
{1},
{1, 2, 3, 4},
set(),
{1, 3},
{1, 3, 4},
{4}]
Güç setinin eleman sayısının olduğu bilinmektedir 2 ** len(A)
, bu nedenle for
döngüde açıkça görülebilmektedir .
Girdiyi (ideal olarak bir küme) bir listeye dönüştürmem gerekiyor çünkü bir küme, benzersiz sıralanmamış öğelerin bir veri yapısıdır ve sıra, alt kümeleri oluşturmak için çok önemli olacaktır.
selector
bu algoritmanın anahtarıdır. selector
Girdi kümesiyle aynı uzunluğa sahip olduğuna dikkat edin ve bunu mümkün kılmak için dolgulu bir f-dizesi kullanmaktır. Temel olarak bu, her yineleme sırasında her alt kümeye eklenecek öğeleri seçmeme olanak tanır. Diyelim ki giriş kümesinde 3 eleman var {0, 1, 2}
, bu yüzden seçici 0 ile 7 (dahil) arasında değerler alacak, bunlar ikilik tabanda:
000 # 0
001 # 1
010 # 2
011 # 3
100 # 4
101 # 5
110 # 6
111 # 7
Bu nedenle, her bit, orijinal setin bir elemanının eklenip eklenmeyeceği konusunda bir gösterge görevi görebilir. İkili sayılara bakın ve her sayıyı süper kümenin bir öğesi olarak düşünün; 1
bu, dizindeki bir öğenin j
eklenmesi gerektiği 0
anlamına gelir ve bu öğenin eklenmemesi gerektiği anlamına gelir.
Her yinelemede bir alt küme oluşturmak için bir küme anlayışı kullanıyorum ve bu alt kümeyi frozenset
,ps
(güç kümesine) . Aksi takdirde, Python'daki bir küme yalnızca değişmez nesnelerden oluştuğu için onu ekleyemem.
Bazı python anlayışlarını kullanarak kodu basitleştirebilir, böylece döngüler için bunlardan kurtulabilirsiniz. Ayrıca dizini kullanmaktan zip
kaçınmak için de kullanabilirsiniz j
ve kod aşağıdaki gibi sonlanacaktır:
def power_set(A):
length = len(A)
return {
frozenset({e for e, b in zip(A, f'{i:{length}b}') if b == '1'})
for i in range(2 ** length)
}
Bu kadar. Bu algoritmadan hoşlandığım şey, diğerlerinden daha net ve sezgisel olması, çünkü itertools
beklendiği gibi çalışmasına rağmen güvenmek oldukça büyülü görünüyor .
def get_power_set(s):
power_set=[[]]
for elem in s:
# iterate over the sub sets so far
for sub_set in power_set:
# add a new subset consisting of the subset at hand added elem
power_set=power_set+[list(sub_set)+[elem]]
return power_set
Örneğin:
get_power_set([1,2,3])
Yol ver
[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
power_set
) değiştirmek çok tartışmalı bir uygulamadır. Örneğin, bunun yerine önerilen değişken değiştirerek bu kod yazdım varsayalım: power_set += [list(sub_set)+[elem]]
. Sonra döngü sona ermiyor.
Aşağıdaki algoritmayı çok açık ve basit buldum:
def get_powerset(some_list):
"""Returns all subsets of size 0 - len(some_list) for some_list"""
if len(some_list) == 0:
return [[]]
subsets = []
first_element = some_list[0]
remaining_list = some_list[1:]
# Strategy: get all the subsets of remaining_list. For each
# of those subsets, a full subset list will contain both
# the original subset as well as a version of the subset
# that contains first_element
for partial_subset in get_powerset(remaining_list):
subsets.append(partial_subset)
subsets.append(partial_subset[:] + [first_element])
return subsets
Güç kümesini oluşturmanın başka bir yolu, bitleri olan tüm ikili sayıları üretmektir n
. Bir güç seti olarak n
basamaklı sayı miktarıdır 2 ^ n
. Bu algoritmanın prensibi, bir elemanın bir alt kümede bulunup bulunmayacağıdır, çünkü ikili bir rakam bir veya sıfır olabilir, ancak ikisi birden olamaz.
def power_set(items):
N = len(items)
# enumerate the 2 ** N possible combinations
for i in range(2 ** N):
combo = []
for j in range(N):
# test bit jth of integer i
if (i >> j) % 2 == 1:
combo.append(items[j])
yield combo
MITx: 6.00.2x Hesaplamalı Düşünme ve Veri Bilimine Giriş alırken her iki algoritmayı da buldum ve anladığım en kolay algoritmalardan biri olduğunu düşünüyorum.
Sadece en anlaşılır çözümü sunmak istedim, anti kod-golf versiyonu.
from itertools import combinations
l = ["x", "y", "z", ]
def powerset(items):
combo = []
for r in range(len(items) + 1):
#use a list to coerce a actual list from the combinations generator
combo.append(list(combinations(items,r)))
return combo
l_powerset = powerset(l)
for i, item in enumerate(l_powerset):
print "All sets of length ", i
print item
Sonuçlar
Tüm uzunluk setleri 0
[()]
Tüm uzunluk setleri 1
[('x',), ('y',), ('z',)]
Tüm uzunluk setleri 2
[('x', 'y'), ('x', 'z'), ('y', 'z')]
Tüm uzunluk setleri 3
[('x', 'y', 'z')]
Daha fazla bilgi için itertools belgelerine ve ayrıca güç kümelerindeki wikipedia girişine bakın
Sadece hızlı bir güç seti tazeleme!
Bir X kümesinin güç kümesi, boş küme dahil olmak üzere X'in tüm alt kümelerinin kümesidir.
Örnek X = (a, b, c) kümesi
Güç Seti = {{a, b, c}, {a, b}, {a, c}, {b, c}, {a}, {b}, {c}, {}}
İşte güç setini bulmanın başka bir yolu:
def power_set(input):
# returns a list of all subsets of the list a
if (len(input) == 0):
return [[]]
else:
main_subset = [ ]
for small_subset in power_set(input[1:]):
main_subset += [small_subset]
main_subset += [[input[0]] + small_subset]
return main_subset
print(power_set([0,1,2,3]))
kaynağa tam kredi
Bu, aşağıdakilerle çok doğal bir şekilde yapılabilir itertools.product
:
import itertools
def powerset(l):
for sl in itertools.product(*[[[], [i]] for i in l]):
yield {j for i in sl for j in i}
Basit bir yol, tamsayıların dahili temsilini 2'nin tamamlayıcı aritmetiği altında kullanmak olabilir.
Tam sayıların ikili gösterimi, 0 ile 7 arasında değişen sayılar için {000, 001, 010, 011, 100, 101, 110, 111} şeklindedir. dışlama olarak, sayma sırasına göre alt kümeler oluşturabiliriz. Sayılar üretilen lazım 0
içinpow(2,n) -1
n, ikili gösterimine bit dizisi yani sayısının uzunluğudur.
Buna dayalı basit bir Alt Küme Oluşturucu Fonksiyonu aşağıdaki gibi yazılabilir. Temelde dayanır
def subsets(array):
if not array:
return
else:
length = len(array)
for max_int in range(0x1 << length):
subset = []
for i in range(length):
if max_int & (0x1 << i):
subset.append(array[i])
yield subset
ve sonra şu şekilde kullanılabilir
def get_subsets(array):
powerset = []
for i in subsets(array):
powerser.append(i)
return powerset
Test yapmak
Yerel dosyaya aşağıdakileri ekleme
if __name__ == '__main__':
sample = ['b', 'd', 'f']
for i in range(len(sample)):
print "Subsets for " , sample[i:], " are ", get_subsets(sample[i:])
aşağıdaki çıktıyı verir
Subsets for ['b', 'd', 'f'] are [[], ['b'], ['d'], ['b', 'd'], ['f'], ['b', 'f'], ['d', 'f'], ['b', 'd', 'f']]
Subsets for ['d', 'f'] are [[], ['d'], ['f'], ['d', 'f']]
Subsets for ['f'] are [[], ['f']]
Bana biraz hile gibi gelen bu yanıtların hemen hemen hepsi list
yerine kullanıyor set
. Bu yüzden meraktan gerçekten basit bir versiyon yapmaya set
ve diğer "Python'a yeni" milletler için özetlemeye çalıştım .
Python'un set uygulamasıyla uğraşırken birkaç tuhaflık olduğunu buldum . Benim için asıl sürpriz boş setlerle uğraşmaktı. Bu, Ruby'nin Set uygulamasının tam tersidir , burada basitçe yapıp Set[Set[]]
bir Set
içeren boş bir tane alabilirimSet
, bu yüzden başlangıçta biraz kafa karıştırıcı buldum.
İncelemek için, s powerset
ile yaparken set
iki problemle karşılaştım:
set()
yinelenebilir bir alan alır, bu nedenle set(set())
geri döner set()
çünkü yinelenebilir boş küme boştur (sanırım :))set({set()})
ve set.add(set)
çünkü çalışmaz set()
hashable değilHer iki sorunu da çözmek için kullandım frozenset()
, bu da istediğimi tam olarak elde edemediğim anlamına geliyor ( yazım kelimenin tam anlamıyla set
), ancak genel set
etkileşimi kullanıyorum.
def powerset(original_set):
# below gives us a set with one empty set in it
ps = set({frozenset()})
for member in original_set:
subset = set()
for m in ps:
# to be added into subset, needs to be
# frozenset.union(set) so it's hashable
subset.add(m.union(set([member]))
ps = ps.union(subset)
return ps
Aşağıda frozenset
çıktı olarak 2² (16) s doğru elde ediyoruz :
In [1]: powerset(set([1,2,3,4]))
Out[2]:
{frozenset(),
frozenset({3, 4}),
frozenset({2}),
frozenset({1, 4}),
frozenset({3}),
frozenset({2, 3}),
frozenset({2, 3, 4}),
frozenset({1, 2}),
frozenset({2, 4}),
frozenset({1}),
frozenset({1, 2, 4}),
frozenset({1, 3}),
frozenset({1, 2, 3}),
frozenset({4}),
frozenset({1, 3, 4}),
frozenset({1, 2, 3, 4})}
Bir var bir yolu yoktur gibi set
bir set
bu çevirmek istiyorsanız, Python s frozenset
içine s set
s, bir geri bunları harita gerekecek list
( list(map(set, powerset(set([1,2,3,4]))))
) veya yukarıdaki değiştirin.
Belki soru eskiyor, ama umarım kodum birine yardımcı olur.
def powSet(set):
if len(set) == 0:
return [[]]
return addtoAll(set[0],powSet(set[1:])) + powSet(set[1:])
def addtoAll(e, set):
for c in set:
c.append(e)
return set
powerset()
Paketin işlevini kullanın more_itertools
.
Yinelenebilir tüm olası alt kümelerini verir
>>> list(powerset([1, 2, 3]))
[(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]
Setler istiyorsanız, şunu kullanın:
list(map(set, powerset(iterable)))
Özyinelemeli tüm alt kümeleri alma. Çılgın tek çizgili
from typing import List
def subsets(xs: list) -> List[list]:
return subsets(xs[1:]) + [x + [xs[0]] for x in subsets(xs[1:])] if xs else [[]]
Haskell çözümüne dayalı
subsets :: [a] -> [[a]]
subsets [] = [[]]
subsets (x:xs) = map (x:) (subsets xs) ++ subsets xs
NameError: name 'List' is not defined
List
İthalat ekledim
def findsubsets(s, n):
return list(itertools.combinations(s, n))
def allsubsets(s) :
a = []
for x in range(1,len(s)+1):
a.append(map(set,findsubsets(s,x)))
return a
Bunu şu şekilde yapabilirsiniz:
def powerset(x):
m=[]
if not x:
m.append(x)
else:
A = x[0]
B = x[1:]
for z in powerset(B):
m.append(z)
r = [A] + z
m.append(r)
return m
print(powerset([1, 2, 3, 4]))
Çıktı:
[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3], [4], [1, 4], [2, 4], [1, 2, 4], [3, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4]]
Bunun çok geç olduğunu biliyorum
Zaten başka birçok çözüm var ama yine de ...
def power_set(lst):
pw_set = [[]]
for i in range(0,len(lst)):
for j in range(0,len(pw_set)):
ele = pw_set[j].copy()
ele = ele + [lst[i]]
pw_set = pw_set + [ele]
return pw_set
Bu çılgınca çünkü bu yanıtların hiçbiri gerçek bir Python kümesinin geri dönüşünü sağlamıyor. İşte aslında bir Python olan bir güç kümesi verecek karmaşık bir uygulama set
.
test_set = set(['yo', 'whatup', 'money'])
def powerset( base_set ):
""" modified from pydoc's itertools recipe shown above"""
from itertools import chain, combinations
base_list = list( base_set )
combo_list = [ combinations(base_list, r) for r in range(len(base_set)+1) ]
powerset = set([])
for ll in combo_list:
list_of_frozensets = list( map( frozenset, map( list, ll ) ) )
set_of_frozensets = set( list_of_frozensets )
powerset = powerset.union( set_of_frozensets )
return powerset
print powerset( test_set )
# >>> set([ frozenset(['money','whatup']), frozenset(['money','whatup','yo']),
# frozenset(['whatup']), frozenset(['whatup','yo']), frozenset(['yo']),
# frozenset(['money','yo']), frozenset(['money']), frozenset([]) ])
Yine de daha iyi bir uygulama görmeyi çok isterim.
[*map(set, chain.from_iterable(combinations(s, r) for r in range(len(s)+1)))]
; eğer tercih ederseniz işlevi arg map
olabilir frozenset
.
İşte kombinasyonları kullanan, ancak yalnızca yerleşikleri kullanan hızlı uygulamam.
def powerSet(array):
length = str(len(array))
formatter = '{:0' + length + 'b}'
combinations = []
for i in xrange(2**int(length)):
combinations.append(formatter.format(i))
sets = set()
currentSet = []
for combo in combinations:
for i,val in enumerate(combo):
if val=='1':
currentSet.append(array[i])
sets.add(tuple(sorted(currentSet)))
currentSet = []
return sets
N aralığındaki tüm alt kümeler ayarlandığı gibi:
n = int(input())
l = [i for i in range (1, n + 1)]
for number in range(2 ** n) :
binary = bin(number)[: 1 : -1]
subset = [l[i] for i in range(len(binary)) if binary[i] == "1"]
print(set(sorted(subset)) if number > 0 else "{}")
import math
def printPowerSet(set,set_size):
pow_set_size =int(math.pow(2, set_size))
for counter in range(pow_set_size):
for j in range(set_size):
if((counter & (1 << j)) > 0):
print(set[j], end = "")
print("")
set = ['a', 'b', 'c']
printPowerSet(set,3)
Sorunun bir çeşidi, "Bilgisayar Bilimini Keşfetmek: Disiplinlerarası Problemler, İlkeler ve Python Programlama. 2015 baskısı" kitabında gördüğüm bir alıştırmadır. Bu alıştırmada 10.2.11, girdi sadece bir tam sayıdır ve çıktı, güç setleri olmalıdır. İşte benim özyinelemeli çözümüm (temel python3 dışında başka bir şey kullanmıyorum)
def powerSetR(n):
assert n >= 0
if n == 0:
return [[]]
else:
input_set = list(range(1, n+1)) # [1,2,...n]
main_subset = [ ]
for small_subset in powerSetR(n-1):
main_subset += [small_subset]
main_subset += [ [input_set[-1]] + small_subset]
return main_subset
superset = powerSetR(4)
print(superset)
print("Number of sublists:", len(superset))
Ve çıktı
[[], [4], [3], [4, 3], [2], [4, 2], [3, 2], [4, 3, 2], [1], [4, 1 ], [3, 1], [4, 3, 1], [2, 1], [4, 2, 1], [3, 2, 1], [4, 3, 2, 1]] Sayısı alt listeler: 16
İşleve rastlamadım more_itertools.powerset
ve bunu kullanmanızı tavsiye ederim. Ayrıca, çıkış için varsayılan sıralamayı kullanmamanızı da tavsiye ederim itertools.combinations
, bunun yerine genellikle konumlar arasındaki mesafeyi en aza indirmek ve aralarında daha büyük mesafe olan öğelerin üstünde / altında daha kısa mesafe olan öğelerin alt kümelerini sıralamak istersiniz .
itertools
Sayfa tarifleri kullandığı gösterilerichain.from_iterable
r
Burada alt kısmı için standart notasyonu maçları binom katsayısı , s
genellikle olarak anılır n
( “n r seç”) matematik metinlerde ve hesap makinelerindedef powerset(iterable):
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
Buradaki diğer örnekler [1,2,3,4]
, 2-tupleların "sözlükbilimsel" sırayla listelenmesini sağlayacak şekilde (sayıları tamsayı olarak yazdırdığımızda) güç kümesini verir. Numaraların arasındaki mesafeyi yanına yazarsam (yani farkı), bu benim noktamı gösterir:
12 ⇒ 1
13 ⇒ 2
14 ⇒ 3
23 ⇒ 1
24 ⇒ 2
34 ⇒ 1
Alt kümeler için doğru sıra, ilk olarak minimum mesafeyi 'tüketen' sıra olmalıdır, örneğin:
12 ⇒ 1
23 ⇒ 1
34 ⇒ 1
13 ⇒ 2
24 ⇒ 2
14 ⇒ 3
Burada sayıların kullanılması bu sıralamanın 'yanlış' görünmesine ["a","b","c","d"]
neden olur , ancak örneğin harfleri düşünün, bu sırayla güç kümesini elde etmenin neden yararlı olabileceği daha açıktır:
ab ⇒ 1
bc ⇒ 1
cd ⇒ 1
ac ⇒ 2
bd ⇒ 2
ad ⇒ 3
Bu etki daha fazla maddeyle daha belirgindir ve benim amaçlarım için, güç kümesinin dizin aralıklarını anlamlı bir şekilde tanımlayabilmek arasındaki farkı yaratır.
( Kombinasyondaki algoritmaların çıktı sıralaması için Gray kodlar vb. Üzerine yazılmış çok şey var, bunu bir yan konu olarak görmüyorum).
Aslında, değerleri doğru sırayla çıkarmak için bu hızlı tamsayı bölümleme kodunu kullanan oldukça ilgili bir program yazdım, ancak sonra keşfettim more_itertools.powerset
ve çoğu kullanım için bu işlevi böyle kullanmanın muhtemelen iyi olduğunu keşfettim :
from more_itertools import powerset
from numpy import ediff1d
def ps_sorter(tup):
l = len(tup)
d = ediff1d(tup).tolist()
return l, d
ps = powerset([1,2,3,4])
ps = sorted(ps, key=ps_sorter)
for x in ps:
print(x)
⇣
()
(1,)
(2,)
(3,)
(4,)
(1, 2)
(2, 3)
(3, 4)
(1, 3)
(2, 4)
(1, 4)
(1, 2, 3)
(2, 3, 4)
(1, 2, 4)
(1, 3, 4)
(1, 2, 3, 4)
(: Güzel ben buraya dahil ettik işlevleri yazdırmak için repo bakınız ben güzel POWERSET yazdırılır bazı daha karmaşık kod yazdım print_partitions
, print_partitions_by_length
ve pprint_tuple
).
pset_partitions.py
Bunların hepsi oldukça basit, ancak güç kümesinin farklı düzeylerine doğrudan erişmenizi sağlayacak bir kod istiyorsanız yine de yararlı olabilir:
from itertools import permutations as permute
from numpy import cumsum
# http://jeromekelleher.net/generating-integer-partitions.html
# via
# /programming/10035752/elegant-python-code-for-integer-partitioning#comment25080713_10036764
def asc_int_partitions(n):
a = [0 for i in range(n + 1)]
k = 1
y = n - 1
while k != 0:
x = a[k - 1] + 1
k -= 1
while 2 * x <= y:
a[k] = x
y -= x
k += 1
l = k + 1
while x <= y:
a[k] = x
a[l] = y
yield tuple(a[:k + 2])
x += 1
y -= 1
a[k] = x + y
y = x + y - 1
yield tuple(a[:k + 1])
# https://stackoverflow.com/a/6285330/2668831
def uniquely_permute(iterable, enforce_sort=False, r=None):
previous = tuple()
if enforce_sort: # potential waste of effort (default: False)
iterable = sorted(iterable)
for p in permute(iterable, r):
if p > previous:
previous = p
yield p
def sum_min(p):
return sum(p), min(p)
def partitions_by_length(max_n, sorting=True, permuting=False):
partition_dict = {0: ()}
for n in range(1,max_n+1):
partition_dict.setdefault(n, [])
partitions = list(asc_int_partitions(n))
for p in partitions:
if permuting:
perms = uniquely_permute(p)
for perm in perms:
partition_dict.get(len(p)).append(perm)
else:
partition_dict.get(len(p)).append(p)
if not sorting:
return partition_dict
for k in partition_dict:
partition_dict.update({k: sorted(partition_dict.get(k), key=sum_min)})
return partition_dict
def print_partitions_by_length(max_n, sorting=True, permuting=True):
partition_dict = partitions_by_length(max_n, sorting=sorting, permuting=permuting)
for k in partition_dict:
if k == 0:
print(tuple(partition_dict.get(k)), end="")
for p in partition_dict.get(k):
print(pprint_tuple(p), end=" ")
print()
return
def generate_powerset(items, subset_handler=tuple, verbose=False):
"""
Generate the powerset of an iterable `items`.
Handling of the elements of the iterable is by whichever function is passed as
`subset_handler`, which must be able to handle the `None` value for the
empty set. The function `string_handler` will join the elements of the subset
with the empty string (useful when `items` is an iterable of `str` variables).
"""
ps = {0: [subset_handler()]}
n = len(items)
p_dict = partitions_by_length(n-1, sorting=True, permuting=True)
for p_len, parts in p_dict.items():
ps.setdefault(p_len, [])
if p_len == 0:
# singletons
for offset in range(n):
subset = subset_handler([items[offset]])
if verbose:
if offset > 0:
print(end=" ")
if offset == n - 1:
print(subset, end="\n")
else:
print(subset, end=",")
ps.get(p_len).append(subset)
for pcount, partition in enumerate(parts):
distance = sum(partition)
indices = (cumsum(partition)).tolist()
for offset in range(n - distance):
subset = subset_handler([items[offset]] + [items[offset:][i] for i in indices])
if verbose:
if offset > 0:
print(end=" ")
if offset == n - distance - 1:
print(subset, end="\n")
else:
print(subset, end=",")
ps.get(p_len).append(subset)
if verbose and p_len < n-1:
print()
return ps
Örnek olarak, komut satırı argümanı olarak bir dizeyi alan bir CLI demo programı yazdım:
python string_powerset.py abcdef
⇣
a, b, c, d, e, f
ab, bc, cd, de, ef
ac, bd, ce, df
ad, be, cf
ae, bf
af
abc, bcd, cde, def
abd, bce, cdf
acd, bde, cef
abe, bcf
ade, bef
ace, bdf
abf
aef
acf
adf
abcd, bcde, cdef
abce, bcdf
abde, bcef
acde, bdef
abcf
abef
adef
abdf
acdf
acef
abcde, bcdef
abcdf
abcef
abdef
acdef
abcdef
Belirli uzunlukta alt kümeler istiyorsanız, bunu şu şekilde yapabilirsiniz:
from itertools import combinations
someSet = {0, 1, 2, 3}
([x for i in range(len(someSet)+1) for x in combinations(someSet,i)])
Daha genel olarak, isteğe bağlı uzunluk alt kümeleri için aralık düzenlemesini değiştirebilirsiniz. Çıktı
[(), (0,), (1,), (2,), (3,), (0, 1), (0, 2), (0, 3), (1, 2), (1 , 3), (2, 3), (0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3), (0, 1, 2, 3 )]
def powerset(some_set):
res = [(a,b) for a in some_set for b in some_set]
return res