किसी सूची के तत्वों का निष्पक्ष विभाजन


12

खिलाड़ियों की रेटिंग की सूची को देखते हुए, मुझे खिलाड़ियों (यानी रेटिंग) को दो समूहों में विभाजित करना आवश्यक है। लक्ष्य टीमों की संचयी रेटिंग के बीच अंतर को कम करना है। इसमें कोई अड़चन नहीं है कि मैं खिलाड़ियों को टीमों में कैसे विभाजित कर सकता हूं (एक टीम में 2 खिलाड़ी हो सकते हैं और दूसरी टीम में 10 खिलाड़ी हो सकते हैं)।

उदाहरण के लिए: [5, 6, 2, 10, 2, 3, 4]लौट जाना चाहिए([6, 5, 3, 2], [10, 4, 2])

मैं इस समस्या को हल करने के लिए एल्गोरिथ्म जानना चाहूंगा। कृपया ध्यान दें कि मैं एक ऑनलाइन प्रोग्रामिंग परिचयात्मक पाठ्यक्रम ले रहा हूं, इसलिए सरल एल्गोरिदम की सराहना की जाएगी।

मैं निम्नलिखित कोड का उपयोग कर रहा हूं, लेकिन किसी कारण से, ऑनलाइन कोड चेकर का कहना है कि यह गलत है।

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)

अद्यतन: मैंने प्रशिक्षकों से संपर्क किया और मुझे बताया गया कि मुझे सभी अलग-अलग संयोजनों की जांच करने के लिए फ़ंक्शन के अंदर एक और "सहायक" फ़ंक्शन को परिभाषित करना चाहिए, फिर मुझे न्यूनतम अंतर की जांच करने की आवश्यकता है।


2
Google "सब्मिट सम प्रॉब्लम"
जॉन कोलमैन

@ जॉनकोनमैन आपके सुझाव के लिए धन्यवाद। क्या आप मुझे सही दिशा में मार्गदर्शन कर सकते हैं कि मेरी समस्या को हल करने के लिए सबसेट रकम का उपयोग कैसे करें?
18

6
इससे भी अधिक विशेष रूप से, आपके पास उप-सम समस्या का एक विशेष मामला है जिसे विभाजन समस्या कहा जाता है । इस पर विकिपीडिया लेख एल्गोरिदम पर चर्चा करता है।
जॉन कोलमैन

4
क्या इससे आपके सवाल का जवाब मिलता है? सूची को दो समान भागों एल्गोरिथ्म में विभाजित करें
kaya3

1
तुम दोनों को धन्यवाद! मैं ईमानदारी से मदद की सराहना करता हूं!
एडीईसी

जवाबों:


4

नोट: सभी संख्याओं का योग विषम होने पर मामले को बेहतर ढंग से संभालने के लिए संपादित किया जाता है।

इस समस्या के लिए Backtracking एक संभावना है।

यह बड़ी मात्रा में मेमोरी की आवश्यकता के बिना, सभी संभावनाओं की पुनरावृत्ति की अनुमति देता है।

जैसे ही एक इष्टतम समाधान पाया जाता है, यह बंद हो जाता है: sum = 0जहां sumसेट ए के तत्वों के योग और सेट बी। तत्वों के योग के बीच का अंतर है: यह जल्द से जल्द बंद हो जाता है sum < 2, मामले को संभालने के लिए जब सभी नंबरों का योग। विषम है, अर्थात 1. न्यूनतम अंतर के अनुरूप। यदि यह वैश्विक राशि सम है, तो न्यूनतम अंतर 1 के बराबर नहीं हो सकता है।

यह समय से पहले परित्याग की एक सरल प्रक्रिया को लागू करने की अनुमति देता है :
एक निश्चित समय पर, यदि sumअधिक है तो सभी शेष तत्वों का योग (यानी ए या बी में नहीं रखा गया है) और वर्तमान में प्राप्त न्यूनतम मूल्य का निरपेक्ष मान है, तो हम परीक्षा देना छोड़ सकते हैं वर्तमान पथ, शेष तत्वों की जांच के बिना। इस प्रक्रिया को इसके साथ अनुकूलित किया गया है:

  • घटते क्रम में इनपुट डेटा को क्रमबद्ध करें
  • प्रत्येक चरण, पहले सबसे संभावित विकल्प की जांच करें: यह एक निकट-इष्टतम समाधान के लिए तेजी से जाने की अनुमति देता है

