প্রদত্ত অঙ্কে পৌঁছানোর জন্য সমস্ত সংখ্যার সম্ভাব্য সংমিশ্রণ সন্ধান করা


232

আপনি প্রদত্ত Nসংখ্যার সেট থেকে সংযোজনগুলির সমস্ত সম্ভাব্য সংমিশ্রণগুলি পরীক্ষা করার বিষয়ে কীভাবে যাবেন যাতে তারা প্রদত্ত চূড়ান্ত সংখ্যাটি যুক্ত করে?

সংক্ষিপ্ত উদাহরণ:

  • সংখ্যার সেট যোগ করতে: N = {1,5,22,15,0,...}
  • কাঙ্ক্ষিত ফলাফল: 12345

@ জেমস - আমি মনে করি আপনার সমস্যাটি পরিষ্কার করা দরকার। নিয়ম কি? আপনি কি কোনও সংখ্যা বাছাই করতে পারেন? সেটে কী সংখ্যা? আপনার বাধা কি?
jmort253

9
উইকিপিডিয়া নিবন্ধ ( en.wikedia.org/wiki/Subset_sum_problem ) এমনকি উল্লেখ করেছে যে এই সমস্যাটি এনপি-সম্পূর্ণ সমস্যার শ্রেণীর একটি ভাল ভূমিকা is
user57368

1
@ জেএমর্ট ২৫৩: আমি মনে করি না যে পূর্ণসংখ্যার একটি সেট থাকা ব্যতীত অন্য কোনও বাধা আছে যা লক্ষ্য হিসাবে প্রদত্ত সংখ্যার চেয়ে ইতিবাচক এবং কম। সংখ্যার যে কোনও সংমিশ্রণ ব্যবহার করা যেতে পারে। এটি হোম ওয়ার্ক নয় বরং যে ধরণের সমস্যার সমাধান রয়েছে তা যদি আপনি কিছু কাজের জন্য আবেদন করেন তবে তা সমাধান করার জন্য আপনাকে দেওয়া হবে। আমি যখন প্রয়োজন হয় তখন সাধারণত একটি অ্যালগরিদম ভাবতে পারি তবে আমি কীভাবে এ জাতীয় কিছু দেখতে হবে তা নিশ্চিত নই। এটি কোনওভাবে পচে যাওয়া প্রয়োজন (পুনরাবৃত্তির?)।
জেমস পি।

3
@ জেমস, আপনার কি সংমিশ্রণগুলি প্রয়োজন বা যোগফলের যোগ হওয়া সাবসেটের কেবল সংখ্যার দরকার?
st0le

6
আমরা কি মূল সেটটির একই উপাদানটিকে একাধিকবার ব্যবহার করতে পারি? উদাহরণস্বরূপ, যদি ইনপুটটি {1,2,3,5} এবং 10 লক্ষ্য হয় তবে 5 + 5 = 10 একটি গ্রহণযোগ্য সমাধান?
আলামপাডা

উত্তর:


248

এই সমস্যাটি সমাধানে পৌঁছানোর সম্ভাব্য সমস্ত সংখ্যার একটি পুনরাবৃত্ত সংমিশ্রণগুলির সাথে সমাধান করা যেতে পারে যা লক্ষ্যে পৌঁছায়। পাইথনের আলগোরিদিম এখানে:

def subset_sum(numbers, target, partial=[]):
    s = sum(partial)

    # check if the partial sum is equals to target
    if s == target: 
        print "sum(%s)=%s" % (partial, target)
    if s >= target:
        return  # if we reach the number why bother to continue

    for i in range(len(numbers)):
        n = numbers[i]
        remaining = numbers[i+1:]
        subset_sum(remaining, target, partial + [n]) 


if __name__ == "__main__":
    subset_sum([3,9,8,4,5,7,10],15)

    #Outputs:
    #sum([3, 8, 4])=15
    #sum([3, 5, 7])=15
    #sum([8, 7])=15
    #sum([5, 10])=15

নিম্নলিখিত স্ট্যান্ডফোর্ডের অ্যাবস্ট্রাক্ট প্রোগ্রামিং বক্তৃতাতে এই ধরণের অ্যালগরিদমগুলি খুব ভালভাবে ব্যাখ্যা করা হয়েছে - পুনরাবৃত্তি কীভাবে সমাধানের অনুমতিগুলি তৈরি করতে কাজ করে তা বোঝার জন্য এই ভিডিওটি খুব সুপারিশযোগ্য।

সম্পাদন করা

উপরেরটিকে একটি জেনারেটর ফাংশন হিসাবে এটিকে কিছুটা দরকারী করে তোলে। পাইথন 3.3+ প্রয়োজন কারণ yield from

def subset_sum(numbers, target, partial=[], partial_sum=0):
    if partial_sum == target:
        yield partial
    if partial_sum >= target:
        return
    for i, n in enumerate(numbers):
        remaining = numbers[i + 1:]
        yield from subset_sum(remaining, target, partial + [n], partial_sum + n)

এখানে একই অ্যালগরিদমের জাভা সংস্করণটি রয়েছে:

package tmp;

import java.util.ArrayList;
import java.util.Arrays;

class SumSet {
    static void sum_up_recursive(ArrayList<Integer> numbers, int target, ArrayList<Integer> partial) {
       int s = 0;
       for (int x: partial) s += x;
       if (s == target)
            System.out.println("sum("+Arrays.toString(partial.toArray())+")="+target);
       if (s >= target)
            return;
       for(int i=0;i<numbers.size();i++) {
             ArrayList<Integer> remaining = new ArrayList<Integer>();
             int n = numbers.get(i);
             for (int j=i+1; j<numbers.size();j++) remaining.add(numbers.get(j));
             ArrayList<Integer> partial_rec = new ArrayList<Integer>(partial);
             partial_rec.add(n);
             sum_up_recursive(remaining,target,partial_rec);
       }
    }
    static void sum_up(ArrayList<Integer> numbers, int target) {
        sum_up_recursive(numbers,target,new ArrayList<Integer>());
    }
    public static void main(String args[]) {
        Integer[] numbers = {3,9,8,4,5,7,10};
        int target = 15;
        sum_up(new ArrayList<Integer>(Arrays.asList(numbers)),target);
    }
}

এটা ঠিক একই ধর্মীয়। আমার জাভা কিছুটা মরিচা তবে আমি মনে করি এটি বুঝতে সহজ।

সি # জাভা সমাধানের রূপান্তর: (@ জেরেমি থম্পসন দ্বারা)

public static void Main(string[] args)
{
    List<int> numbers = new List<int>() { 3, 9, 8, 4, 5, 7, 10 };
    int target = 15;
    sum_up(numbers, target);
}

private static void sum_up(List<int> numbers, int target)
{
    sum_up_recursive(numbers, target, new List<int>());
}

private static void sum_up_recursive(List<int> numbers, int target, List<int> partial)
{
    int s = 0;
    foreach (int x in partial) s += x;

    if (s == target)
        Console.WriteLine("sum(" + string.Join(",", partial.ToArray()) + ")=" + target);

    if (s >= target)
        return;

    for (int i = 0; i < numbers.Count; i++)
    {
        List<int> remaining = new List<int>();
        int n = numbers[i];
        for (int j = i + 1; j < numbers.Count; j++) remaining.Add(numbers[j]);

        List<int> partial_rec = new List<int>(partial);
        partial_rec.Add(n);
        sum_up_recursive(remaining, target, partial_rec);
    }
}

রুবি সমাধান: (@ ইমেলেলিন দ্বারা)

def subset_sum(numbers, target, partial=[])
  s = partial.inject 0, :+
# check if the partial sum is equals to target

  puts "sum(#{partial})=#{target}" if s == target

  return if s >= target # if we reach the number why bother to continue

  (0..(numbers.length - 1)).each do |i|
    n = numbers[i]
    remaining = numbers.drop(i+1)
    subset_sum(remaining, target, partial + [n])
  end
end

subset_sum([3,9,8,4,5,7,10],15)

সম্পাদনা: জটিলতা আলোচনা

অন্যরা যেমন উল্লেখ করেছেন এটি একটি এনপি-হার্ড সমস্যা । এটি সূচকীয় সময়ে হে (2 ^ n) এ সমাধান করা যেতে পারে, উদাহরণস্বরূপ n = 10 এর জন্য 1024 সম্ভাব্য সমাধান থাকবে। আপনি যে লক্ষ্যগুলি পৌঁছানোর চেষ্টা করছেন তা যদি স্বল্প পরিসরে থাকে তবে এই অ্যালগরিদম কাজ করে। উদাহরণস্বরূপ:

