Faire Aufteilung von Elementen einer Liste

12

Angesichts einer Liste von Bewertungen von Spielern muss ich die Spieler (dh Bewertungen) so fair wie möglich in zwei Gruppen aufteilen. Ziel ist es, den Unterschied zwischen der kumulierten Bewertung der Teams zu minimieren. Es gibt keine Einschränkungen, wie ich die Spieler in die Teams aufteilen kann (ein Team kann 2 Spieler haben und das andere Team kann 10 Spieler haben).

Zum Beispiel: [5, 6, 2, 10, 2, 3, 4]sollte zurückkehren([6, 5, 3, 2], [10, 4, 2])

Ich würde gerne den Algorithmus kennen, um dieses Problem zu lösen. Bitte beachten Sie, dass ich an einem Online-Programmier-Einführungskurs teilnehme, daher wären einfache Algorithmen willkommen.

Ich verwende den folgenden Code, aber aus irgendeinem Grund sagt der Online-Codeprüfer, dass er falsch ist.

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)

Update: Ich habe die Instruktoren kontaktiert und mir wurde gesagt, ich sollte eine andere "Hilfs" -Funktion innerhalb der Funktion definieren, um alle verschiedenen Kombinationen zu überprüfen, dann muss ich nach dem minimalen Unterschied suchen.

EddieEC
quelle
2
Google "Subset Sum Problem"
John Coleman
@ JohnColeman danke für deinen Vorschlag. Können Sie mich bitte in die richtige Richtung führen, wie ich Teilmengen zur Lösung meines Problems verwenden kann?
EddieEC
6
Insbesondere haben Sie einen Sonderfall des Teilmengen-Summen-Problems, das als Partitionsproblem bezeichnet wird . Der Wikipedia-Artikel beschreibt Algorithmen.
John Coleman
4
Beantwortet das deine Frage? Teilen Sie die Liste in zwei gleiche Teile Algorithmus
kaya3
1
Danke euch beiden! Ich freue mich sehr über die Hilfe!
EddieEC

Antworten:

4

Hinweis: Bearbeitet, um den Fall besser zu behandeln, wenn die Summe aller Zahlen ungerade ist.

Backtracking ist eine Möglichkeit für dieses Problem.

Es ermöglicht die rekursive Prüfung aller Möglichkeiten, ohne dass viel Speicher benötigt wird.

Es stoppt, sobald eine optimale Lösung gefunden wurde: sum = 0Wo sumist die Differenz zwischen der Summe der Elemente von Satz A und der Summe der Elemente von Satz B. BEARBEITEN: Es stoppt, sobald sum < 2der Fall behandelt wird, wenn die Summe aller Zahlen ist ungerade, dh entspricht einer minimalen Differenz von 1. Wenn diese globale Summe gerade ist, kann die minimale Differenz nicht gleich 1 sein.

Es ermöglicht die Implementierung eines einfachen Verfahrens der vorzeitigen Aufgabe :
Wenn zu einem bestimmten Zeitpunkt sumdie Summe aller verbleibenden Elemente (dh nicht in A oder B platziert) plus dem absoluten Wert des erhaltenen aktuellen Minimums höher ist, können wir die Prüfung aufgeben den aktuellen Pfad, ohne die verbleibenden Elemente zu untersuchen. Dieses Verfahren wird optimiert mit:

  • Sortieren Sie die Eingabedaten in absteigender Reihenfolge
  • Untersuchen Sie bei jedem Schritt zunächst die wahrscheinlichste Wahl: So können Sie schnell zu einer nahezu optimalen Lösung gelangen

Hier ist ein Pseudocode

Initialisierung:

  • Elemente sortieren a[]
  • Berechnen Sie die Summe der verbleibenden Elemente: sum_back[i] = sum_back[i+1] + a[i];
  • Stellen Sie die minimale "Differenz" auf ihren Maximalwert ein: min_diff = sum_back[0];
  • Geben Sie a[0]A -> ein. Der Index ides untersuchten Elements wird auf 1 gesetzt
  • Set up_down = true;: Dieser Boolesche Wert gibt an, ob wir gerade vorwärts (wahr) oder rückwärts (falsch) gehen.

While-Schleife:

  • If (up_down): vorwärts

    • Testen Sie vorzeitigen Abbruch mit Hilfe von sum_back
    • Wählen Sie den wahrscheinlichsten Wert und passen Sie ihn sumentsprechend dieser Auswahl an
    • if (i == n-1): LEAF -> Test, ob der optimale Wert verbessert wurde, und Rückgabe, wenn der neue Wert gleich 0 ist (EDIT :) if (... < 2); Gehe zurück
    • Wenn nicht in einem Blatt: weiter vorwärts
  • If (! Updown): rückwärts

    • Wenn wir ankommen i == 0: zurück
    • Wenn es der zweite Schritt in diesem Knoten ist: Wählen Sie den zweiten Wert aus und gehen Sie nach oben
    • sonst: geh runter
    • In beiden Fällen: Berechnen Sie den neuen sumWert neu