यहाँ एक छद्म कोड है

प्रारंभ:

  • तत्वों की तरह a[]
  • शेष तत्वों की राशि की गणना करें: sum_back[i] = sum_back[i+1] + a[i];
  • न्यूनतम "अंतर" को इसके अधिकतम मूल्य पर सेट करें: min_diff = sum_back[0];
  • a[0]ए -> में रखो iपरीक्षा तत्व का सूचकांक 1 पर सेट है
  • सेट करें up_down = true;: यह बूलियन इंगित करता है कि क्या हम वर्तमान में आगे (सच्चे) या पिछड़े (झूठे) हैं

घुमाव के दौरान:

  • यदि (up_down): आगे

    • की मदद से समय से पहले परित्याग का परीक्षण करें sum_back
    • सबसे संभावित मूल्य का चयन करें, sumइस पसंद के अनुसार समायोजित करें
    • if (i == n-1): LEAF -> परीक्षण अगर इष्टतम मूल्य में सुधार हुआ है और यदि नया मान 0 (EDIT:) के बराबर है तो वापस लौटें if (... < 2); पीछे जाओ
    • यदि एक पत्ती में नहीं: आगे बढ़ना जारी रखें
  • अगर (updown): पिछड़ा

    • अगर हम यहां पहुंचते हैं i == 0: वापस लौटते हैं
    • यदि यह इस नोड में दूसरा चलना है: दूसरे मूल्य का चयन करें, ऊपर जाएं
    • और: नीचे जाओ
    • दोनों ही मामलों में: नए sumमूल्य का पुनर्गणना करें

यहाँ C ++ में एक कोड है (क्षमा करें, पायथन को नहीं जानते)

#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";
}

यहाँ एकमात्र मुद्दा हमेशा इष्टतम योग नहीं होता है। 0. इसे अच्छी तरह से समझाने के लिए मैं आपको धन्यवाद देता हूं, क्योंकि मैं C ++ को अच्छी तरह से नहीं पढ़ सकता।
एडीसीईसी

यदि इष्टतम योग 0 के बराबर नहीं है, तो कोड सभी संभावनाओं को देखता है, सबसे अच्छा समाधान याद करता है। जिन रास्तों की जांच नहीं की गई है, वे हम निश्चित हैं कि वे इष्टतम नहीं हैं। यह रिटर्न से मेल खाती है if I == 0। मैंने आपके उदाहरण में 10 को 11 से बदलकर इसका परीक्षण किया
डेमियन

3

मुझे लगता है कि आपको अगला अभ्यास खुद से करना चाहिए, अन्यथा आप ज्यादा कुछ नहीं सीखते हैं। इस एक के लिए, यहाँ एक समाधान है जो आपके प्रशिक्षक द्वारा सलाह को लागू करने की कोशिश करता है:

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

आउटपुट:

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

ध्यान दें कि यह आउटपुट आपके वांछित से अलग है, लेकिन दोनों सही हैं।

यह एल्गोरिथ्म इस तथ्य पर आधारित है कि एन तत्वों के साथ दिए गए सेट के सभी संभावित सबसेट को लेने के लिए, आप एन बिट्स के साथ सभी पूर्णांक उत्पन्न कर सकते हैं, और आई-वें बिट के मूल्य के आधार पर आई-वें आइटम का चयन कर सकते हैं। best_distanceशून्य होने के बाद रुकने के लिए मैं आपको कुछ पंक्तियों को जोड़ना चाहता हूं (क्योंकि यह किसी भी बेहतर, निश्चित रूप से नहीं मिल सकता है)।

बिट्स पर थोड़ा (ध्यान दें कि 0bपायथन में एक बाइनरी नंबर के लिए उपसर्ग है):

एक बाइनरी नंबर: 0b0111001 == 0·2⁶+1·2⁵+1·2⁴+1·2³+0·2²+0·2¹+1·2⁰ == 57

1 द्वारा सही स्थानांतरित: 0b0111001 >> 1 == 0b011100 == 28

1 द्वारा छोड़ा गया वाम: 0b0111001 << 1 == 0b01110010 == 114

4 द्वारा सही स्थानांतरित: 0b0111001 >> 4 == 0b011 == 3