subset_sum([1,2,3,4,5,6,7,8,9,10],100000) 1024 টি শাখা উত্পন্ন করে কারণ লক্ষ্যটি কখনই সম্ভাব্য সমাধানগুলি ফিল্টার করে না।

অন্যদিকে subset_sum([1,2,3,4,5,6,7,8,9,10],10)কেবল 175 টি শাখা উত্পন্ন করে, কারণ পৌঁছানোর লক্ষ্যটি 10অনেকগুলি সংমিশ্রণ ফিল্টার করে।

যদি Nএবং Targetবড় সংখ্যা হয় তবে একের সমাধানের আনুমানিক সংস্করণে স্থানান্তর করা উচিত।


1
জাভা অপ্টিমাইজেশন: অ্যারেলিস্ট <Integer> আংশিক_আরক = নতুন অ্যারেলিস্ট <Integer> (আংশিক); partial_rec.add (ঢ); এটি আংশিক একটি অনুলিপি করে। এবং এইভাবে ও (এন) যুক্ত করে। আরও ভাল উপায় হ'ল "আংশিক.এডিডি (এন)" পুনরাবৃত্তি করা এবং তারপরে "আংশিক.রেভ (আংশিক.সাইজ -1) করুন। আমি আপনার কোডটি পুনরায় পুনরুদ্ধার করছি তা নিশ্চিত করার জন্য
খ্রিস্টিয়ান বনজিওর্নো

4
এই সমাধানটি সব ক্ষেত্রে কার্যকর হয় না। বিবেচনা করুন [1, 2, 0, 6, -3, 3], 3- [1,2], [0,3], [3]অনুপস্থিত ক্ষেত্রে যেমন আউটপুটগুলি [6, -3, 3]
ঘটে

11
এছাড়া প্রত্যেক সংযুক্তির জন্য কাজ না করে, উদাহরণস্বরূপ [1, 2, 5], 5শুধুমাত্র আউটপুট [5], যখন [1, 1, 1, 1, 1], [2, 2, 1]এবং [2, 1, 1, 1]সমাধান হয়।
cbrad

3
@cbrad- এর কারণ i+1এটি remaining = numbers[i+1:]। দেখে মনে হচ্ছে অ্যালগোরিদম সদৃশগুলিকে অনুমতি দেয় না।
লিওনিড ভাসিলেভ

1
সদৃশ সহ @cbrad সমাধান এছাড়াও পেতে চান [1, 1, 3]একটি এ চেহারা আছে stackoverflow.com/a/34971783/3684296 (পাইথন)
: Mesa

36

এই সমস্যার সমাধান ইন্টারনেটে এক মিলিয়ন বার দেওয়া হয়েছে। সমস্যাটিকে বলা হয় মুদ্রা পরিবর্তনের সমস্যাHttp://rosettacode.org/wiki/Count_the_coins এবং এর গাণিতিক মডেলটিতে http://jaqm.ro/issues/volume-5,issue-2/pdfs/patterson_harmel.pdf (অথবা গুগল মুদ্রার পরিবর্তন) এর মাধ্যমে সমাধান পেতে পারেন সমস্যা )।

যাইহোক, সাগাদাইয়ের স্কেল সমাধান মজাদার। এই উদাহরণটি 1 বা 0 উত্পাদন করে a পার্শ্ব প্রতিক্রিয়া হিসাবে, এটি কনসোলে সমস্ত সম্ভাব্য সমাধান তালিকাভুক্ত করে। এটি সমাধানটি প্রদর্শন করে, তবে এটি কোনওভাবেই ব্যবহারযোগ্য করে তুলতে ব্যর্থ।

যতটা সম্ভব কার্যকর হওয়ার জন্য, List[List[Int]]কোডটির সমাধানের সংখ্যা (তালিকার তালিকার দৈর্ঘ্য), "সেরা" সমাধান (সংক্ষিপ্ত তালিকা), বা সমস্ত সম্ভাব্য সমাধান পাওয়ার অনুমতি দেওয়ার জন্য একটি কোডটি ফেরত দেওয়া উচিত ।

এখানে একটি উদাহরণ। এটি খুব অদক্ষ, তবে এটি বোঝা সহজ।

object Sum extends App {

  def sumCombinations(total: Int, numbers: List[Int]): List[List[Int]] = {

    def add(x: (Int, List[List[Int]]), y: (Int, List[List[Int]])): (Int, List[List[Int]]) = {
      (x._1 + y._1, x._2 ::: y._2)
    }

    def sumCombinations(resultAcc: List[List[Int]], sumAcc: List[Int], total: Int, numbers: List[Int]): (Int, List[List[Int]]) = {
      if (numbers.isEmpty || total < 0) {
        (0, resultAcc)
      } else if (total == 0) {
        (1, sumAcc :: resultAcc)
      } else {
        add(sumCombinations(resultAcc, sumAcc, total, numbers.tail), sumCombinations(resultAcc, numbers.head :: sumAcc, total - numbers.head, numbers))
      }
    }

    sumCombinations(Nil, Nil, total, numbers.sortWith(_ > _))._2
  }

  println(sumCombinations(15, List(1, 2, 5, 10)) mkString "\n")
}

রান করার সময় এটি প্রদর্শিত হয়:

List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2)
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2)
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2)
List(1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2)
List(1, 1, 1, 1, 1, 2, 2, 2, 2, 2)
List(1, 1, 1, 2, 2, 2, 2, 2, 2)
List(1, 2, 2, 2, 2, 2, 2, 2)
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5)
List(1, 1, 1, 1, 1, 1, 1, 1, 2, 5)
List(1, 1, 1, 1, 1, 1, 2, 2, 5)
List(1, 1, 1, 1, 2, 2, 2, 5)
List(1, 1, 2, 2, 2, 2, 5)
List(2, 2, 2, 2, 2, 5)
List(1, 1, 1, 1, 1, 5, 5)
List(1, 1, 1, 2, 5, 5)
List(1, 2, 2, 5, 5)
List(5, 5, 5)
List(1, 1, 1, 1, 1, 10)
List(1, 1, 1, 2, 10)
List(1, 2, 2, 10)
List(5, 10)

sumCombinations()ফাংশন নিজেই দ্বারা ব্যবহৃত হতে পারে, এবং এর ফলে আরও "বেস্ট" সমাধান (সবচেয়ে কম তালিকা), অথবা সমাধান নম্বর (তালিকার সংখ্যা) প্রদর্শন করে বিশ্লেষণ করা যেতে পারে।

মনে রাখবেন যে এমনকি এটির মতো, প্রয়োজনীয়তা সম্পূর্ণরূপে সন্তুষ্ট নাও হতে পারে। এটি ঘটতে পারে যে সমাধানের প্রতিটি তালিকার ক্রমটি গুরুত্বপূর্ণ। এই জাতীয় ক্ষেত্রে, প্রতিটি তালিকার উপাদানগুলির সংমিশ্রণ থাকায় অনেক সময় নকল করতে হবে। অথবা আমরা কেবল আলাদা যে সংমিশ্রণে আগ্রহী।

উদাহরণস্বরূপ, আমরা বিবেচনা করতে পারি যে List(5, 10)দুটি সংমিশ্রণ দেওয়া উচিত: List(5, 10)এবং List(10, 5)। জন্য List(5, 5, 5)তিন সমন্বয় বা একমাত্র প্রয়োজনীয়তা উপর নির্ভর করে দিতে পারে। পূর্ণসংখ্যার জন্য, তিনটি অনুমান সমান, তবে আমরা যদি "মুদ্রা পরিবর্তনের সমস্যা" এর মতো কয়েন নিয়ে কাজ করি তবে তা হয় না।

প্রয়োজনীয়তাগুলিতেও বলা হয়নি যে প্রতিটি সংখ্যা (বা মুদ্রা) কেবল একবার বা বহুবার ব্যবহৃত হতে পারে কিনা তা নিয়েই প্রশ্ন। আমরা (এবং আমাদের উচিত!) প্রতিটি সংখ্যার সংঘটনগুলির তালিকার তালিকায় সমস্যাটিকে সাধারণীকরণ করতে পারি। এটি বাস্তব জীবনে অনুবাদ করে "মুদ্রার সেট (এবং মুদ্রার মানগুলির সেট নয়) দিয়ে নির্দিষ্ট পরিমাণ অর্থোপার্জনের সম্ভাব্য উপায়গুলি কী" " আসল সমস্যাটি হ'ল এটির একটি নির্দিষ্ট ক্ষেত্রে, যেখানে আমাদের প্রতিটি মুদ্রার যতগুলি সংখ্যক ঘটনা রয়েছে প্রতিটি একক মুদ্রার মান দিয়ে মোট পরিমাণ তৈরি করতে।