Hier ist ein Code in C ++ (Entschuldigung, ich kenne Python nicht)

#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";
}
Damien
quelle
Das einzige Problem hierbei ist, dass nicht immer die optimale Summe 0 ist. Ich danke Ihnen, dass Sie es recht gut erklärt haben, da ich C ++ nicht gut lesen kann.
EddieEC
Wenn die optimale Summe nicht gleich 0 ist, prüft der Code alle Möglichkeiten und merkt sich die beste Lösung. Die nicht untersuchten Pfade sind diejenigen, von denen wir sicher sind, dass sie nicht optimal sind. Dies entspricht der Rückgabe if I == 0. Ich habe es getestet, indem ich in Ihrem Beispiel 10 durch 11 ersetzt habe
Damien
3

Ich denke, du solltest die nächste Übung alleine machen, sonst lernst du nicht viel. Hier ist eine Lösung, die versucht, den Rat Ihres Lehrers umzusetzen:

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))

Ausgabe:

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

Beachten Sie, dass sich diese Ausgabe von der gewünschten unterscheidet, aber beide korrekt sind.

Dieser Algorithmus basiert auf der Tatsache, dass Sie zum Auswählen aller möglichen Teilmengen einer gegebenen Menge mit N Elementen alle ganzen Zahlen mit N Bits generieren und das I-te Element abhängig vom Wert des I-ten Bits auswählen können. Ich überlasse es Ihnen, ein paar Zeilen hinzuzufügen, um anzuhalten, sobald der best_distanceWert Null ist (weil es natürlich nicht besser werden kann).

Bit für Bit (beachten Sie, dass dies 0bdas Präfix für eine Binärzahl in Python ist):

Eine Binärzahl: 0b0111001 == 0·2⁶+1·2⁵+1·2⁴+1·2³+0·2²+0·2¹+1·2⁰ == 57

Rechts um 1 verschoben: 0b0111001 >> 1 == 0b011100 == 28

Links um 1 verschoben: 0b0111001 << 1 == 0b01110010 == 114

Rechts um 4 verschoben: 0b0111001 >> 4 == 0b011 == 3

Bitweise &(und):0b00110 & 0b10101 == 0b00100

So prüfen Sie, ob das 5. Bit (Index 4) 1 ist: (0b0111001 >> 4) & 1 == 0b011 & 1 == 1

Eine Eins gefolgt von 7 Nullen: 1 << 7 == 0b10000000

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

Alle 3-Bit - Kombinationen: 0b000==0, 0b001==1, 0b010==2, 0b011==3, 0b100==4, 0b101==5, 0b110==6, 0b111==7(Hinweis : 0b111 + 1 == 0b1000 == 1 << 3)

Walter Tross
quelle
Ich danke dir sehr! Können Sie bitte erklären, was Sie getan haben? Was nützt auch <<? Diese Sachen zum Beispiel habe ich noch nie gelernt. Aber ich wusste, dass ich alle Möglichkeiten generieren und die mit dem geringsten Unterschied zurückgeben musste!
EddieEC
Ich habe eine Mikrolektion über Binärzahlen und Bitoperationen hinzugefügt
Walter Tross
Sie sollten wahrscheinlich keine Funktion in einer anderen definieren.
AMC
1
@ AlexanderCécile es kommt darauf an . In diesem Fall denke ich, dass es akzeptabel ist und die Sauberkeit verbessert, und es ist sowieso das, was das OP von seinen Ausbildern vorgeschlagen wurde (siehe das Update in seiner Frage).
Walter Tross
1
@MiniMax die Permutationen von N Elementen sind N!, Aber ihre Teilmengen sind 2 ^ N: das erste Element kann in der Teilmenge sein oder nicht: 2 Möglichkeiten; Das zweite Element kann in der Teilmenge enthalten sein oder nicht: × 2; der dritte Punkt ... und so weiter, N-mal.
Walter Tross
1

Der folgende Algorithmus macht das:

  • sortiert die Elemente
  • Setzt gerade Mitglieder in die Liste a, ungerade in die Liste b, um zu beginnen
  • bewegt und tauscht zufällig Gegenstände zwischen aund bwenn die Änderung zum Besseren ist

Ich habe Druckanweisungen hinzugefügt, um den Fortschritt in Ihrer Beispielliste anzuzeigen:

# -*- 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')  

Ausgabe:

  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]) 
Paddy3118
quelle
Vielen Dank, aber ich soll es tun, ohne etwas zu importieren.
EddieEC
1