बिटवाइज़ &(और):0b00110 & 0b10101 == 0b00100

यह जांचने के लिए कि क्या 5 वां बिट (इंडेक्स 4) 1 है: (0b0111001 >> 4) & 1 == 0b011 & 1 == 1

एक के बाद 7 शून्य: 1 << 7 == 0b10000000

7 वाले: (1 << 7) - 1 == 0b10000000 - 1 == 0b1111111

सभी 3-बिट संयोजन: 0b000==0, 0b001==1, 0b010==2, 0b011==3, 0b100==4, 0b101==5, 0b110==6, 0b111==7(ध्यान दें कि 0b111 + 1 == 0b1000 == 1 << 3)


आपको बहुत - बहुत धन्यवाद! क्या आप बता सकते हैं कि आपने क्या किया? इसके अलावा << का क्या उपयोग है? उदाहरण के लिए ये सामान मैंने कभी नहीं सीखा कि कैसे करना है। लेकिन मुझे पता था कि मुझे सभी संभावनाओं को उत्पन्न करने और एक अंतर के साथ वापसी करने की आवश्यकता है!
एडीईसी

मैंने बाइनरी नंबर और बिट ऑपरेशंस पर एक माइक्रोलेसन जोड़ा
वाल्टर ट्रॉस

आपको संभवतः किसी दूसरे के अंदर फ़ंक्शन को परिभाषित नहीं करना चाहिए।
एएमसी

1
@ अलेक्जेंडरसील यह निर्भर करता है । इस मामले में मुझे लगता है कि यह स्वीकार्य है और स्वच्छता में सुधार करता है, और वैसे भी, यह वही है जो ओपी को उसके प्रशिक्षकों द्वारा सुझाया गया है (अपने प्रश्न में अपडेट देखें)।
वाल्टर ट्रॉस

1
@MiniMax N आइटम के क्रमपरिवर्तन N हैं!, लेकिन उनके सबसेट 2 ^ N हैं: पहला आइटम सबसेट में हो सकता है या नहीं: 2 संभावनाएं; दूसरा आइटम सबसेट में हो सकता है या नहीं: × 2; तीसरा आइटम ... और इतने पर, एन बार।
वाल्टर ट्रॉस

1

निम्नलिखित एल्गोरिथ्म ऐसा करता है:

  • आइटम सॉर्ट करें
  • सूची में सदस्यों को भी डालता है a, सूची में अजीब bशुरू करने के लिए
  • बेतरतीब ढंग से चलता है और बीच में आइटम स्वैप करता है aऔर bअगर परिवर्तन बेहतर के लिए है

मैंने आपके उदाहरण सूची में प्रगति दिखाने के लिए प्रिंट स्टेटमेंट जोड़े हैं:

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

आउटपुट:

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

बहुत बहुत धन्यवाद, लेकिन मैं कुछ भी आयात किए बिना इसे करने वाला हूं।
एडीसीईसी

1

चूंकि मुझे पता है कि मुझे सभी संभावित सूची तैयार करनी है, इसलिए मुझे सभी संभावनाओं को उत्पन्न करने में मदद करने के लिए एक "सहायक" फ़ंक्शन बनाने की आवश्यकता है। ऐसा करने के बाद, मैं न्यूनतम अंतर की जांच करना सही मानता हूं, और उस न्यूनतम अंतर के साथ सूचियों का संयोजन वांछित समाधान है।

सहायक फ़ंक्शन पुनरावर्ती है, और सूचियों के संयोजन की सभी संभावनाओं की जांच करें।

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)

उदाहरण:, r = [1, 2, 2, 3, 5, 4, 2, 4, 5, 5, 2]इष्टतम विभाजन होगा: ([1, 2, 2, 3, 5, 4], [2, 4, 5, 5, 2])के अंतर के साथ 1

r = [73, 7, 44, 21, 43, 42, 92, 88, 82, 70]इष्टतम विभाजन होगा: ([73, 7, 21, 92, 88], [44, 43, 42, 82, 70])के अंतर के साथ 0