14
এই সমস্যাটি মুদ্রা পরিবর্তনের সমস্যার মতো নয়। ওপি সর্বনিম্ন নয়, সমস্ত সংমিশ্রণের জন্য জিজ্ঞাসা করছে। এবং সম্ভবত, সেটে পূর্ণসংখ্যাগুলি নেতিবাচক হতে পারে। সুতরাং, মুদ্রা পরিবর্তন সমস্যার নির্দিষ্ট অনুকূলতা এই সমস্যাটি দিয়ে সম্ভব নয়।
থমাসম্যাকলিওড

5
এবং এছাড়াও এই সমস্যাটি আইটেমগুলির পুনরাবৃত্তি করতে অনুমতি দেয়, আমি নিশ্চিত নই যে ওপি এটি চেয়েছিল, তবে আরও একটি ন্যাপস্যাকের সমস্যা
মার্চকে কৌকব

34

ইন Haskell, :

filter ((==) 12345 . sum) $ subsequences [1,5,22,15,0,..]

এবং জে :

(]#~12345=+/@>)(]<@#~[:#:@i.2^#)1 5 22 15 0 ...

আপনি লক্ষ্য করতে পারেন যে, উভয়ই একই পদ্ধতির গ্রহণ করে এবং সমস্যাটিকে দুটি ভাগে ভাগ করে: পাওয়ার সেটটির প্রতিটি সদস্য উত্পন্ন করুন, এবং প্রতিটি সদস্যের লক্ষ্যকে লক্ষ্য করুন check

অন্যান্য সমাধান আছে তবে এটি সবচেয়ে সোজা।

আপনার কারও একজনের সাহায্য দরকার, না আলাদা পদ্ধতির সন্ধান?


3
বাহ, এটি কিছু সুন্দর সংক্ষিপ্ত কোড। তোমার উত্তরে আমি ভাল আছি আমার মনে হয় সাধারণভাবে অ্যালগোরিদম সম্পর্কে আমার কিছুটা পড়া দরকার। আপনি আমার কৌতূহলকে বাড়িয়ে দেওয়ার সাথে সাথে আমি দুটি ভাষার বাক্য গঠনটি একবারে দেখতে পাব।
জেমস পি।

এটি চেষ্টা করার জন্য আমি হ্যাস্কেলকে ইনস্টল করেছি, অবশ্যই এটি আটকানো যায় না এবং এটি কার্যকর করতে পারে, not in scope: 'subsequences'কোনও পয়েন্টার?
হার্ট সিও

4
@ হার্টকো পার্টিতে কিছুটা দেরি করলেন, তবেimport Data.List
জির

28

একটি জাভাস্ক্রিপ্ট সংস্করণ:

function subsetSum(numbers, target, partial) {
  var s, n, remaining;

  partial = partial || [];

  // sum partial
  s = partial.reduce(function (a, b) {
    return a + b;
  }, 0);

  // check if the partial sum is equals to target
  if (s === target) {
    console.log("%s=%s", partial.join("+"), target)
  }

  if (s >= target) {
    return;  // if we reach the number why bother to continue
  }

  for (var i = 0; i < numbers.length; i++) {
    n = numbers[i];
    remaining = numbers.slice(i + 1);
    subsetSum(remaining, target, partial.concat([n]));
  }
}

subsetSum([3,9,8,4,5,7,10],15);

// output:
// 3+8+4=15
// 3+5+7=15
// 8+7=15
// 5+10=15


কোডটি স্লাইসে একটি ভুল রয়েছে, remaining = numbers.slice(); remaining.slice(i + 1);অন্যথায় numbers.slice(i + 1);সংখ্যাগুলি অ্যারে পরিবর্তন করা উচিত
এমিউস

@ এমিউস, আমি মনে করি এটি সত্য নয়। sliceএকটি (অগভীর) অনুলিপি প্রদান করে, এটি numbersঅ্যারে সংশোধন করে না ।
দারিও সিডল

@ ডারিওসিডল হ্যাঁ, স্লাইস একটি অনুলিপি প্রদান করে, এটি অ্যারে পরিবর্তন করে না, এটি হ'ল বিন্দু, এই কারণেই যদি আপনি এটি পরিবর্তনশীল হিসাবে নির্ধারণ না করেন তবে আপনি এটি পরিবর্তন করবেন না don't এই ক্ষেত্রে, আমি যেমন বুঝতে পেরেছি তেমনি আমাদের একটি পরিবর্তিত সংস্করণও পাস করতে হবে, আসলটি নয়। এই jsfiddle.net/che06t3w/1
Emeeus

1
@ রেদু ... উদাহরণস্বরূপ এটি করার একটি সহজ উপায় হ'ল আমরা আলগোরিদমকে কিছুটা সংশোধন করতে পারি এবং অভ্যন্তরীণ ফাংশনটি ব্যবহার করতে পারি: jsbin.com/lecokaw/edit?js,console
rbarilani

1
প্রদত্ত কোডটি অগত্যা সমস্ত সংমিশ্রণগুলি গ্রহণ করে না .. উদাহরণস্বরূপ [1,2], 3 স্থাপন করা কেবল 1 + 2 = 3 নয় 1 + 1 + 1 বা 2 + 1
জুসিক ওয়াইবুরিটো

12

একই অ্যালগোরিদমের সি ++ সংস্করণ

#include <iostream>
#include <list>
void subset_sum_recursive(std::list<int> numbers, int target, std::list<int> partial)
{
        int s = 0;
        for (std::list<int>::const_iterator cit = partial.begin(); cit != partial.end(); cit++)
        {
            s += *cit;
        }
        if(s == target)
        {
                std::cout << "sum([";

                for (std::list<int>::const_iterator cit = partial.begin(); cit != partial.end(); cit++)
                {
                    std::cout << *cit << ",";
                }
                std::cout << "])=" << target << std::endl;
        }
        if(s >= target)
            return;
        int n;
        for (std::list<int>::const_iterator ai = numbers.begin(); ai != numbers.end(); ai++)
        {
            n = *ai;
            std::list<int> remaining;
            for(std::list<int>::const_iterator aj = ai; aj != numbers.end(); aj++)
            {
                if(aj == ai)continue;
                remaining.push_back(*aj);
            }
            std::list<int> partial_rec=partial;
            partial_rec.push_back(n);
            subset_sum_recursive(remaining,target,partial_rec);

        }
}

void subset_sum(std::list<int> numbers,int target)
{
    subset_sum_recursive(numbers,target,std::list<int>());
}
int main()
{
    std::list<int> a;
    a.push_back (3); a.push_back (9); a.push_back (8);
    a.push_back (4);
    a.push_back (5);
    a.push_back (7);
    a.push_back (10);
    int n = 15;
    //std::cin >> n;
    subset_sum(a, n);
    return 0;
}

11

সি # সংস্করণ @ এসএমএলভাডোরস কোড উত্তরের

void Main()
{
    int[] numbers = {3,9,8,4,5,7,10};
    int target = 15;
    sum_up(new List<int>(numbers.ToList()),target);
}

static void sum_up_recursive(List<int> numbers, int target, List<int> part)
{
   int s = 0;
   foreach (int x in part)
   {
       s += x;
   }
   if (s == target)
   {
        Console.WriteLine("sum(" + string.Join(",", part.Select(n => n.ToString()).ToArray()) + ")=" + target);
   }
   if (s >= target)
   {
        return;
   }
   for (int i = 0;i < numbers.Count;i++)
   {
         var remaining = new List<int>();
         int n = numbers[i];
         for (int j = i + 1; j < numbers.Count;j++)
         {
             remaining.Add(numbers[j]);
         }
         var part_rec = new List<int>(part);
         part_rec.Add(n);
         sum_up_recursive(remaining,target,part_rec);
   }
}
static void sum_up(List<int> numbers, int target)
{
    sum_up_recursive(numbers,target,new List<int>());
}

4

আমি ভেবেছিলাম আমি এই প্রশ্ন থেকে একটি উত্তর ব্যবহার করব তবে আমি পারিনি, তাই আমার উত্তর এখানে is এটি কম্পিউটার প্রোগ্রামগুলির কাঠামো এবং ব্যাখ্যায় একটি উত্তরের একটি পরিবর্তিত সংস্করণ ব্যবহার করছে । আমি মনে করি এটি একটি ভাল পুনরাবৃত্তি সমাধান এবং আরও বিশুদ্ধবাদীদের খুশি করা উচিত।

