Bir listenin elemanlarının adil bölümlenmesi


12

Oyuncuların derecelendirmelerinin bir listesi verildiğinde, oyuncuları (yani derecelendirmeleri) mümkün olduğunca adil bir şekilde iki gruba ayırmam gerekiyor. Amaç, takımların kümülatif puanları arasındaki farkı en aza indirmektir. Oyuncuları takımlara nasıl bölebileceğime dair herhangi bir kısıtlama yok (bir takımın 2 oyuncusu ve diğer takımın 10 oyuncusu olabilir).

Örneğin: [5, 6, 2, 10, 2, 3, 4]geri dönmeli([6, 5, 3, 2], [10, 4, 2])

Bu sorunu çözmek için algoritmayı bilmek istiyorum. Bir çevrimiçi programlama tanıtım dersi aldığımı lütfen unutmayın, bu nedenle basit algoritmalar takdir edilecektir.

Aşağıdaki kodu kullanıyorum, ancak bazı nedenlerden dolayı çevrimiçi kod denetleyicisi yanlış olduğunu söylüyor.

def partition(ratings):
    set1 = []
    set2 =[]
    sum_1 = 0
    sum_2 = 0
    for n in sorted(ratings, reverse=True):
        if sum_1 < sum_2:
            set1.append(n)
            sum_1 = sum_1 + n
        else:
            set2.append(n)
            sum_2 = sum_2 + n
    return(set1, set2)

Güncelleme: Eğitmenlerle iletişime geçtim ve tüm farklı kombinasyonları kontrol etmek için fonksiyonun içinde başka bir "yardımcı" fonksiyon tanımlamam gerektiği söylendi, sonra minimum farkı kontrol etmem gerekiyor.


2
Google "alt küme toplamı sorunu"
John Coleman

@ JohnColeman öneriniz için teşekkür ederim. Sorunumu çözmek için alt küme toplamlarının nasıl kullanılacağı konusunda bana doğru yönde rehberlik edebilir misiniz?
EddieEC

6
Daha da spesifik olarak, bölüm sorunu olarak adlandırılan alt küme toplamı sorunu özel bir durum var . Bununla ilgili Wikipedia makalesi algoritmaları tartışıyor.
John Coleman

4
Bu sorunuza cevap veriyor mu? Listeyi iki eşit parça algoritmasına
bölün

1
İkinize de teşekkürler! Yardımları içtenlikle takdir ediyorum!
EddieEC

Yanıtlar:


4

Not: Tüm sayıların toplamı garip olduğunda durumu daha iyi ele almak için düzenlenmiştir.

Geri izleme bu sorun için bir olasılıktır.

Çok fazla belleğe ihtiyaç duymadan tüm olasılıkları yinelemeli olarak incelemeye izin verir.

Optimal bir çözüm bulunur bulunmaz durur: sum = 0sum A kümesinin elemanlarının toplamı ile B kümesinin elemanlarının toplamı arasındaki fark nerede . EDIT: en kısa sürede durursum < 2 tüm sayıların toplamı olduğunda davayı ele almak için garip, yani minimum 1 farkına karşılık gelir. Eğer bu küresel toplam çift ise, min fark 1'e eşit olamaz.