Da ich weiß, dass ich alle möglichen Listen generieren muss, muss ich eine "Hilfs" -Funktion erstellen, um alle Möglichkeiten zu generieren. Danach überprüfe ich den minimalen Unterschied, und die Kombination von Listen mit diesem minimalen Unterschied ist die gewünschte Lösung.

Die Hilfsfunktion ist rekursiv und prüft auf alle Möglichkeiten von Listenkombinationen.

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)

Beispiele: r = [1, 2, 2, 3, 5, 4, 2, 4, 5, 5, 2]Die optimale Partition wäre: ([1, 2, 2, 3, 5, 4], [2, 4, 5, 5, 2])mit einem Unterschied von 1.

r = [73, 7, 44, 21, 43, 42, 92, 88, 82, 70]wäre die optimale Partition: ([73, 7, 21, 92, 88], [44, 43, 42, 82, 70])mit einem Unterschied von 0.

EddieEC
quelle
1
seit du mich gefragt hast: deine lösung ist in ordnung wenn du lernst. Es gibt nur ein Problem, das Sie glücklicherweise nicht vor dem anderen Problem lösen, das es mit anderen Lösungen gemeinsam hat: Es verwendet den exponentiellen Raum (O (n2ⁿ)). Aber die exponentielle Zeit tritt schon lange zuvor als Problem auf. Es wäre jedoch einfach, die Verwendung des exponentiellen Raums zu vermeiden.
Walter Tross
1

Hier ist ein ziemlich ausführliches Beispiel, das eher für Bildungszwecke als für Aufführungszwecke gedacht ist. Es werden einige interessante Python-Konzepte wie Listenverständnis und Generatoren sowie ein gutes Beispiel für eine Rekursion vorgestellt, bei der Randfälle angemessen überprüft werden müssen. Erweiterungen, zB nur Teams mit gleicher Anzahl von Spielern, sind in den entsprechenden Einzelfunktionen einfach zu implementieren.

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)

Ausgabe:

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]
****************************************
Sander
quelle
1

Wenn Sie sogar Teams wollen, kennen Sie die Zielpunktzahl der Bewertungen jedes Teams. Dies ist die Summe der Bewertungen geteilt durch 2.

Der folgende Code sollte also tun, was Sie wollen.

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)

Ausgabe

first_strong_ratings 
[6, 10]

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

Es gibt andere Splits, die die gleichen haben, die fairnessalle im Tupel strong_ratings verfügbar sind. Ich schaue mir nur den ersten an, da dieser für jede Bewertungsliste, die Sie übergeben (vorausgesetzt len(ratings) > 1), immer vorhanden ist .

WGP
quelle
Die Herausforderung dieser Frage bestand darin, nichts zu importieren, wie ich in meiner Frage erwähnt habe. Danke für deinen Beitrag!
EddieEC
0

Eine gierige Lösung kann zu einer suboptimalen Lösung führen. Hier ist eine ziemlich einfache gierige Lösung. Die Idee ist, die Liste in absteigender Reihenfolge zu sortieren, um den Effekt des Hinzufügens von Bewertungen im Bucket zu verringern. Die Bewertung wird dem Eimer hinzugefügt, dessen Gesamtbewertungssumme geringer ist

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))

Ausgabe :

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

Bearbeiten:

Ein anderer Ansatz besteht darin, alle möglichen Teilmengen der Liste zu generieren. Angenommen, Sie haben l1, eine der Teilmengen der Liste, dann können Sie die Liste l2 leicht so abrufen, dass l2 = Liste (Original) - l1. Die Nummer aller möglichen Teilmengen der Liste der Größe n ist 2 ^ n. Wir können sie als Folge einer ganzen Zahl von 0 bis 2 ^ n -1 bezeichnen. Nehmen Sie ein Beispiel, sagen Sie, Sie haben list = [1, 3, 5], dann ist keine der möglichen Kombinationen 2 ^ 3, dh 8. Jetzt können wir alle Kombinationen wie folgt schreiben:

  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 und 12 können in diesem Fall leicht erhalten werden, indem xor mit 2 ^ n-1 genommen wird.

Lösung:

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))

Ausgabe :

Bucket 1 : [5, 2, 2, 3, 4]
Bucket 2 : [6, 10]
vkSinha
quelle
Hallo, wenn Sie meine ursprüngliche Frage lesen, können Sie sehen, dass ich die Greedy-Methode bereits verwendet habe und sie abgelehnt wurde. Vielen Dank für Ihre Eingabe!
EddieEC
@EddieEC Was ist die Einschränkung für n (Länge des Arrays). Wenn Sie alle möglichen Kombinationen generieren möchten, handelt es sich im Grunde genommen um ein Teilmengen-Summenproblem, bei dem es sich um ein NP-vollständiges Problem handelt.
vkSinha