আমার উত্তরটি স্কালায় রয়েছে (এবং যদি আমার স্কালা সফল হয় তবে ক্ষমাপ্রার্থী, আমি এটি শিখতে শুরু করেছি)। FindSumCombinations পাগলামি পুনরাবৃত্তির dupes প্রতিরোধ করার জন্য সাজানোর এবং অনন্য মূল তালিকা হয়।

def findSumCombinations(target: Int, numbers: List[Int]): Int = {
  cc(target, numbers.distinct.sortWith(_ < _), List())
}

def cc(target: Int, numbers: List[Int], solution: List[Int]): Int = {
  if (target == 0) {println(solution); 1 }
  else if (target < 0 || numbers.length == 0) 0
  else 
    cc(target, numbers.tail, solution) 
    + cc(target - numbers.head, numbers, numbers.head :: solution)
}

এটি ব্যবহার করতে:

 > findSumCombinations(12345, List(1,5,22,15,0,..))
 * Prints a whole heap of lists that will sum to the target *

4
Thank you.. ephemient

আমি অজগর থেকে পিএইচপি রূপান্তর করেছি উপরের যুক্তি ..

<?php
$data = array(array(2,3,5,10,15),array(4,6,23,15,12),array(23,34,12,1,5));
$maxsum = 25;

print_r(bestsum($data,$maxsum));  //function call

function bestsum($data,$maxsum)
{
$res = array_fill(0, $maxsum + 1, '0');
$res[0] = array();              //base case
foreach($data as $group)
{
 $new_res = $res;               //copy res

  foreach($group as $ele)
  {
    for($i=0;$i<($maxsum-$ele+1);$i++)
    {   
        if($res[$i] != 0)
        {
            $ele_index = $i+$ele;
            $new_res[$ele_index] = $res[$i];
            $new_res[$ele_index][] = $ele;
        }
    }
  }

  $res = $new_res;
}

 for($i=$maxsum;$i>0;$i--)
  {
    if($res[$i]!=0)
    {
        return $res[$i];
        break;
    }
  }
return array();
}
?>

4

আরও একটি অজগর সমাধান হ'ল itertools.combinationsমডিউলটি নিম্নরূপ ব্যবহার করা হবে :

#!/usr/local/bin/python

from itertools import combinations

def find_sum_in_list(numbers, target):
    results = []
    for x in range(len(numbers)):
        results.extend(
            [   
                combo for combo in combinations(numbers ,x)  
                    if sum(combo) == target
            ]   
        )   

    print results

if __name__ == "__main__":
    find_sum_in_list([3,9,8,4,5,7,10], 15)

আউটপুট: [(8, 7), (5, 10), (3, 8, 4), (3, 5, 7)]


এটি কাজ করে না যেমন: find_sum_in_list (পরিসর (0,8), 4)। পাওয়া গেছে: [(4,), (0, 4), (1, 3), (0, 1, 3)]। তবে (২, ২) একটি বিকল্পও!
আন্দ্রে আরাউজো

@ আন্ড্রেআরওজো: 0 টি ব্যবহার করার কোনও অর্থ নেই, তবে আপনি যদি (1,8) ব্যবহার করেন তবে itertools.combitions_with_replacement কাজ করে এবং ২,২ আউটপুটও দেয়।
রুবেনিসমে

@ রুবেনিসমে হ্যাঁ, মানুষ! সমস্যা ছিল প্রতিস্থাপন! ধন্যবাদ! ;-)
আন্দ্রে আরাউজো

4

এখানে আর এর একটি সমাধান রয়েছে

subset_sum = function(numbers,target,partial=0){
  if(any(is.na(partial))) return()
  s = sum(partial)
  if(s == target) print(sprintf("sum(%s)=%s",paste(partial[-1],collapse="+"),target))
  if(s > target) return()
  for( i in seq_along(numbers)){
    n = numbers[i]
    remaining = numbers[(i+1):length(numbers)]
    subset_sum(remaining,target,c(partial,n))
  }
}

আমি আর তে একটি সমাধান খুঁজছি, তবে এটি আমার পক্ষে কাজ করে না। উদাহরণস্বরূপ, subset_sum(numbers = c(1:2), target = 5)ফেরৎ "sum(1+2+2)=5"। তবে সংশ্লেষ 1 + 1 + 1 + 1 + 1 অনুপস্থিত। উচ্চ সংখ্যায় লক্ষ্য নির্ধারণ করা (যেমন 20) আরও সংমিশ্রণ অনুপস্থিত।
ফ্রেডরিক

আপনি যা বর্ণনা করছেন তা ফাংশনটি ফিরে আসার উদ্দেশ্যে নয়। গৃহীত উত্তর দেখুন। যে বিষয়টি 2 টি পুনরাবৃত্তি করা হয়েছে এটি আর কীভাবে উত্স সৃষ্টি করে এবং ধারাবাহিকগুলি উপস্থাপিত করে না তার উদ্দেশ্যগত আচরণ নয় an
চিহ্নিত করুন

subset_sum(1:2, 4)কোনও সমাধান ফেরত দেওয়া উচিত নয় কারণ 1 এবং 2 এর সংমিশ্রণ নেই যা 4 যোগ করে my আমার ফাংশনে যা যুক্ত করা দরকার তা iদৈর্ঘ্যের চেয়ে বেশি হলে পলায়নnumbers
মার্ক

3

এখানে একটি জাভা সংস্করণ রয়েছে যা ছোট এন এবং খুব বড় টার্গেটের যোগফলের জন্য ভাল উপযুক্ত, যখন জটিলতা O(t*N)(গতিশীল সমাধান) তাত্পর্যপূর্ণ আলগোরিদমের চেয়ে বেশি। আমার সংস্করণ মধ্যম হামলায় একটি দেখা ব্যবহার করে, একটি সামান্য বিট অর্ডার সর্বোত্তম সাদাসিধা থেকে জটিলতা কমানোর জন্য নাড়াচাড়া সহ O(n*2^n)করার O(2^(n/2))

আপনি যদি 32 এবং 64 এর মধ্যে উপাদানগুলির সাথে সেটগুলির জন্য এটি ব্যবহার করতে চান তবে আপনার intস্টেপ ফাংশনের বর্তমান উপসেটটিকে এমন একটিতে পরিবর্তন করতে longহবে যদিও সেটটির আকার বাড়ার সাথে সাথে পারফরম্যান্স স্পষ্টতই হ্রাস পাবে। আপনি যদি বিজোড় সংখ্যক উপাদানগুলির একটি সেটের জন্য এটি ব্যবহার করতে চান তবে সেটটিকে আরও সংখ্যাযুক্ত করার জন্য আপনার সেটটিতে 0 যুক্ত করা উচিত।

import java.util.ArrayList;
import java.util.List;

public class SubsetSumMiddleAttack {
    static final int target = 100000000;
    static final int[] set = new int[]{ ... };

    static List<Subset> evens = new ArrayList<>();
    static List<Subset> odds = new ArrayList<>();

    static int[][] split(int[] superSet) {
        int[][] ret = new int[2][superSet.length / 2]; 

        for (int i = 0; i < superSet.length; i++) ret[i % 2][i / 2] = superSet[i];

        return ret;
    }

    static void step(int[] superSet, List<Subset> accumulator, int subset, int sum, int counter) {
        accumulator.add(new Subset(subset, sum));
        if (counter != superSet.length) {
            step(superSet, accumulator, subset + (1 << counter), sum + superSet[counter], counter + 1);
            step(superSet, accumulator, subset, sum, counter + 1);
        }
    }

    static void printSubset(Subset e, Subset o) {
        String ret = "";
        for (int i = 0; i < 32; i++) {
            if (i % 2 == 0) {
                if ((1 & (e.subset >> (i / 2))) == 1) ret += " + " + set[i];
            }
            else {
                if ((1 & (o.subset >> (i / 2))) == 1) ret += " + " + set[i];
            }
        }
        if (ret.startsWith(" ")) ret = ret.substring(3) + " = " + (e.sum + o.sum);
        System.out.println(ret);
    }

    public static void main(String[] args) {
        int[][] superSets = split(set);

        step(superSets[0], evens, 0,0,0);
        step(superSets[1], odds, 0,0,0);

        for (Subset e : evens) {
            for (Subset o : odds) {
                if (e.sum + o.sum == target) printSubset(e, o);
            }
        }
    }
}