Basit bir erken terk prosedürünün uygulanmasına izin verir :
belirli bir zamanda, eğersum kalan tüm elemanların toplamından (yani A veya B'ye yerleştirilmemişse) artı elde edilen mevcut minimumun mutlak değerini daha yüksekse, incelemeyi bırakabiliriz kalan öğeleri incelemeden geçerli yol. Bu prosedür aşağıdakilerle optimize edilmiştir:

  • girdi verilerini azalan düzende sırala
  • Her adımda, ilk önce en olası seçimi inceleyin: bu, neredeyse optimum bir çözüme hızla ulaşılmasını sağlar

İşte bir sahte kod

Başlatma:

  • öğeleri sırala a[]
  • Kalan öğelerin toplamını hesaplayın: sum_back[i] = sum_back[i+1] + a[i];
  • Min "farkı" maksimum değerine ayarlayın: min_diff = sum_back[0];
  • a[0]A -> koyun iincelenen elemanın endeksi 1 olarak ayarlanır
  • Ayarla up_down = true;: bu boole şu anda ileri (doğru) veya geri (yanlış) olup olmadığımızı gösterir

Döngü sırasında:

  • Eğer (yukarı_ aşağı): ileri

    • Yardımıyla erken terk etmeyi test edin sum_back
    • En olası değeri seçin, sumbu seçeneğe göre ayarlayın
    • if (i == n-1): YAPRAK -> optimum değerin artırılıp iyileştirilmediğini test edin ve yeni değer 0'a eşitse geri dönün (DÜZENLE: if (... < 2) ; Geriye gitmek
    • Bir yaprakta değilse: ilerlemeye devam edin
  • Eğer (! Yukarı): geri

    • Eğer ulaşırsak i == 0 : dönüş
    • Bu düğümdeki ikinci yürüyüş ise: ikinci değeri seçin, yukarı çıkın
    • başka: aşağı in
    • Her iki durumda da: yeni sumdeğeri yeniden hesaplayın

İşte bir kod, C ++ (Üzgünüm, Python bilmiyorum)

#include    <iostream>
#include    <vector>
#include    <algorithm>
#include    <tuple>

std::tuple<int, std::vector<int>> partition(std::vector<int> &a) {
    int n = a.size();
    std::vector<int> parti (n, -1);     // current partition studies
    std::vector<int> parti_opt (n, 0);  // optimal partition
    std::vector<int> sum_back (n, 0);   // sum of remaining elements
    std::vector<int> n_poss (n, 0);     // number of possibilities already examined at position i

    sum_back[n-1] = a[n-1];
    for (int i = n-2; i >= 0; --i) {
        sum_back[i] = sum_back[i+1] + a[i];
    }

    std::sort(a.begin(), a.end(), std::greater<int>());
    parti[0] = 0;       // a[0] in A always !
    int sum = a[0];     // current sum

    int i = 1;          // index of the element being examined (we force a[0] to be in A !)
    int min_diff = sum_back[0];
    bool up_down = true;

    while (true) {          // UP
        if (up_down) {
            if (std::abs(sum) > sum_back[i] + min_diff) {  //premature abandon
                i--;
                up_down = false;
                continue;
            }
            n_poss[i] = 1;
            if (sum > 0) {
                sum -= a[i];
                parti[i] = 1;
            } else {
                sum += a[i];
                parti[i] = 0;
            }

            if (i == (n-1)) {           // leaf
                if (std::abs(sum) < min_diff) {
                    min_diff = std::abs(sum);
                    parti_opt = parti;
                    if (min_diff < 2) return std::make_tuple (min_diff, parti_opt);   // EDIT: if (... < 2) instead of (... == 0)
                }
                up_down = false;
                i--;
            } else {
                i++;        
            }

        } else {            // DOWN
            if (i == 0) break;
            if (n_poss[i] == 2) {
                if (parti[i]) sum += a[i];
                else sum -= a[i];
                //parti[i] = 0;
                i--;
            } else {
                n_poss[i] = 2;
                parti[i] = 1 - parti[i];
                if (parti[i]) sum -= 2*a[i];
                else sum += 2*a[i];
                i++;
                up_down = true;
            }
        }
    }
    return std::make_tuple (min_diff, parti_opt);
}

int main () {
    std::vector<int> a = {5, 6, 2, 10, 2, 3, 4, 13, 17, 38, 42};
    int diff;
    std::vector<int> parti;
    std::tie (diff, parti) = partition (a);

    std::cout << "Difference = " << diff << "\n";

    std::cout << "set A: ";
    for (int i = 0; i < a.size(); ++i) {
        if (parti[i] == 0) std::cout << a[i] << " ";
    }
    std::cout << "\n";

    std::cout << "set B: ";
    for (int i = 0; i < a.size(); ++i) {
        if (parti[i] == 1) std::cout << a[i] << " ";
    }
    std::cout << "\n";
}

Buradaki tek sorun her zaman en uygun toplamın 0 olacağı değildir. C ++ 'ı iyi okuyamadığım için oldukça iyi açıkladığınız için teşekkür ederim.
EddieEC

En uygun toplam 0'a eşit değilse, kod en iyi çözümü ezberleyerek tüm olasılıklara bakar. İncelenmeyen yollar, optimal olmadığından emin olduğumuz yollardır. Bu geri dönüşe karşılık gelir if I == 0. Örneğinizde 10'u 11 ile değiştirerek test ettim
Damien

3

Bir sonraki egzersizi kendiniz yapmanız gerektiğini düşünüyorum, aksi takdirde çok fazla şey öğrenmiyorsunuz. Buna gelince, eğitmeniniz tarafından tavsiyeyi uygulamaya çalışan bir çözüm:

def partition(ratings):

    def split(lst, bits):
        ret = ([], [])
        for i, item in enumerate(lst):
            ret[(bits >> i) & 1].append(item)
        return ret

    target = sum(ratings) // 2
    best_distance = target
    best_split = ([], [])
    for bits in range(0, 1 << len(ratings)):
        parts = split(ratings, bits)
        distance = abs(sum(parts[0]) - target)
        if best_distance > distance:
            best_distance = distance
            best_split = parts
    return best_split

ratings = [5, 6, 2, 10, 2, 3, 4]
print(ratings)
print(partition(ratings))

Çıktı:

[5, 6, 2, 10, 2, 3, 4]
([5, 2, 2, 3, 4], [6, 10])

Bu çıktının istediğiniz çıktıdan farklı olduğunu, ancak her ikisinin de doğru olduğunu unutmayın.

Bu algoritma, N elemanları ile belirli bir kümenin tüm olası alt kümelerini seçmek için, N bitleri ile tüm tamsayıları üretebilir ve I'inci bitin değerine bağlı olarak I'inci öğeyi seçebileceğiniz gerçeğine dayanır. best_distanceSıfır olduğu anda durmak için birkaç satır eklemek için size bırakıyorum (çünkü elbette daha iyi olamaz çünkü).

Bitlerde bir bit ( 0bPython'daki bir ikili sayının öneki olduğuna dikkat edin ):

İkili bir sayı: 0b0111001 == 0·2⁶+1·2⁵+1·2⁴+1·2³+0·2²+0·2¹+1·2⁰ == 57

Sağa 1 kaydırıldı: 0b0111001 >> 1 == 0b011100 == 28

Sola 1 kaydı: 0b0111001 << 1 == 0b01110010 == 114

Sağa 4 kaydırılmış: 0b0111001 >> 4 == 0b011 == 3

Bitsel &(ve):0b00110 & 0b10101 == 0b00100

5. bitin (dizin 4) 1 olup olmadığını kontrol etmek için: (0b0111001 >> 4) & 1 == 0b011 & 1 == 1

Biri ardından 7 sıfır: 1 << 7 == 0b10000000

7 olanlar: (1 << 7) - 1 == 0b10000000 - 1 == 0b1111111

Bütün 3-bit kombinasyonları: 0b000==0, 0b001==1, 0b010==2, 0b011==3, 0b100==4, 0b101==5, 0b110==6, 0b111==7(not 0b111 + 1 == 0b1000 == 1 << 3)


Çok teşekkür ederim! Ne yaptığını açıklayabilir misin? Ayrıca << kullanımı nedir? Mesela bu şeyleri nasıl yapacağımı hiç öğrenmedim. Ama tüm olasılıkları üretmem ve onu en az farkla geri döndürmem gerektiğini biliyordum!
EddieEC

İkili sayılar ve bit işlemlerine bir microlesson ekledim
Walter Tross

Muhtemelen başka bir fonksiyonun içinde bir fonksiyon tanımlamamalısınız.
AMC

1
@ AlexanderCécile buna bağlı . Bu durumda kabul edilebilir olduğunu ve temizliği geliştirdiğini düşünüyorum ve yine de OP'nin eğitmenleri tarafından önerildiği şey budur (sorusundaki güncellemeye bakın).
Walter Tross

1
@MiniMax N öğenin permütasyonları N! 'Dir, ancak alt kümeleri 2 ^ N'dir: ilk öğe alt kümede olabilir veya olmayabilir: 2 olasılık; ikinci öğe alt kümede olabilir veya olmayabilir: × 2; üçüncü öğe ... ve benzeri, N kez.
Walter Tross

1

Aşağıdaki algoritma bunu yapar:

  • öğeleri sıralar
  • üyeleri bile listeye koyar a, bbaşlamak için listede tek
  • arasında rastgele hareket eder ve takasları ürün ave bdeğişim iyiye doğru olup olmadığını

Örnek listenizdeki ilerlemeyi göstermek için yazdırma ifadeleri ekledim:

# -*- coding: utf-8 -*-
"""
Created on Fri Dec  6 18:10:07 2019

@author: Paddy3118
"""

from random import shuffle, random, randint

#%%
items = [5, 6, 2, 10, 2, 3, 4]

def eq(a, b):
    "Equal enough"
    return int(abs(a - b)) == 0

def fair_partition(items, jiggles=100):
    target = sum(items) / 2
    print(f"  Target sum: {target}")
    srt = sorted(items)
    a = srt[::2]    # every even
    b = srt[1::2]   # every odd
    asum = sum(a)
    bsum = sum(b)
    n = 0
    while n < jiggles and not eq(asum, target):
        n += 1
        if random() <0.5:
            # move from a to b?
            if random() <0.5:
                a, b, asum, bsum = b, a, bsum, asum     # Switch
            shuffle(a)
            trial = a[0]
            if abs(target - (bsum + trial)) < abs(target - bsum):  # closer
                b.append(a.pop(0))
                asum -= trial
                bsum += trial
                print(f"  Jiggle {n:2}: Delta after Move: {abs(target - asum)}")
        else:
            # swap between a and b?
            apos = randint(0, len(a) - 1)
            bpos = randint(0, len(b) - 1)
            trya, tryb = a[apos], b[bpos]
            if abs(target - (bsum + trya - tryb)) < abs(target - bsum):  # closer
                b.append(trya)  # adds to end
                b.pop(bpos)     # remove what is swapped
                a.append(tryb)
                a.pop(apos)
                asum += tryb - trya
                bsum += trya - tryb
                print(f"  Jiggle {n:2}: Delta after Swap: {abs(target - asum)}")
    return sorted(a), sorted(b)

if __name__ == '__main__':
    for _ in range(5):           
        print('\nFinal:', fair_partition(items), '\n')  

Çıktı:

  Target sum: 16.0
  Jiggle  1: Delta after Swap: 2.0
  Jiggle  7: Delta after Swap: 0.0

Final: ([2, 3, 5, 6], [2, 4, 10]) 

  Target sum: 16.0
  Jiggle  4: Delta after Swap: 0.0

Final: ([2, 4, 10], [2, 3, 5, 6]) 

  Target sum: 16.0
  Jiggle  9: Delta after Swap: 3.0
  Jiggle 13: Delta after Move: 2.0
  Jiggle 14: Delta after Swap: 1.0
  Jiggle 21: Delta after Swap: 0.0

Final: ([2, 3, 5, 6], [2, 4, 10]) 

  Target sum: 16.0
  Jiggle  7: Delta after Swap: 3.0
  Jiggle  8: Delta after Move: 1.0
  Jiggle 13: Delta after Swap: 0.0

Final: ([2, 3, 5, 6], [2, 4, 10]) 

  Target sum: 16.0
  Jiggle  5: Delta after Swap: 0.0

Final: ([2, 4, 10], [2, 3, 5, 6]) 

Çok teşekkür ederim, ama hiçbir şey ithal etmeden yapmam gerekiyor.
EddieEC

1

Tüm olası listeleri oluşturmak zorunda olduğumu bildiğim için, tüm olasılıkları üretmeye yardımcı olacak bir "yardımcı" işlev yapmam gerekiyor. Bunu yaptıktan sonra, minimum farkı kontrol etmek doğrudur ve bu minimum fark ile listelerin kombinasyonu istenen çözümdür.

Yardımcı işlev özyinelemelidir ve liste kombinasyonlarının tüm olasılıklarını kontrol edin.

def partition(ratings):

    def helper(ratings, left, right, aux_list, current_index):
        if current_index >= len(ratings):
            aux_list.append((left, right))
            return

        first = ratings[current_index]
        helper(ratings, left + [first], right, aux_list, current_index + 1)
        helper(ratings, left, right + [first], aux_list, current_index + 1)

    #l contains all possible sublists
    l = []
    helper(ratings, [], [], l, 0)
    set1 = []
    set2 = []
    #set mindiff to a large number
    mindiff = 1000
    for sets in l:
        diff = abs(sum(sets[0]) - sum(sets[1]))
        if diff < mindiff:
            mindiff = diff
            set1 = sets[0]
            set2 = sets[1]
    return (set1, set2)

Örnekler:, r = [1, 2, 2, 3, 5, 4, 2, 4, 5, 5, 2]en uygun bölüm: ([1, 2, 2, 3, 5, 4], [2, 4, 5, 5, 2])bir farkla 1.

r = [73, 7, 44, 21, 43, 42, 92, 88, 82, 70], en uygun bölüm: ([73, 7, 21, 92, 88], [44, 43, 42, 82, 70])bir farkla 0.


1
bana sorduğun için: öğreniyorsan çözüm iyi. Sadece bir sorunu vardır, şanslı olduğunuz diğer problemlerle ortak olan diğer problemden önce devreye girmez: üstel boşluk kullanır (O (n2ⁿ)). Ancak üstel zaman çok uzun zaman önce bir sorun olarak ortaya çıkıyor. Bununla birlikte, üstel alan kullanmaktan kaçınmak kolay olurdu.
Walter Tross

1

İşte performanstan ziyade eğitim amaçlı tasarlanmış oldukça ayrıntılı bir örnek. Liste kavrayışları ve jeneratörler gibi bazı ilginç Python kavramlarının yanı sıra, saçak vakalarının uygun şekilde kontrol edilmesi gereken iyi bir özyineleme örneği sunar. Uzantılar, örneğin sadece eşit sayıda oyuncuya sahip takımlar geçerlidir, uygun bireysel işlevlerde kolayca uygulanabilir.

def listFairestWeakTeams(ratings):
    current_best_weak_team_rating = -1
    fairest_weak_teams = []
    for weak_team in recursiveWeakTeamGenerator(ratings):
        weak_team_rating = teamRating(weak_team, ratings)
        if weak_team_rating > current_best_weak_team_rating:
            fairest_weak_teams = []
            current_best_weak_team_rating = weak_team_rating
        if weak_team_rating == current_best_weak_team_rating:
            fairest_weak_teams.append(weak_team)
    return fairest_weak_teams


def recursiveWeakTeamGenerator(
    ratings,
    weak_team=[],
    current_applicant_index=0
):
    if not isValidWeakTeam(weak_team, ratings):
        return
    if current_applicant_index == len(ratings):
        yield weak_team
        return
    for new_team in recursiveWeakTeamGenerator(
        ratings,
        weak_team + [current_applicant_index],
        current_applicant_index + 1
    ):
        yield new_team
    for new_team in recursiveWeakTeamGenerator(
        ratings,
        weak_team,
        current_applicant_index + 1
    ):
        yield new_team


def isValidWeakTeam(weak_team, ratings):
    total_rating = sum(ratings)
    weak_team_rating = teamRating(weak_team, ratings)
    optimal_weak_team_rating = total_rating // 2
    if weak_team_rating > optimal_weak_team_rating:
        return False
    elif weak_team_rating * 2 == total_rating:
        # In case of equal strengths, player 0 is assumed
        # to be in the "weak" team
        return 0 in weak_team
    else:
        return True


def teamRating(team_members, ratings):
    return sum(memberRatings(team_members, ratings))    


def memberRatings(team_members, ratings):
    return [ratings[i] for i in team_members]


def getOpposingTeam(team, ratings):
    return [i for i in range(len(ratings)) if i not in team]


ratings = [5, 6, 2, 10, 2, 3, 4]
print("Player ratings:     ", ratings)
print("*" * 40)
for option, weak_team in enumerate(listFairestWeakTeams(ratings)):
    strong_team = getOpposingTeam(weak_team, ratings)
    print("Possible partition", option + 1)
    print("Weak team members:  ", weak_team)
    print("Weak team ratings:  ", memberRatings(weak_team, ratings))
    print("Strong team members:", strong_team)
    print("Strong team ratings:", memberRatings(strong_team, ratings))
    print("*" * 40)

Çıktı:

Player ratings:      [5, 6, 2, 10, 2, 3, 4]
****************************************
Possible partition 1
Weak team members:   [0, 1, 2, 5]
Weak team ratings:   [5, 6, 2, 3]
Strong team members: [3, 4, 6]
Strong team ratings: [10, 2, 4]
****************************************
Possible partition 2
Weak team members:   [0, 1, 4, 5]
Weak team ratings:   [5, 6, 2, 3]
Strong team members: [2, 3, 6]
Strong team ratings: [2, 10, 4]
****************************************
Possible partition 3
Weak team members:   [0, 2, 4, 5, 6]
Weak team ratings:   [5, 2, 2, 3, 4]
Strong team members: [1, 3]
Strong team ratings: [6, 10]
****************************************

1

Takımları bile istediğiniz göz önüne alındığında, her takımın puanlarının hedef puanını bilirsiniz. Bu, derecelendirmelerin toplamının 2'ye bölünmesiyle elde edilir.

Yani aşağıdaki kod istediğinizi yapmalıdır.

from itertools import combinations

ratings = [5, 6, 2, 10, 2, 3, 4]

target = sum(ratings)/2 

difference_dictionary = {}
for i in range(1, len(ratings)): 
    for combination in combinations(ratings, i): 
        diff = sum(combination) - target
        if diff >= 0: 
            difference_dictionary[diff] = difference_dictionary.get(diff, []) + [combination]

# get min difference to target score 
min_difference_to_target = min(difference_dictionary.keys())
strong_ratings = difference_dictionary[min_difference_to_target]
first_strong_ratings = [x for x in strong_ratings[0]]

weak_ratings = ratings.copy()
for strong_rating in first_strong_ratings: 
    weak_ratings.remove(strong_rating)

Çıktı

first_strong_ratings 
[6, 10]

weak_rating 
[5, 2, 2, 3, 4]

fairnessTüm bu strong_ratings tuple içinde bulmak için kullanılabilir olan aynı diğer böler vardır , ben sadece birincisine bakmayı seçer, çünkü bu her zaman geçmek (sağlanan len(ratings) > 1) derecelendirme listesi için var olacaktır .


Bu sorunun zorluğu sorumda bahsettiğim gibi hiçbir şey ithal etmemekti. Girişiniz için teşekkürler!
EddieEC

0

Açgözlü bir çözüm, optimal olmayan bir çözüm sağlayabilir. İşte oldukça basit bir açgözlü çözüm, fikir, kovaya derecelendirme eklenmesinin etkisini azaltmak için listeyi azalan sırada sıralamaktır. Toplam puan toplamı daha az olan kovaya puan eklenecek

lis = [5, 6, 2, 10, 2, 3, 4]
lis.sort()
lis.reverse()

bucket_1 = []
bucket_2 = []

for item in lis:
    if sum(bucket_1) <= sum(bucket_2):
        bucket_1.append(item)
    else:
        bucket_2.append(item)

print("Bucket 1 : {}".format(bucket_1))
print("Bucket 2 : {}".format(bucket_2))

Çıktı :

Bucket 1 : [10, 4, 2]
Bucket 2 : [6, 5, 3, 2]

Düzenle:

Başka bir yaklaşım, listenin tüm olası alt kümelerini oluşturmak olacaktır. Listenin alt kümelerinden biri olan l1'iniz olduğunu varsayalım, o zaman l2 listesini kolayca alabilirsiniz, böylece l2 = liste (orijinal) - l1. N listesinin tüm olası alt kümelerinin sayısı 2 ^ n'dir. Bunları 0 ile 2 ^ n -1 arasında bir tamsayı sırayla gösterebiliriz. Bir örnek alın, listeniz olduğunu varsayalım = [1, 3, 5] sonra olası kombinasyonlardan hiçbiri 2 ^ 3 ie 8 değildir. Şimdi tüm kombinasyonları aşağıdaki gibi yazabiliriz:

  1. 000 - [] - 0
  2. 001 - [1] - 1
  3. 010 - [3] -2
  4. 011 - [1,3] - 3
  5. 100 - [5] - 4
  6. 101 - [1,5] - 5
  7. 110 - [3,5] - 6
  8. 111 - [1,3,5] - 7 ve l2, bu durumda, 2 ^ n-1 ile xor alınarak kolayca elde edilebilir.

Çözüm:

def sum_list(lis, n, X):
    """
    This function will return sum of all elemenst whose bit is set to 1 in X
    """
    sum_ = 0
    # print(X)
    for i in range(n):
        if (X & 1<<i ) !=0:
            # print( lis[i], end=" ")
            sum_ += lis[i]
    # print()
    return sum_

def return_list(lis, n, X):
    """
    This function will return list of all element whose bit is set to 1 in X
    """
    new_lis = []
    for i in range(n):
        if (X & 1<<i) != 0:
            new_lis.append(lis[i])
    return new_lis

lis = [5, 6, 2, 10, 2, 3, 4]
n = len(lis)
total = 2**n -1 

result_1 = 0
result_2 = total
result_1_sum = 0
result_2_sum = sum_list(lis,n, result_2)
ans = total
for i in range(total):
    x = (total ^ i)
    sum_x = sum_list(lis, n, x)
    sum_y = sum_list(lis, n, i)

    if abs(sum_x-sum_y) < ans:
        result_1 =  x
        result_2 = i
        result_1_sum = sum_x
        result_2_sum = sum_y
        ans = abs(result_1_sum-result_2_sum)

"""
Produce resultant list
"""

bucket_1 = return_list(lis,n,result_1)
bucket_2 = return_list(lis, n, result_2)

print("Bucket 1 : {}".format(bucket_1))
print("Bucket 2 : {}".format(bucket_2))

Çıktı :

Bucket 1 : [5, 2, 2, 3, 4]
Bucket 2 : [6, 10]

Merhaba, orijinal sorumu okursanız, Açgözlü Yöntemi zaten kullandığımı görebiliyordunuz ve reddedildi. Yine de girişiniz için teşekkür ederiz!
EddieEC

@EddieEC n (dizinin uzunluğu) üzerindeki kısıtlama nedir? Olası tüm kombinasyonları oluşturmak istiyorsanız, temelde bir NP tam problemi olan bir alt küme toplamı problemidir.
vkSinha
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.