1
चूंकि आपने मुझसे पूछा था: यदि आप सीख रहे हैं तो आपका समाधान ठीक है। इसमें केवल एक ही समस्या है, जो आप भाग्यशाली हैं कि अन्य समस्याओं के साथ अन्य समाधानों से पहले यह किक नहीं करता है: यह घातीय स्थान (O (n2ⁿ)) का उपयोग करता है। लेकिन घातांक समय एक समस्या के रूप में लंबे समय से पहले। बहरहाल, घातीय स्थान का उपयोग करने से बचना आसान होगा।
वाल्टर ट्रॉस

1

यहाँ एक काफी विस्तृत उदाहरण है, जिसका उद्देश्य प्रदर्शन के बजाय शैक्षिक उद्देश्यों के लिए है। यह कुछ दिलचस्प पायथन अवधारणाओं का परिचय देता है जैसे कि सूची समझ और जनरेटर, साथ ही पुनरावृत्ति का एक अच्छा उदाहरण जिसमें फ्रिंज मामलों को उचित रूप से जांचने की आवश्यकता होती है। एक्सटेंशन, उदाहरण के लिए केवल समान संख्या में खिलाड़ियों वाली टीमें ही मान्य हैं, उपयुक्त व्यक्तिगत कार्यों में इसे लागू करना आसान है।

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)

आउटपुट:

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

यह देखते हुए कि आप चाहते हैं कि टीमों को भी आप प्रत्येक टीम की रेटिंग का लक्ष्य स्कोर पता है। यह 2 से विभाजित रेटिंग का योग है।

तो निम्नलिखित कोड को वही करना चाहिए जो आप चाहते हैं।

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)

उत्पादन

first_strong_ratings 
[6, 10]

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

अन्य विभाजन हैं जो समान हैं fairnessये सभी strong_ratings tuple के अंदर खोजने के लिए उपलब्ध हैं, मैं बस पहले एक को देखना चुनता हूं क्योंकि यह हमेशा किसी भी रेटिंग सूची के लिए मौजूद होगा जिसे आप (प्रदान len(ratings) > 1) करते हैं।


इस प्रश्न की चुनौती कुछ भी आयात नहीं करना था जैसा कि मैंने अपने प्रश्न में उल्लेख किया है। आपके इनपुट के लिए धन्यवाद!
एडी डे

0

एक लालची समाधान एक उप-इष्टतम समाधान प्राप्त कर सकता है। यहाँ एक काफी सरल लालची समाधान है, यह विचार है कि बाल्टी में रेटिंग के अतिरिक्त के प्रभाव को कम करने के लिए सूची को अवरोही क्रम में क्रमबद्ध किया जाए। रेटिंग को उस बाल्टी में जोड़ा जाएगा जिसकी कुल रेटिंग राशि कम है

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

आउटपुट:

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

संपादित करें:

एक अन्य दृष्टिकोण सूची के सभी संभव सबसेट को उत्पन्न करना होगा। मान लीजिए कि आपके पास l1 है जो सूची के सबसेट में से एक है, तो आप आसानी से l2 सूची प्राप्त कर सकते हैं जैसे कि l2 = सूची (मूल) - l1। आकार n की सूची के सभी संभावित सबसेट की संख्या 2 ^ n है। हम उन्हें 0 से 2 ^ n -1 से पूर्णांक के seq के रूप में निरूपित कर सकते हैं। एक उदाहरण लें, कहते हैं कि आपके पास सूची है [[१, ३, ५] फिर कोई भी संभावित संयोजन २ ^ ३ अर्थात Now नहीं है। अब हम निम्नलिखित के रूप में सभी संयोजन लिख सकते हैं:

  1. 000 - [] - 0
  2. 001 - [1] - 1
  3. ०१० - [३] - २
  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 और l2, इस मामले में, आसानी से 2 ^ n-1 के साथ xor लेकर प्राप्त किया जा सकता है।

समाधान:

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

आउटपुट:

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

नमस्ते, यदि आप मेरे मूल प्रश्न को पढ़ते हैं, तो आप देख सकते हैं कि मैंने पहले से ही लालची विधि का उपयोग किया था, और इसे अस्वीकार कर दिया गया था। हालांकि आपके इनपुट के लिए धन्यवाद!
ईडीईसीईसी

@EddieEC n (व्यूह की लंबाई) पर कसना है। यदि आप सभी संभव संयोजन उत्पन्न करना चाहते हैं तो यह मूल रूप से एक सबसेट समस्या है, जो एनपी-पूर्ण समस्या है।
vkSinha
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.