class Subset {
    int subset;
    int sum;

    Subset(int subset, int sum) {
        this.subset = subset;
        this.sum = sum;
    }
}

3

এটি মুদ্রা পরিবর্তনের সমস্যার মতো

public class CoinCount 
{   
public static void main(String[] args)
{
    int[] coins={1,4,6,2,3,5};
    int count=0;

    for (int i=0;i<coins.length;i++)
    {
        count=count+Count(9,coins,i,0);
    }
    System.out.println(count);
}

public static int Count(int Sum,int[] coins,int index,int curSum)
{
    int count=0;

    if (index>=coins.length)
        return 0;

    int sumNow=curSum+coins[index];
    if (sumNow>Sum)
        return 0;
    if (sumNow==Sum)
        return 1;

    for (int i= index+1;i<coins.length;i++)
        count+=Count(Sum,coins,i,sumNow);

    return count;       
}
}

2

আমি বেশ কয়েক বছর আগে সি ++ দম্পতিতে যে টেবিলগুলি লিখেছিলাম তা ব্যবহার করে খুব দক্ষ অ্যালগরিদম।

আপনি প্রিন্ট 1 সেট করলে এটি সমস্ত সংমিশ্রণ মুদ্রণ করবে (তবে এটি দক্ষ পদ্ধতিটি ব্যবহার করবে না)।

এটি এতই দক্ষ যে এটি 10 ​​মিমি এরও কম 10 ^ 14 টি সংশ্লেষ গণনা করে।

#include <stdio.h>
#include <stdlib.h>
//#include "CTime.h"

#define SUM 300
#define MAXNUMsSIZE 30

#define PRINT 0


long long CountAddToSum(int,int[],int,const int[],int);
void printr(const int[], int);
long long table1[SUM][MAXNUMsSIZE];

int main()
{
    int Nums[]={3,4,5,6,7,9,13,11,12,13,22,35,17,14,18,23,33,54};
    int sum=SUM;
    int size=sizeof(Nums)/sizeof(int);
    int i,j,a[]={0};
    long long N=0;
    //CTime timer1;

    for(i=0;i<SUM;++i) 
        for(j=0;j<MAXNUMsSIZE;++j) 
            table1[i][j]=-1;

    N = CountAddToSum(sum,Nums,size,a,0); //algorithm
    //timer1.Get_Passd();

    //printf("\nN=%lld time=%.1f ms\n", N,timer1.Get_Passd());
    printf("\nN=%lld \n", N);
    getchar();
    return 1;
}

long long CountAddToSum(int s, int arr[],int arrsize, const int r[],int rsize)
{
    static int totalmem=0, maxmem=0;
    int i,*rnew;
    long long result1=0,result2=0;

    if(s<0) return 0;
    if (table1[s][arrsize]>0 && PRINT==0) return table1[s][arrsize];
    if(s==0)
    {
        if(PRINT) printr(r, rsize);
        return 1;
    }
    if(arrsize==0) return 0;

    //else
    rnew=(int*)malloc((rsize+1)*sizeof(int));

    for(i=0;i<rsize;++i) rnew[i]=r[i]; 
    rnew[rsize]=arr[arrsize-1];

    result1 =  CountAddToSum(s,arr,arrsize-1,rnew,rsize);
    result2 =  CountAddToSum(s-arr[arrsize-1],arr,arrsize,rnew,rsize+1);
    table1[s][arrsize]=result1+result2;
    free(rnew);

    return result1+result2;

}

void printr(const int r[], int rsize)
{
    int lastr=r[0],count=0,i;
    for(i=0; i<rsize;++i) 
    {
        if(r[i]==lastr)
            count++;
        else
        {
            printf(" %d*%d ",count,lastr);
            lastr=r[i];
            count=1;
        }
    }
    if(r[i-1]==lastr) printf(" %d*%d ",count,lastr);

    printf("\n");

}

হাই! এর মতো কিছু করার জন্য আমার একটি কোড দরকার, numbers০ সংখ্যার তালিকায় of সংখ্যার সেটগুলির সমস্ত সম্ভাব্য যোগফলগুলি সন্ধান করুন। অঙ্কগুলি সর্বনিম্ন 180, সর্বোচ্চ 191 এর ব্যাপ্তিতে হওয়া উচিত that কোডটি কি তার জন্য সামঞ্জস্য করা যেতে পারে? মেঘে কোডটি কোথায় চালাবেন? আমি কোডেনভিতে কোনও সাফল্যের সাথে চেষ্টা করেছিলাম
পুনরুদ্ধার করুন

2

নীচে এক্সেল ভিবিএ সংস্করণ। আমার এটি ভিবিএতে প্রয়োগ করতে হবে (আমার পছন্দ নয়, আমাকে বিচার করবেন না!), এবং এই পৃষ্ঠায় উত্তরগুলি পদ্ধতির জন্য ব্যবহার করেছেন। অন্যদেরও ভিবিএ সংস্করণ প্রয়োজন হলে আমি আপলোড করছি।

Option Explicit

Public Sub SumTarget()
    Dim numbers(0 To 6)  As Long
    Dim target As Long

    target = 15
    numbers(0) = 3: numbers(1) = 9: numbers(2) = 8: numbers(3) = 4: numbers(4) = 5
    numbers(5) = 7: numbers(6) = 10

    Call SumUpTarget(numbers, target)
End Sub

Public Sub SumUpTarget(numbers() As Long, target As Long)
    Dim part() As Long
    Call SumUpRecursive(numbers, target, part)
End Sub

Private Sub SumUpRecursive(numbers() As Long, target As Long, part() As Long)

    Dim s As Long, i As Long, j As Long, num As Long
    Dim remaining() As Long, partRec() As Long
    s = SumArray(part)

    If s = target Then Debug.Print "SUM ( " & ArrayToString(part) & " ) = " & target
    If s >= target Then Exit Sub

    If (Not Not numbers) <> 0 Then
        For i = 0 To UBound(numbers)
            Erase remaining()
            num = numbers(i)
            For j = i + 1 To UBound(numbers)
                AddToArray remaining, numbers(j)
            Next j
            Erase partRec()
            CopyArray partRec, part
            AddToArray partRec, num
            SumUpRecursive remaining, target, partRec
        Next i
    End If

End Sub

Private Function ArrayToString(x() As Long) As String
    Dim n As Long, result As String
    result = "{" & x(n)
    For n = LBound(x) + 1 To UBound(x)
        result = result & "," & x(n)
    Next n
    result = result & "}"
    ArrayToString = result
End Function

Private Function SumArray(x() As Long) As Long
    Dim n As Long
    SumArray = 0
    If (Not Not x) <> 0 Then
        For n = LBound(x) To UBound(x)
            SumArray = SumArray + x(n)
        Next n
    End If
End Function

Private Sub AddToArray(arr() As Long, x As Long)
    If (Not Not arr) <> 0 Then
        ReDim Preserve arr(0 To UBound(arr) + 1)
    Else
        ReDim Preserve arr(0 To 0)
    End If
    arr(UBound(arr)) = x
End Sub

Private Sub CopyArray(destination() As Long, source() As Long)
    Dim n As Long
    If (Not Not source) <> 0 Then
        For n = 0 To UBound(source)
                AddToArray destination, source(n)
        Next n
    End If
End Sub

আউটপুট (তাত্ক্ষণিক উইন্ডোতে লিখিত) হওয়া উচিত:

SUM ( {3,8,4} ) = 15
SUM ( {3,5,7} ) = 15
SUM ( {8,7} ) = 15
SUM ( {5,10} ) = 15 

2

এখানে আরও ভাল আউটপুট বিন্যাস এবং সি ++ 11 বৈশিষ্ট্য সহ আরও একটি সংস্করণ রয়েছে:

void subset_sum_rec(std::vector<int> & nums, const int & target, std::vector<int> & partialNums) 
{
    int currentSum = std::accumulate(partialNums.begin(), partialNums.end(), 0);
    if (currentSum > target)
        return;
    if (currentSum == target) 
    {
        std::cout << "sum([";
        for (auto it = partialNums.begin(); it != std::prev(partialNums.end()); ++it)
            cout << *it << ",";
        cout << *std::prev(partialNums.end());
        std::cout << "])=" << target << std::endl;
    }
    for (auto it = nums.begin(); it != nums.end(); ++it) 
    {
        std::vector<int> remaining;
        for (auto it2 = std::next(it); it2 != nums.end(); ++it2)
            remaining.push_back(*it2);

        std::vector<int> partial = partialNums;
        partial.push_back(*it);
        subset_sum_rec(remaining, target, partial);
    }
}

