একটি তালিকার উপাদানগুলির সুষ্ঠু বিভাজন


12

খেলোয়াড়দের রেটিংয়ের একটি তালিকা দেওয়া, আমাকে খেলোয়াড়দের (যেমন রেটিং) যথাসম্ভব দুটি গ্রুপে বিভক্ত করা দরকার। দলগুলির संचयी রেটিংয়ের মধ্যে পার্থক্য হ্রাস করা লক্ষ্য। আমি কীভাবে খেলোয়াড়দের দলে বিভক্ত করতে পারি তার কোনও বাধা নেই (একটি দলে 2 জন খেলোয়াড় থাকতে পারে এবং অন্য দলে 10 জন খেলোয়াড় থাকতে পারে)।

উদাহরণস্বরূপ: [5, 6, 2, 10, 2, 3, 4]ফিরে আসা উচিত([6, 5, 3, 2], [10, 4, 2])

আমি এই সমস্যাটি সমাধানের জন্য অ্যালগরিদমটি জানতে চাই। দয়া করে নোট করুন আমি একটি অনলাইন প্রোগ্রামিং প্রবর্তক কোর্স নিচ্ছি, তাই সাধারণ অ্যালগরিদমগুলি প্রশংসিত হবে।

আমি নিম্নলিখিত কোডটি ব্যবহার করছি তবে কোনও কারণে অনলাইন কোড চেকার বলছেন এটি ভুল rect

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
গুগল "সাবসেটের সমষ্টি সমস্যা"
জন কোলেম্যান

@ জনকোলম্যান আপনার পরামর্শের জন্য আপনাকে ধন্যবাদ আপনি কীভাবে আমার সমস্যা সমাধানের জন্য সাবসেট যোগফলগুলি ব্যবহার করবেন সে সম্পর্কে আমাকে সঠিক দিক নির্দেশনা দিতে পারেন?
এডিইইসি

6
আরও সুনির্দিষ্টভাবে আপনার কাছে সাবসেট-সম সমস্যার একটি বিশেষ কেস রয়েছে যা পার্টিশন সমস্যা বলে । এতে উইকিপিডিয়া নিবন্ধ আলগোরিদিমগুলি নিয়ে আলোচনা করেছে।
জন কোলেম্যান


1
দুজন কেই ধন্যবাদ! আমি আন্তরিকভাবে সাহায্যের প্রশংসা করি!
এডিইইসি

উত্তর:


4

দ্রষ্টব্য: সমস্ত সংখ্যার যোগফল বিজোড় হলে কেসটি আরও ভালভাবে পরিচালনা করতে সম্পাদিত।

ব্যাকট্র্যাকিং এই সমস্যার সম্ভাবনা।

এটি প্রচুর পরিমাণে মেমরির প্রয়োজন ছাড়াই সমস্ত সম্ভাবনাগুলি পুনরাবৃত্তভাবে পরীক্ষা করার অনুমতি দেয়।

এটি সর্বোত্তম সমাধানটি পাওয়া মাত্রই থামবে: sum = 0যেখানে wheresum মাত্রই থামবে:, সেট এ এর ​​উপাদানগুলির সমষ্টি এবং সেট বি এর উপাদানের যোগফলের মধ্যে পার্থক্য : sum < 2সমস্ত সংখ্যার যোগফলের ক্ষেত্রে কেসটি পরিচালনা করার জন্য এটি যত তাড়াতাড়ি থামে বিজোড়, অর্থাত্ সর্বনিম্ন 1 পার্থক্যের সাথে সম্পর্কিত this

এটি অকাল ত্যাগের একটি সহজ প্রক্রিয়া বাস্তবায়নের অনুমতি দেয় :
একটি নির্দিষ্ট সময়ে, যদি 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) :) এর ; পিছনে যেতে
    • কোনও পাতায় না থাকলে: এগিয়ে যেতে চালিয়ে যান
  • যদি (! আপডেটাউন): পিছনে

    • যদি আমরা এখানে পৌঁছান i == 0: ফিরে আসুন
    • যদি এটি এই নোডের দ্বিতীয় পদচারণা হয়: দ্বিতীয় মানটি নির্বাচন করুন, উপরে যান
    • অন্য: নীচে যান
    • উভয় ক্ষেত্রেই: নতুন sumমানটি পুনরায় গণনা করুন

এখানে সি ++ তে একটি কোড রয়েছে (দুঃখিত, পাইথন জানেন না)

#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 হয় না এটি যথেষ্ট ভালভাবে ব্যাখ্যা করার জন্য আপনাকে ধন্যবাদ, কারণ আমি সি ++ ভালভাবে পড়তে পারি না।
এডিইইসি

যদি সর্বোত্তম যোগফল 0 এর সমান না হয় তবে কোডটি সমস্ত সম্ভাবনার দিকে নজর দেয়, সেরা সমাধানটি মুখস্থ করে। যে পথগুলি পরীক্ষা করা হয় না সেগুলি হ'ল আমরা নিশ্চিত যে তারা অনুকূল নয় not এটি রিটার্নের সাথে মিলে যায় 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

bitwise & (এবং):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
@ মনিম্যাক্স এন আইটেমগুলির ক্রিয়াকলাপ হ'ল এন !, দ্বিতীয় আইটেমটি সাবসেটে থাকতে পারে বা না: × 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বিভক্ততা রয়েছে যা এই একই রয়েছে সবগুলি স্ট্রং_রেটিংস টিপলের ভিতরে সন্ধান করার জন্য, আমি কেবলমাত্র প্রথমটিকে দেখতে পছন্দ করি কারণ আপনি যে রেটিং তালিকায় পাস করেছেন (প্রদত্ত 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]

সম্পাদনা:

আর একটি পদ্ধতির তালিকার সমস্ত সম্ভাব্য উপসেট তৈরি করা হবে। ধরা যাক আপনার কাছে এল 1 রয়েছে যা তালিকার অন্যতম উপগ্রহ, তারপরে আপনি সহজেই এল 2 তালিকাটি পেতে পারেন যেমন l2 = তালিকা (মূল) - l1। আকার n এর তালিকার সমস্ত সম্ভাব্য সাবসেটের সংখ্যা 2 ^ n। আমরা তাদের 0 থেকে 2 ^ n -1 এর মধ্যে একটি পূর্ণসংখ্যার বর্গ হিসাবে চিহ্নিত করতে পারি। একটি উদাহরণ নিন, বলুন আপনার তালিকা = [[1, 3, 5]] তবে সম্ভাব্য সংমিশ্রণের কোনওটি 2 ^ 3 অর্থাৎ 8 নয় Now এখন আমরা সমস্ত সংমিশ্রকে অনুসরণ করে লিখতে পারি:

  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 এবং l2, এক্ষেত্রে 2 ^ n-1 দিয়ে জোওর নিয়ে সহজেই পাওয়া যায়।

সমাধান:

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]

হ্যালো, আপনি যদি আমার আসল প্রশ্নটি পড়ে থাকেন তবে আপনি দেখতে পাবেন যে আমি ইতিমধ্যে লোভী পদ্ধতিটি ব্যবহার করেছি এবং এটি প্রত্যাখ্যান করা হয়েছিল। যদিও আপনার ইনপুট জন্য ধন্যবাদ!
এডিইইসিইসি

@ এডিইইসি- কে n (অ্যারে এর দৈর্ঘ্য) বাধা কী? আপনি যদি সমস্ত সম্ভাব্য সংমিশ্রণ উত্পন্ন করতে চান তবে এটি মূলত একটি উপসেট যোগ সমস্যা, যা এনপি-সম্পূর্ণ সমস্যা।
vkSinha
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.