2

জাভা অ-পুনরাবৃত্ত সংস্করণ যা কেবলমাত্র উপাদানগুলিকে যুক্ত করে এবং তাদেরকে সম্ভাব্য মানগুলির মধ্যে পুনরায় বিতরণ করে। 0এগুলি উপেক্ষা করা হয় এবং স্থির তালিকার জন্য কাজ করে (আপনাকে যা দেওয়া হয় তা আপনি কী খেলতে পারেন) বা পুনরাবৃত্তযোগ্য সংখ্যার একটি তালিকা।

import java.util.*;

public class TestCombinations {

    public static void main(String[] args) {
        ArrayList<Integer> numbers = new ArrayList<>(Arrays.asList(0, 1, 2, 2, 5, 10, 20));
        LinkedHashSet<Integer> targets = new LinkedHashSet<Integer>() {{
            add(4);
            add(10);
            add(25);
        }};

        System.out.println("## each element can appear as many times as needed");
        for (Integer target: targets) {
            Combinations combinations = new Combinations(numbers, target, true);
            combinations.calculateCombinations();
            for (String solution: combinations.getCombinations()) {
                System.out.println(solution);
            }
        }

        System.out.println("## each element can appear only once");
        for (Integer target: targets) {
            Combinations combinations = new Combinations(numbers, target, false);
            combinations.calculateCombinations();
            for (String solution: combinations.getCombinations()) {
                System.out.println(solution);
            }
        }
    }

    public static class Combinations {
        private boolean allowRepetitions;
        private int[] repetitions;
        private ArrayList<Integer> numbers;
        private Integer target;
        private Integer sum;
        private boolean hasNext;
        private Set<String> combinations;

        /**
         * Constructor.
         *
         * @param numbers Numbers that can be used to calculate the sum.
         * @param target  Target value for sum.
         */
        public Combinations(ArrayList<Integer> numbers, Integer target) {
            this(numbers, target, true);
        }

        /**
         * Constructor.
         *
         * @param numbers Numbers that can be used to calculate the sum.
         * @param target  Target value for sum.
         */
        public Combinations(ArrayList<Integer> numbers, Integer target, boolean allowRepetitions) {
            this.allowRepetitions = allowRepetitions;
            if (this.allowRepetitions) {
                Set<Integer> numbersSet = new HashSet<>(numbers);
                this.numbers = new ArrayList<>(numbersSet);
            } else {
                this.numbers = numbers;
            }
            this.numbers.removeAll(Arrays.asList(0));
            Collections.sort(this.numbers);

            this.target = target;
            this.repetitions = new int[this.numbers.size()];
            this.combinations = new LinkedHashSet<>();

            this.sum = 0;
            if (this.repetitions.length > 0)
                this.hasNext = true;
            else
                this.hasNext = false;
        }

        /**
         * Calculate and return the sum of the current combination.
         *
         * @return The sum.
         */
        private Integer calculateSum() {
            this.sum = 0;
            for (int i = 0; i < repetitions.length; ++i) {
                this.sum += repetitions[i] * numbers.get(i);
            }
            return this.sum;
        }

        /**
         * Redistribute picks when only one of each number is allowed in the sum.
         */
        private void redistribute() {
            for (int i = 1; i < this.repetitions.length; ++i) {
                if (this.repetitions[i - 1] > 1) {
                    this.repetitions[i - 1] = 0;
                    this.repetitions[i] += 1;
                }
            }
            if (this.repetitions[this.repetitions.length - 1] > 1)
                this.repetitions[this.repetitions.length - 1] = 0;
        }

        /**
         * Get the sum of the next combination. When 0 is returned, there's no other combinations to check.
         *
         * @return The sum.
         */
        private Integer next() {
            if (this.hasNext && this.repetitions.length > 0) {
                this.repetitions[0] += 1;
                if (!this.allowRepetitions)
                    this.redistribute();
                this.calculateSum();

                for (int i = 0; i < this.repetitions.length && this.sum != 0; ++i) {
                    if (this.sum > this.target) {
                        this.repetitions[i] = 0;
                        if (i + 1 < this.repetitions.length) {
                            this.repetitions[i + 1] += 1;
                            if (!this.allowRepetitions)
                                this.redistribute();
                        }
                        this.calculateSum();
                    }
                }

                if (this.sum.compareTo(0) == 0)
                    this.hasNext = false;
            }
            return this.sum;
        }

        /**
         * Calculate all combinations whose sum equals target.
         */
        public void calculateCombinations() {
            while (this.hasNext) {
                if (this.next().compareTo(target) == 0)
                    this.combinations.add(this.toString());
            }
        }

        /**
         * Return all combinations whose sum equals target.
         *
         * @return Combinations as a set of strings.
         */
        public Set<String> getCombinations() {
            return this.combinations;
        }

        @Override
        public String toString() {
            StringBuilder stringBuilder = new StringBuilder("" + sum + ": ");
            for (int i = 0; i < repetitions.length; ++i) {
                for (int j = 0; j < repetitions[i]; ++j) {
                    stringBuilder.append(numbers.get(i) + " ");
                }
            }
            return stringBuilder.toString();
        }
    }
}

নমুনা ইনপুট:

numbers: 0, 1, 2, 2, 5, 10, 20
targets: 4, 10, 25

নমুনা আউটপুট:

## each element can appear as many times as needed
4: 1 1 1 1 
4: 1 1 2 
4: 2 2 
10: 1 1 1 1 1 1 1 1 1 1 
10: 1 1 1 1 1 1 1 1 2 
10: 1 1 1 1 1 1 2 2 
10: 1 1 1 1 2 2 2 
10: 1 1 2 2 2 2 
10: 2 2 2 2 2 
10: 1 1 1 1 1 5 
10: 1 1 1 2 5 
10: 1 2 2 5 
10: 5 5 
10: 10 
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 
25: 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 
25: 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 
25: 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 
25: 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 
25: 1 1 1 2 2 2 2 2 2 2 2 2 2 2 
25: 1 2 2 2 2 2 2 2 2 2 2 2 2 
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 5 
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 5 
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 5 
25: 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 5 
25: 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 5 
25: 1 1 1 1 1 1 1 1 2 2 2 2 2 2 5 
25: 1 1 1 1 1 1 2 2 2 2 2 2 2 5 
25: 1 1 1 1 2 2 2 2 2 2 2 2 5 
25: 1 1 2 2 2 2 2 2 2 2 2 5 
25: 2 2 2 2 2 2 2 2 2 2 5 
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 2 5 5 
25: 1 1 1 1 1 1 1 1 1 1 1 2 2 5 5 
25: 1 1 1 1 1 1 1 1 1 2 2 2 5 5 
25: 1 1 1 1 1 1 1 2 2 2 2 5 5 
25: 1 1 1 1 1 2 2 2 2 2 5 5 
25: 1 1 1 2 2 2 2 2 2 5 5 
25: 1 2 2 2 2 2 2 2 5 5 
25: 1 1 1 1 1 1 1 1 1 1 5 5 5 
25: 1 1 1 1 1 1 1 1 2 5 5 5 
25: 1 1 1 1 1 1 2 2 5 5 5 
25: 1 1 1 1 2 2 2 5 5 5 
25: 1 1 2 2 2 2 5 5 5 
25: 2 2 2 2 2 5 5 5 
25: 1 1 1 1 1 5 5 5 5 
25: 1 1 1 2 5 5 5 5 
25: 1 2 2 5 5 5 5 
25: 5 5 5 5 5 
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 10 
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 2 10 
25: 1 1 1 1 1 1 1 1 1 1 1 2 2 10 
25: 1 1 1 1 1 1 1 1 1 2 2 2 10 
25: 1 1 1 1 1 1 1 2 2 2 2 10 
25: 1 1 1 1 1 2 2 2 2 2 10 
25: 1 1 1 2 2 2 2 2 2 10 
25: 1 2 2 2 2 2 2 2 10 
25: 1 1 1 1 1 1 1 1 1 1 5 10 
25: 1 1 1 1 1 1 1 1 2 5 10 
25: 1 1 1 1 1 1 2 2 5 10 
25: 1 1 1 1 2 2 2 5 10 
25: 1 1 2 2 2 2 5 10 
25: 2 2 2 2 2 5 10 
25: 1 1 1 1 1 5 5 10 
25: 1 1 1 2 5 5 10 
25: 1 2 2 5 5 10 
25: 5 5 5 10 
25: 1 1 1 1 1 10 10 
25: 1 1 1 2 10 10 
25: 1 2 2 10 10 
25: 5 10 10 
25: 1 1 1 1 1 20 
25: 1 1 1 2 20 
25: 1 2 2 20 
25: 5 20 
## each element can appear only once
4: 2 2 
10: 1 2 2 5 
10: 10 
25: 1 2 2 20 
25: 5 20

1

এক্সেল ব্যবহার করে সমন্বয়গুলি সন্ধান করতে - (এটি মোটামুটি সহজ)। (আপনার কম্পিউটার অবশ্যই খুব ধীর হওয়া উচিত নয়)

  1. এই সাইটে যান
  2. "লক্ষ্য থেকে লক্ষ্য" পৃষ্ঠায় যান
  3. "লক্ষ্য থেকে লক্ষ্য" এক্সেল ফাইলটি ডাউনলোড করুন।

    ওয়েবসাইট পৃষ্ঠায় নির্দেশাবলী অনুসরণ করুন।

আশাকরি এটা সাহায্য করবে.


1

জাভা সমাধানের সুইফট 3 রূপান্তর: (@ জেরি থমসন দ্বারা)

protocol _IntType { }
extension Int: _IntType {}


extension Array where Element: _IntType {

    func subsets(to: Int) -> [[Element]]? {

        func sum_up_recursive(_ numbers: [Element], _ target: Int, _ partial: [Element], _ solution: inout [[Element]]) {

            var sum: Int = 0
            for x in partial {
                sum += x as! Int
            }

            if sum == target {
                solution.append(partial)
            }

            guard sum < target else {
                return
            }

            for i in stride(from: 0, to: numbers.count, by: 1) {

                var remaining = [Element]()

                for j in stride(from: i + 1, to: numbers.count, by: 1) {
                    remaining.append(numbers[j])
                }

                var partial_rec = [Element](partial)
                partial_rec.append(numbers[i])

                sum_up_recursive(remaining, target, partial_rec, &solution)
            }
        }

        var solutions = [[Element]]()
        sum_up_recursive(self, to, [Element](), &solutions)

        return solutions.count > 0 ? solutions : nil
    }

}

ব্যবহার:

let numbers = [3, 9, 8, 4, 5, 7, 10]

if let solution = numbers.subsets(to: 15) {
    print(solution) // output: [[3, 8, 4], [3, 5, 7], [8, 7], [5, 10]]
} else {
    print("not possible")
}

1

এটি সমস্ত উত্তর মুদ্রণের জন্যও ব্যবহার করা যেতে পারে

public void recur(int[] a, int n, int sum, int[] ans, int ind) {
    if (n < 0 && sum != 0)
        return;
    if (n < 0 && sum == 0) {
        print(ans, ind);
        return;
    }
    if (sum >= a[n]) {
        ans[ind] = a[n];
        recur(a, n - 1, sum - a[n], ans, ind + 1);
    }
    recur(a, n - 1, sum, ans, ind);
}

public void print(int[] a, int n) {
    for (int i = 0; i < n; i++)
        System.out.print(a[i] + " ");
    System.out.println();
}

সময় জটিলতা তাত্পর্যপূর্ণ। 2 Order n এর অর্ডার


1

আমি স্কেল অ্যাসাইনমেন্টের জন্য অনুরূপ কিছু করছিলাম। আমার সমাধান এখানে পোস্ট করার চিন্তাভাবনা:

 def countChange(money: Int, coins: List[Int]): Int = {
      def getCount(money: Int, remainingCoins: List[Int]): Int = {
        if(money == 0 ) 1
        else if(money < 0 || remainingCoins.isEmpty) 0
        else
          getCount(money, remainingCoins.tail) +
            getCount(money - remainingCoins.head, remainingCoins)
      }
      if(money == 0 || coins.isEmpty) 0
      else getCount(money, coins)
    }

1

আমি সি # নমুনাকে উদ্দেশ্য-সিতে পোর্ট করেছি এবং প্রতিক্রিয়াগুলিতে এটি দেখিনি:

//Usage
NSMutableArray* numberList = [[NSMutableArray alloc] init];
NSMutableArray* partial = [[NSMutableArray alloc] init];
int target = 16;
for( int i = 1; i<target; i++ )
{ [numberList addObject:@(i)]; }
[self findSums:numberList target:target part:partial];


//*******************************************************************
// Finds combinations of numbers that add up to target recursively
//*******************************************************************
-(void)findSums:(NSMutableArray*)numbers target:(int)target part:(NSMutableArray*)partial
{
    int s = 0;
    for (NSNumber* x in partial)
    { s += [x intValue]; }

    if (s == target)
    { NSLog(@"Sum[%@]", partial); }

    if (s >= target)
    { return; }

    for (int i = 0;i < [numbers count];i++ )
    {
        int n = [numbers[i] intValue];
        NSMutableArray* remaining = [[NSMutableArray alloc] init];
        for (int j = i + 1; j < [numbers count];j++)
        { [remaining addObject:@([numbers[j] intValue])]; }

        NSMutableArray* partRec = [[NSMutableArray alloc] initWithArray:partial];
        [partRec addObject:@(n)];
        [self findSums:remaining target:target part:partRec];
    }
}

1

কিছুটা পরিবর্তিত পরিবর্তনশীল নাম এবং কিছু মন্তব্যে @ কিথবেলার এর উত্তর।

    public static void Main(string[] args)
    {
        List<int> input = new List<int>() { 3, 9, 8, 4, 5, 7, 10 };
        int targetSum = 15;
        SumUp(input, targetSum);
    }

    public static void SumUp(List<int> input, int targetSum)
    {
        SumUpRecursive(input, targetSum, new List<int>());
    }

    private static void SumUpRecursive(List<int> remaining, int targetSum, List<int> listToSum)
    {
        // Sum up partial
        int sum = 0;
        foreach (int x in listToSum)
            sum += x;

        //Check sum matched
        if (sum == targetSum)
            Console.WriteLine("sum(" + string.Join(",", listToSum.ToArray()) + ")=" + targetSum);

        //Check sum passed
        if (sum >= targetSum)
            return;

        //Iterate each input character
        for (int i = 0; i < remaining.Count; i++)
        {
            //Build list of remaining items to iterate
            List<int> newRemaining = new List<int>();
            for (int j = i + 1; j < remaining.Count; j++)
                newRemaining.Add(remaining[j]);

            //Update partial list
            List<int> newListToSum = new List<int>(listToSum);
            int currentItem = remaining[i];
            newListToSum.Add(currentItem);
            SumUpRecursive(newRemaining, targetSum, newListToSum);
        }
    }'

1

পিএইচপি সংস্করণ , কীথ বেলার সি # সংস্করণ দ্বারা অনুপ্রাণিত হিসাবে।

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

/**
 * Calculates a subset sum: finds out which combinations of numbers
 * from the numbers array can be added together to come to the target
 * number.
 * 
 * Returns an indexed array with arrays of number combinations.
 * 
 * Example: 
 * 
 * <pre>
 * $matches = subset_sum(array(5,10,7,3,20), 25);
 * </pre>
 * 
 * Returns:
 * 
 * <pre>
 * Array
 * (
 *   [0] => Array
 *   (
 *       [0] => 3
 *       [1] => 5
 *       [2] => 7
 *       [3] => 10
 *   )
 *   [1] => Array
 *   (
 *       [0] => 5
 *       [1] => 20
 *   )
 * )
 * </pre>
 * 
 * @param number[] $numbers
 * @param number $target
 * @param array $part
 * @return array[number[]]
 */
function subset_sum($numbers, $target, $part=null)
{
    // we assume that an empty $part variable means this
    // is the top level call.
    $toplevel = false;
    if($part === null) {
        $toplevel = true;
        $part = array();
    }

    $s = 0;
    foreach($part as $x) 
    {
        $s = $s + $x;
    }

    // we have found a match!
    if($s == $target) 
    {
        sort($part); // ensure the numbers are always sorted
        return array(implode('|', $part));
    }

    // gone too far, break off
    if($s >= $target) 
    {
        return null;
    }

    $matches = array();
    $totalNumbers = count($numbers);

    for($i=0; $i < $totalNumbers; $i++) 
    {
        $remaining = array();
        $n = $numbers[$i];

        for($j = $i+1; $j < $totalNumbers; $j++) 
        {
            $remaining[] = $numbers[$j];
        }

        $part_rec = $part;
        $part_rec[] = $n;

        $result = subset_sum($remaining, $target, $part_rec);
        if($result) 
        {
            $matches = array_merge($matches, $result);
        }
    }

    if(!$toplevel) 
    {
        return $matches;
    }

    // this is the top level function call: we have to
    // prepare the final result value by stripping any
    // duplicate results.
    $matches = array_unique($matches);
    $result = array();
    foreach($matches as $entry) 
    {
        $result[] = explode('|', $entry);
    }

    return $result;
}

1

উত্তর হিসাবে প্রস্তাবিত:

এখানে es2015 জেনারেটর ব্যবহার করে একটি সমাধান দেওয়া হয়েছে :

function* subsetSum(numbers, target, partial = [], partialSum = 0) {

  if(partialSum === target) yield partial

  if(partialSum >= target) return

  for(let i = 0; i < numbers.length; i++){
    const remaining = numbers.slice(i + 1)
        , n = numbers[i]

    yield* subsetSum(remaining, target, [...partial, n], partialSum + n)
  }

}

জেনারেটর ব্যবহার প্রকৃতপক্ষে খুব দরকারী কারণ এটি আপনাকে বৈধ সাবসেটের সন্ধানের সাথে সাথে স্ক্রিপ্ট সম্পাদনকে অবিলম্বে বিরতি দিতে দেয়। এটি জেনারেটর ছাড়াই সমাধানগুলির বিপরীতে (অর্থাত্ রাষ্ট্রের অভাব) যার প্রতিটি একক উপসেটের মাধ্যমে পুনরাবৃত্তি করতে হয়numbers


1

প্রথম স্থানে 0 ছাড় করুন। জিরো সংযোজনের জন্য একটি পরিচয় তাই এটি বিশেষ ক্ষেত্রে একঘেয়েমি আইন দ্বারা অকেজো। ইতিবাচক সংখ্যায় আরোহণ করতে চাইলে নেতিবাচক সংখ্যাগুলিও কেটে দিন। অন্যথায় আপনার বিয়োগ অপারেশনও প্রয়োজন।

সুতরাং ... আপনি এই বিশেষ কাজটি পেতে পারেন দ্রুততম অ্যালগরিদম জেএস-এর নীচে দেওয়া হয়েছে।

function items2T([n,...ns],t){
    var c = ~~(t/n);
    return ns.length ? Array(c+1).fill()
                                 .reduce((r,_,i) => r.concat(items2T(ns, t-n*i).map(s => Array(i).fill(n).concat(s))),[])
                     : t % n ? []
                             : [Array(c).fill(n)];
};

var data = [3, 9, 8, 4, 5, 7, 10],
    result;

console.time("combos");
result = items2T(data, 15);
console.timeEnd("combos");
console.log(JSON.stringify(result));

এটি খুব দ্রুত অ্যালগরিদম তবে আপনি যদি সাজানোdata অ্যারেটি সাজান তবে এটি আরও দ্রুত হবে। ব্যবহার তুচ্ছ কারণ যেহেতু অ্যালগরিদমটি খুব কম পুনরাবৃত্তির অনুরোধের সাথে শেষ হবে ।.sort()


খুশী হলাম। এটা দেখায় যে আপনি একজন অভিজ্ঞ প্রোগ্রামার আছেন :)
জেমস পি

1

পার্ল সংস্করণ (শীর্ষস্থানীয় উত্তরের):

use strict;

sub subset_sum {
  my ($numbers, $target, $result, $sum) = @_;

  print 'sum('.join(',', @$result).") = $target\n" if $sum == $target;
  return if $sum >= $target;

  subset_sum([@$numbers[$_ + 1 .. $#$numbers]], $target, 
             [@{$result||[]}, $numbers->[$_]], $sum + $numbers->[$_])
    for (0 .. $#$numbers);
}

subset_sum([3,9,8,4,5,7,10,6], 15);

ফলাফল:

sum(3,8,4) = 15
sum(3,5,7) = 15
sum(9,6) = 15
sum(8,7) = 15
sum(4,5,6) = 15
sum(5,10) = 15

জাভাস্ক্রিপ্ট সংস্করণ:

const subsetSum = (numbers, target, partial = [], sum = 0) => {
  if (sum < target)
    numbers.forEach((num, i) =>
      subsetSum(numbers.slice(i + 1), target, partial.concat([num]), sum + num));
  else if (sum == target)
    console.log('sum(%s) = %s', partial.join(), target);
}

subsetSum([3,9,8,4,5,7,10,6], 15);

জাভাস্ক্রিপ্ট ওয়ান-লাইনার যা আসলে ফলাফলগুলি দেয় (এটি মুদ্রণের পরিবর্তে):

const subsetSum=(n,t,p=[],s=0,r=[])=>(s<t?n.forEach((l,i)=>subsetSum(n.slice(i+1),t,[...p,l],s+l,r)):s==t?r.push(p):0,r);

console.log(subsetSum([3,9,8,4,5,7,10,6], 15));

এবং আমার প্রিয়, কলব্যাক সহ ওয়ান-লাইনার:

const subsetSum=(n,t,cb,p=[],s=0)=>s<t?n.forEach((l,i)=>subsetSum(n.slice(i+1),t,cb,[...p,l],s+l)):s==t?cb(p):0;

subsetSum([3,9,8,4,5,7,10,6], 15, console.log);


0
function solve(n){
    let DP = [];

     DP[0] = DP[1] = DP[2] = 1;
     DP[3] = 2;

    for (let i = 4; i <= n; i++) {
      DP[i] = DP[i-1] + DP[i-3] + DP[i-4];
    }
    return DP[n]
}

console.log(solve(5))

যে কোনও নির্দিষ্ট পরিমাণ কী পরিমাণ পেতে পারে তার উপায় বলতে এটি জেএসের একটি ডায়নামিক সমাধান। সময় এবং স্থানের জটিলতা সম্পর্কে যদি আপনি চিন্তা করেন তবে এটি সঠিক সমাধান হতে পারে।


0
import java.util.*;

public class Main{

     int recursionDepth = 0;
     private int[][] memo;

     public static void main(String []args){
         int[] nums = new int[] {5,2,4,3,1};
         int N = nums.length;
         Main main =  new Main();
         main.memo = new int[N+1][N+1];
         main._findCombo(0, N-1,nums, 8, 0, new LinkedList() );
         System.out.println(main.recursionDepth);
     }


       private void _findCombo(
           int from,
           int to,
           int[] nums,
           int targetSum,
           int currentSum,
           LinkedList<Integer> list){

            if(memo[from][to] != 0) {
                currentSum = currentSum + memo[from][to];
            }

            if(currentSum > targetSum) {
                return;
            }

            if(currentSum ==  targetSum) {
                System.out.println("Found - " +list);
                return;
            }

            recursionDepth++;

           for(int i= from ; i <= to; i++){
               list.add(nums[i]);
               memo[from][i] = currentSum + nums[i];
               _findCombo(i+1, to,nums, targetSum, memo[from][i], list);
                list.removeLast();
           }

     }
}

0

আমি জাভাস্ক্রিপ্ট সমাধানটি পছন্দ করেছিলাম না কেন আমি দেখতে পেলাম যে আমি আংশিক প্রয়োগ, সমাপনীকরণ এবং পুনরাবৃত্তি ব্যবহার করে নিজের জন্য একটি তৈরি করি:

ঠিক আছে, সংশ্লেষ অ্যারে প্রয়োজনীয় লক্ষ্য পূরণ করতে পারে কিনা তা নিয়ে আমি মূলত উদ্বেগ ছিলাম, তবে এইটির সাথে আপনি বাকী সংমিশ্রণগুলি সন্ধান করতে পারেন

এখানে কেবল লক্ষ্য নির্ধারণ করুন এবং সংমিশ্রণের অ্যারেটি পাস করুন।

function main() {
    const target = 10
    const getPermutationThatSumT = setTarget(target)
    const permutation = getPermutationThatSumT([1, 4, 2, 5, 6, 7])

    console.log( permutation );
}

বর্তমানে বাস্তবায়ন আমি নিয়ে এসেছি

function setTarget(target) {
    let partial = [];

    return function permute(input) {
        let i, removed;
        for (i = 0; i < input.length; i++) {
            removed = input.splice(i, 1)[0];
            partial.push(removed);

            const sum = partial.reduce((a, b) => a + b)
            if (sum === target) return partial.slice()
            if (sum < target) permute(input)

            input.splice(i, 0, removed);
            partial.pop();
        }
        return null
    };
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.