फलों के बागान का कारखाना


21

आपका मिशन एक एल्गोरिथ्म (प्रोग्राम या फ़ंक्शन) का निर्माण करना है जो एक कन्वेयर बेल्ट से फलों को बैग में पैक करके खुदरा विक्रेताओं को भेजा जा सकता है, जो बड़ी संख्या में बैग के लिए अनुकूलन करते हैं।

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

यह कल्पना करने का दूसरा तरीका nअंत में आकार के लोडिंग क्षेत्र के साथ एक कन्वेयर बेल्ट है , जहां से एक नए फल आने से पहले एक फल लेना होता है। किसी भी बचे हुए फल और अंत में एक गैर-पूर्ण बैग को छोड़ दिया जाता है।

चित्र 1: फलों का बैग बनाने का कारखाना

इनपुट

  • कतार में फलों के वजन की सूची / सरणी (सकारात्मक पूर्णांक)
  • बैग के लिए न्यूनतम कुल वजन (सकारात्मक पूर्णांक)
  • लाहदहेड n(सकारात्मक पूर्णांक)

उत्पादन

आपके एल्गोरिथ्म को उन सभी फलों के वजन के लिए वापस जाना चाहिए, जो कुछ भी आपके और आपकी भाषा के लिए सुविधाजनक है, स्टैड या रिटर्न वैल्यू या कुछ और। आपको प्रोग्राम चलाने और अपने स्कोर की गणना अपने कंप्यूटर पर एक मिनट में करने में सक्षम होना चाहिए।

उदाहरण

Total weight 1000, lookahead of 3 and fruit queue: 
[171,163,172,196,156,175,162,176,155,182,189,142,161,160,152,162,174,172,191,185]

One possible output (indented to show how the lookahead affects the bagging):
[171,163,172,    156,175,    176]
                        [162,    155,182,189,    161,160]
                                                        [152,162,174,172,191,185]

स्कोरिंग

आपके एल्गोरिथ्म को 10000 संतरे के एक बैच पर छह रनों पर परीक्षण किया जाएगा , जो मैंने आपके लिए तैयार किए हैं, दोनों छोरों पर समावेशी, 2 से 7 तक दिखते हैं। आप उन्हें कम से कम 1000 इकाइयों के वजन वाले बैग में पैक करेंगे। संतरे को आमतौर पर 170 के औसत वजन और 13 के मानक विचलन के साथ वितरित किया जाता है, यदि वह किसी भी मदद का हो।

आपका स्कोर छह रनों से बैग की संख्या का योग होगा। सबसे ज्यादा अंक जीते। मानक खामियों को अस्वीकार कर दिया जाता है।

हास्केल में सरल उदाहरण कार्यान्वयन और परीक्षण सूट बॉयलरप्लेट


7
लोगों पर आते हैं, मुझे लगता है कि अभी भी कुछ कम लटका हुआ फल एल्गोरिदम अभी भी उठाया जाने की प्रतीक्षा कर रहे हैं ...
Angs

2
क्या माध्य भार / वितरण में प्रोग्राम हार्डकोड कर सकते हैं? (मान लें कि यह समान बैचों पर समान रूप से अच्छी तरह से काम करता है, बेशक हार्डकॉडिंग सब कुछ अमान्य है क्योंकि यह सीमित
लुकहेड

@ user202729: हाँ वे कर सकते हैं।
आंग्स

और हार्डकोडिंग सब कुछ वैसे भी एक निषिद्ध मानक ढलान है।
आंग्स

मैं नहीं देख सकता कि क्या लग रहा है
l4m2

जवाबों:


8

पायथन 3, 9964 9981 बैग

इस समाधान का विचार जोनाथन, जेसीई और फोरट्रान के समान है, लेकिन एक स्कोरिंग फ़ंक्शन के साथ))

यह समाधान लुकहेड क्षेत्र के सबसे अच्छे सबसेट को जोड़ता है score

score निम्नलिखित योजना का उपयोग करने वाले सबसेट पर एक आदेश प्रदान करता है:

  • एक बैग को पूरा करने वाला सबसेट एक से बेहतर है जो नहीं है
  • एक थैला पूरा करने वाला एक सबसेट दूसरे से बेहतर होता है अगर उसका वजन कम होता है
  • एक बैग को पूरा नहीं करने वाला एक सबसेट दूसरे से बेहतर है अगर उसका मतलब बैग में होने की उम्मीद के करीब हो

expected_mean यह अनुमान लगाने की कोशिश करता है कि बाकी मूल्यों को क्या देखना चाहिए (उनकी पसंद इष्टतम है)।

UPD :

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

import itertools as it
import math
from functools import partial
from collections import Counter


mean, std = 170, 13


def powerset(list_, max_items):
    return it.chain.from_iterable(it.combinations(list_, r) for r in range(1, max_items + 1))


def expected_mean(w):
    spread = std * 1
    return max(mean - spread, min(mean + spread, w / max(1, round(w / mean))))


def score(weight_needed, candidate):
    c_sum = sum(candidate)
    c_mean = c_sum / len(candidate)
    if c_sum >= weight_needed:
        return int(-2e9) + c_sum - weight_needed
    return abs(expected_mean(weight_needed) - c_mean)


def f(oranges, min_bag_weight, lookahead):
    check = Counter(oranges)

    oranges = oranges.copy()
    result = []
    bag = []

    while oranges:
        weight_needed = min_bag_weight - sum(bag)

        lookahead_area = oranges[:lookahead]
        tail = oranges[lookahead:]

        to_add = min(powerset(lookahead_area, lookahead),
                     key=partial(score, weight_needed))
        to_add = min(powerset(to_add, 1),
                     key=partial(score, weight_needed))

        bag.extend(to_add)
        for x in to_add:
            lookahead_area.remove(x)
        oranges = lookahead_area + tail

        if sum(bag) >= min_bag_weight:
            result.append(bag)
            bag = []

    assert check == Counter(oranges) + Counter(bag) + sum(map(Counter, result), Counter())

    return result


if __name__ == '__main__':
    with open('oranges') as file:
        oranges = list(map(int, file))
    res = [f(oranges, 1000, l) for l in range(2, 7+1)]
    print(sum(map(len, res)))

कोशिश करो!


बहुत अच्छा! यह 7 के लुकहेड के साथ 1672 हो जाता है, कभी भी ऐसा नहीं देखा गया है।
आंग्स

(ऐसा लगता है कि आपके powersetफ़ंक्शन का दूसरा तर्क इस मामले में निरर्थक है क्योंकि यह len(list_)वैसे भी बराबर है ?)
user202729

@user मैंने पिछले संस्करण में इस पैरामीटर के साथ प्रयोग किया था। शायद इसे बाद में हटा देंगे
एलेक्स

1
सबसे अच्छा एकल तत्व के सर्वश्रेष्ठ संयोजन के शक्तिशाली संयोजन की खोज करने के लिए बधाई और सबसे अच्छा स्कोर भी! ईनाम आपका है।
Angs

एक सरल expected_mean(w)जो अच्छे परिणाम देता है:return (w+2) / max(1, round((w+2) / mean))
Angs

10

अजगर 3 , 9796 बैग

जोनाथन के उत्तर पर निर्माण:

import itertools as it

def powerset(iterable):
    s = list(iterable)
    return it.chain.from_iterable(it.combinations(s, r) for r in range(len(s)+1))

def f(a,m,l):
 r=[];b=[]
 while a:
  c =  min(list(powerset(a[:l])),key=lambda w: abs(sum(b)+sum(w)-m))
  if sum(c)==0:
   c = a[:l]
  b+=[a.pop(a.index(min(c,key=lambda w: abs(sum(b)+w-m))))]
  if sum(b)>=m:r+=[b];b=[]
 return r

यह इटेरटूल की रसोई की किताब से अधिकार पर निर्भर करता है। पहले सभी उपसमुच्चय के लिए लक्ष्य वजन से अंतर को कम करने के आधार पर बफर का इष्टतम सबसेट पाया जाता है, और फिर उसी कसौटी पर आधारित इस उपसमुच्चय से एक तत्व चुनता है। यदि पूरे बफर से कोई इष्टतम उपसमूह नहीं चुनता है।


PPCG में आपका स्वागत है!
मार्टिन एंडर

@ मर्टिनएंडर थैंक्स मार्टिन का स्वागत करने के लिए धन्यवाद :)
JayCe

1
आह हाँ, मैं वहाँ एक चाल से चूक गया ... मुझे इसके साथ कोई समस्या नहीं है जैसा कि एक और जवाब है!
जोनाथन एलन

1
@JonathanAllan धन्यवाद जोनाथन मैंने सभी माफ़ी के बिना आपको क्रेडिट देने के लिए अपना जवाब छोटा कर दिया है। इस तथ्य का उपयोग करके सुधार किया जा सकता है कि यह एक सामान्य (170,13) वितरण है - मुझे यकीन है कि अगले रन (एस) में बेहतर फल प्राप्त करने की संभावना का उपयोग किया जा सकता है।
JayCe

@JayCe गंभीर रूप से जुआरी के पतन के करीब लगता है।
qwr

6

C ++ 17, 9961.58 (कुछ यादृच्छिक बीजों पर औसत)

(यदि आप C ++ नहीं जानते हैं तो स्पष्टीकरण के लिए नीचे स्क्रॉल करें)

#include<iostream>

#include<vector>
#include<random>

std::mt19937 engine(279); // random engine
// random distribution of the oranges
std::normal_distribution dist (170.,13.);

int constexpr N_NEW_ORANGES=7;

/** Input format: Current remaining weight of the bag (remain) and 
the weight of the oranges (weights)
Output: the index of the orange to be pick.
*/
struct pick_orange{
    std::vector<int>weights,sum_postfix;int remain;

    /// returns {min excess, mask}, (index) is the LSB
    std::pair<int,int> backtrack(int index, int remain) {
        if(sum_postfix[index]<remain)return {1e9,0};
        int min_excess=1e9, good_mask=0;
        for(int next=index;next<N_NEW_ORANGES;++next){
            if(weights[next]==remain){
                return {0, 1<<(next-index)};
            }else if(weights[next]>remain){
                if(weights[next]-remain<min_excess){
                    min_excess=weights[next]-remain;
                    good_mask=1<<(next-index);
                }
            }else{
                auto[excess,mask]=backtrack(next+1,remain-weights[next]);
                if(excess<min_excess){
                    min_excess=excess;
                    good_mask=(mask<<1|1)<<(next-index);
                }
            }
        }
        return {min_excess,good_mask};
    } 

    int ans;

    pick_orange(std::vector<int> weights_,int remain_)
        :weights(std::move(weights_)),remain(remain_){

        int old_size=weights.size();

        std::vector<int> count (N_NEW_ORANGES, 0);
        weights.resize(N_NEW_ORANGES, 0);

        sum_postfix.resize(N_NEW_ORANGES+1);
        sum_postfix.back()=0;

        for(int _=0; _<500; ++_){

            for(int i=old_size;i<N_NEW_ORANGES;++i)
                weights[i] = dist(engine);

            // prepare sum postfix
            for(int i=N_NEW_ORANGES;i-->0;)
                sum_postfix[i]=weights[i]+sum_postfix[i+1];

            // auto[excess,mask]=backtrack(0,remain);
            int mask = backtrack(0,remain).second;

            for(int i=0; 

                mask
                // i < N_NEW_ORANGES

                ; mask>>=1, ++i){

                // if(mask&1)std::cout<<'(';
                // std::cout<<weights[i];
                // if(mask&1)std::cout<<')';
                // std::cout<<' ';

                count[i]+=mask&1;
            }

            // std::cout<<"| "<<remain<<" | "<<excess<<'\n';

        }

        std::vector<double> count_balanced(old_size, -1);
        for(int i=0;i<old_size;++i){
            if(count_balanced[i]>-1)continue;
            int sum=0,amount=0;
            for(int j=i;j<old_size;++j)
                if(weights[j]==weights[i]){sum+=count[j];++amount;}

            double avg=sum;avg/=amount;
            for(int j=i;j<old_size;++j)
                if(weights[j]==weights[i])count_balanced[j]=avg;
        }

        ans=old_size-1;
        for(int i=ans;i-->0;)
            if(count_balanced[i]>count_balanced[ans])ans=i;
        // Fun fact: originally I wrote `<` for `>` here and wonder
        // why the number of bags is even less than that of the
        // randomized algorithm
    }

    operator int()const{return ans;}
};


#include<iostream>
#include<fstream>
#include<algorithm>

int main(){
    // read input from the file "data"
    std::ifstream data ("data");
    std::vector<int> weights;
    int weight;while(data>>weight)weights.push_back(weight);

    int constexpr BAG_SIZE=1000;
    int total_n_bag=0;
    for(int lookahead=2;lookahead<=7;++lookahead){
        auto weights1=weights;
        std::reverse(weights1.begin(),weights1.end());

        int remain=BAG_SIZE,n_bag=0;
        std::vector<int> w;
        for(int _=lookahead;_--;){
            w.push_back(weights1.back());
            weights1.pop_back();
        }
        while(!weights1.empty()){
            int index=pick_orange(w,remain);

            remain-=w[index];
            if(remain<=0){
                ++n_bag;remain=BAG_SIZE;

                if(n_bag%100==0)
                    std::cout<<n_bag<<" bags so far..."<<std::endl;
            }
            w[index]=weights1.back();weights1.pop_back();
        }

        while(!w.empty()){
            int index=pick_orange(w,remain);
            remain-=w[index];
            if(remain<=0){++n_bag;remain=BAG_SIZE;}
            w.erase(w.begin()+index);
        }

        std::cout<<"lookahead = "<<lookahead<<", "
            "n_bag = "<<n_bag<<'\n';
        total_n_bag += n_bag;
    }

    std::cout<<"total_n_bag = "<<total_n_bag<<'\n';
}

// मजेदार तथ्य: मूल रूप से मैंने यहां और आश्चर्य के <लिए लिखा है >। // बेतरतीब एल्गोरिथ्म
की तुलना में बैग की संख्या क्यों कम है

(यदि <मूल रूप से एल्गोरिथ्म का उपयोग किया जाता है तो बैग की संख्या को कम करने की कोशिश करता है )

इस उत्तर से प्रेरित ।

250 पुनरावृत्तियों के लिए TIO लिंक: इसे ऑनलाइन आज़माएं!


एक फ़ंक्शन को परिभाषित करता है (वास्तव में यह सिर्फ एक फ़ंक्शन की तरह दिखता है, यह एक संरचना है) pick_orange, vector<int> weightsजो संतरे के int remainवजन और बैग के शेष वजन को देखते हुए, नारंगी के सूचकांक को लौटाता है जिसे उठाया जाना चाहिए।

कलन विधि:

दोहराने का 500समय यादृच्छिक (नकली) संतरे {
उत्पन्न करता है (मतलब 170 और stddev 13 के साथ सामान्य वितरण) जब तक N_NEW_ORANGES=7संतरे
किसी भी उपसमुच्चय को चुन लेते हैं, जिसका योग सबसे छोटा होता है और इससे छोटा नहीं होता remain(फ़ंक्शन backtrackऐसा करता है)
उस उप-भाग में सभी संतरे को अच्छे के रूप में चिह्नित करता है
}

एक संतरे के अच्छे के रूप में चिह्नित किया जा रहा है (असली) संतरे के बराबर वजन के साथ औसत
से सबसे अच्छा नारंगी लौटा


कार्यक्रम में 3 हार्डकॉस्ट स्थिरांक हैं जो समस्या से प्रभावित नहीं हो सकते हैं:

  • यादृच्छिक बीज (यह महत्वपूर्ण नहीं है)
  • N_NEW_ORANGES(भविष्यवाणी की लंबाई)। इसे बढ़ाने से प्रोग्राम तेजी से लंबा चलता है (क्योंकि बैकट्रैक)
  • पुनरावृत्ति की संख्या। इसे बढ़ाने से कार्यक्रम रैखिक रूप से लंबा चलता है।

ठीक है। सबसे अच्छा जवाब देने वाले को बीज को बदलना ऐसा लगता है जैसे परीक्षण मामले के लिए अनुकूलन है, इसलिए आपको अपने स्कोर के रूप में कुछ, औसत 10, अलग-अलग बीजों का औसत लेना चाहिए। क्या आप उस संस्करण के लिए एक TIO लिंक पोस्ट कर सकते हैं जो रनटाइम को कम करने के लिए कम पुनरावृत्ति करता है?
आंग्स

अंत में इसे एक नया gcc प्राप्त करने के बाद संकलन करने के लिए मिला। यादृच्छिक बीजों के साथ 50 रनों पर इसे औसतन 9961.58 मिली। अभी भी बहुत प्रभावशाली है। हालांकि मुझे आश्चर्य है कि - आपका एल्गोरिथ्म मूल रूप से हर बैग पर खुद को फिर से प्रशिक्षित करता है, क्या सबसे अच्छे मूल्यों का एक सेट है जिसे याद किया जा सकता है?
एंग्स

@ मुझे नहीं लगता कि ऐसा कोई तरीका है जो इस मामले में मदद करने के लिए संस्मरण का उपयोग कर सकता है। कोई उपाय?
user202729

मेरा OS 5.4.0 gcc के साथ आता है, इसमें कुछ समस्याएँ थीं invalid use of template-name ‘std::normal_distribution’। जीसीसी 7.1.0 के साथ कोई समस्या नहीं है।
आंग्स

4

अजगर 2 , 9756 बैग

आइये जाने संतरे का रोल ...

def f(a,m,l):
 r=[];b=[]
 while a:
  b+=[a.pop(a.index(min(a[:l],key=lambda w:abs(sum(b)+w-m))))]
  if sum(b)>=m:r+=[b];b=[]
 return r

इसे ऑनलाइन आज़माएं!

हमेशा बफर से फल चुनता है जो नए वजन और लक्ष्य वजन के पूर्ण अंतर को कम करता है।


4

पायथन 3, 9806 बैग

जोनाथन और JayCe के उत्तरों पर निर्माण:

import itertools as it

def powerset(iterable):
    s = list(iterable)
    return it.chain.from_iterable(it.combinations(s, r) for r in range(len(s)+1))

def f(a,m,l):
 r=[];b=[]
 while a:
  c =  min(list(powerset(list(reversed(sorted(a[:l]))))),key=lambda w: abs((sum(b)+sum(w))-m))
  if sum(c)==0:
   c = a[:l]
  b+=[a.pop(a.index(min(c,key=lambda w: abs((sum(b)+w)-m))))]
  if sum(b)>=m:r+=[b];b=[]
 return r

इसे ऑनलाइन आज़माएं!

यह काम किस प्रकार करता है

कहें कि बैग में 900 इकाइयाँ हैं, और 2 फल उपलब्ध हैं: एक 99 यूनिट फल और एक 101 यूनिट फल। यदि 99 यूनिट फल लुकहेड सूची की शुरुआत के करीब है, तो min101 के बजाय इसका चयन करेगा। यदि ऐसा होता है, तो हमें अब शेष 1 इकाई को पूरा करने के लिए एक और फल की आवश्यकता होगी। मैंने इन मामलों में उच्च-मूल्यवान फल के पक्ष में कार्यक्रम बदल दिया।

यह सॉर्ट करता है और फिर पावरसेटिंग से पहले लुकहेड सूची को उलट कर देता है।


4

PHP, 9975 बैग

  • यदि संभव हो तो 5 संतरे के लिए जाएं
  • जब बैग शुरू हो तो अत्यधिक मूल्य चुनें, बाद में संतुलन
  • संभव हो तो तुरंत बैग भरें
  • अनुमानित वक्र के करीब बैग वजन रखने की कोशिश करें (5बैग के लिए एन * 200, 6बैग के लिए एन * 167, आदि)

सभी सबमिशन में से सबसे लंबा, लेकिन पठनीय होना चाहिए

class Belt
{
    private $file;
    private $windowSize;
    private $buffer = [];

    public function __construct($filename, $windowSize) {
        $this->file = new \SplFileObject($filename);
        $this->windowSize = $windowSize;
        $this->loadBuffer();
    }

    public function reset($windowSize) {
        $this->file->seek(0);
        $this->windowSize = $windowSize;
        $this->buffer = [];
        $this->loadBuffer();
    }

    public function peekBuffer() {
        return $this->buffer;
    }

    public function pick($index) {
        if (!array_key_exists($index, $this->buffer)) {
            return null;
        }
        $value = $this->buffer[$index];
        unset($this->buffer[$index]);
        $this->buffer = \array_values($this->buffer);
        $this->loadBuffer();
        return $value;
    }

    private function loadBuffer() {
        for ($c = count($this->buffer); $c < $this->windowSize; $c++) {
            if ($this->file->eof()) {
                return;
            }
            $line = $this->file->fgets();
            if (false !== $line && "" !== $line) {
                $this->buffer[] = trim($line);
            }
        }
    }
}

class Packer
{

    const BAG_TARGET_WEIGHT = 1000;
    const MEAN_WEIGHT = 170;
    const MEAN_COUNT = 6; //ceil(self::BAG_WEIGHT/self::MEAN_WEIGHT);
    const MEAN_TARGET_WEIGHT = 167; //ceil(self::BAG_WEIGHT/self::MEAN_COUNT);

    public static function pack(Belt $belt, Picker $picker) {
        $bag = ["oranges" => [], "buffers" => []];
        $bags = [];
        while ($oranges = $belt->peekBuffer()) {

            $index = $picker->pick($oranges, \array_sum($bag["oranges"]));
            $orange = $belt->pick($index);
            $bag["oranges"][] = $orange;
            $bag["buffers"][] = $oranges;

            if (\array_sum($bag["oranges"]) >= self::BAG_TARGET_WEIGHT) {
                $bags[] = $bag;
                $bag = ["oranges" => [], "buffers" => []];
            }
        }
        return $bags;
    }
}

class Base
{
    public static function bestPermutation($elements, $weight = 0) {
        if (\array_sum($elements) < Packer::BAG_TARGET_WEIGHT - $weight) {
            return null;
        }
        $permute = function ($weight, $elements) use (&$permute) {
            if ($weight >= Packer::BAG_TARGET_WEIGHT) {
                return [];
            }
            $best = \PHP_INT_MAX;
            $bestElements = [];
            foreach ($elements as $key => $value) {
                $sum = $weight + $value;
                $els = [$value];
                if ($sum < Packer::BAG_TARGET_WEIGHT) {
                    $subSet = $elements;
                    unset($subSet[$key]);
                    $els = $permute($weight + $value, $subSet);
                    $els[] = $value;
                    $sum = $weight + \array_sum($els);
                }
                if ($sum >= Packer::BAG_TARGET_WEIGHT && $sum < $best) {
                    $best = $sum;
                    $bestElements = $els;
                }
            }
            return $bestElements;
        };
        $best = $permute($weight, $elements);

        return $best;
    }

    public function pickLightestOutOfHeavierThan($buffer, $targetWeight) {
        $b = -1;
        $bW = PHP_INT_MAX;
        foreach ($buffer as $key => $value) {
            if ($targetWeight <= $value && $value < $bW) {
                $b = $key;
                $bW = $value;
            }
        }
        return $b;
    }

    public function pickClosestTo($buffer, $targetWeight) {
        $b = -1;
        $bW = PHP_INT_MAX;
        foreach ($buffer as $key => $value) {
            $diff = \abs($targetWeight - $value);
            if ($diff < $bW) {
                $b = $key;
                $bW = $diff;
            }
        }
        return $b;
    }

    public function pickFurthestFrom($buffer, $targetWeight) {
        $b = -1;
        $bW = \PHP_INT_MIN;
        foreach ($buffer as $key => $value) {
            $diff = \abs($targetWeight - $value);
            if ($diff > $bW) {
                $b = $key;
                $bW = $diff;
            }
        }
        return $b;
    }

    public function findMax($buffer) {
        $i = -1;
        $m = 0;
        foreach ($buffer as $k => $v) {
            if ($v > $m) {
                $m = $v;
                $i = $k;
            }
        }
        return $i;
    }

    public function findMin($buffer) {
        $i = -1;
        $m = \PHP_INT_MAX;
        foreach ($buffer as $k => $v) {
            if ($v < $m) {
                $m = $v;
                $i = $k;
            }
        }
        return $i;
    }

    public function minimalOrangeCount($buffer, $weight) {
        $elementsToAdd = ceil((Packer::BAG_TARGET_WEIGHT - $weight) / Packer::MEAN_WEIGHT);
        $buffer = \array_merge($buffer,
            \array_fill(0, \floor($elementsToAdd / 2), Packer::MEAN_WEIGHT - 7),
            \array_fill(0, \floor($elementsToAdd / 2), Packer::MEAN_WEIGHT + 7),
            \array_fill(0, $elementsToAdd - \floor($elementsToAdd / 2) * 2, Packer::MEAN_WEIGHT)
        );
        \rsort($buffer);
        $orangeCount = 0;
        foreach ($buffer as $w) {
            $weight += $w;
            $orangeCount++;
            if ($weight >= Packer::BAG_TARGET_WEIGHT) {
                return $orangeCount;
            }
        }
        return $orangeCount + (Packer::BAG_TARGET_WEIGHT - $weight) / Packer::MEAN_WEIGHT;
    }
}


class Picker extends Base
{
    public function pick($buffer, $weight) {
        $weightNeeded = Packer::BAG_TARGET_WEIGHT - $weight;

        $minimalOrangeCount = $this->minimalOrangeCount($buffer, $weight);
        $orangeTargetWeight = ceil($weightNeeded / $minimalOrangeCount);

        if (0 === $weight) {
            $mean = \array_sum($buffer) / count($buffer);
            if ($mean > $orangeTargetWeight) {
                return $this->findMin($buffer);
            } elseif ($mean < $orangeTargetWeight) {
                return $this->findMax($buffer);
            }
            return $this->pickFurthestFrom($buffer, $orangeTargetWeight);
        }

        $i = $this->pickLightestOutOfHeavierThan($buffer, $weightNeeded);
        if (-1 !== $i) {
            return $i;
        }
        $i = $this->pickClosestTo($buffer, $orangeTargetWeight);
        return -1 !== $i ? $i : 0;
    }
}

$bagCount = 0;
$belt = new Belt(__DIR__ . "/oranges.txt", 0);
for ($l = 2; $l <= 7; $l++) {
    $belt->reset($l);
    $bags = Packer::pack($belt, new Picker());
    $bagCount += count($bags);
    printf("%d -> %d\n", $l, count($bags));
}
echo "Total: $bagCount\n";

2 -> 1645 3 -> 1657 4 -> 1663 5 -> 1667 6 -> 1671 7 -> 1672 कुल: 9975

कोशिश करो


अच्छा! मेरे लिए आश्चर्य की बात यह है कि यह वर्तमान आइटम गणना का उपयोग करता है - मुझे आश्चर्य है कि क्या इससे अधिक फैक्टर किया जा सकता है। सब के बाद, यह कोई फर्क नहीं पड़ता कि अगर 3 आइटम 120 प्रत्येक का वजन या 3 आइटम 160 प्रत्येक का वजन कर रहे हैं।
आंग्स

@ आंग शायद यह संभव है। करंट आइटम काउंट विचार के लिए एक सरल शॉर्टकट के रूप में सामने आया "अरे, कभी-कभी इसके 5 आइटम बैग करने के लिए संभव है" और मैंने 5 मिलियन बैग काम करने पर ट्यून किया। खाली समय के साथ सुधार आ जाएगा :)
mleko

3

पायथन 3, 9855 9928 9947 9956 9964 बैग

जोनाथन एलन के स्टार्टर कोड के आधार पर, लेकिन पठनीय होने के लिए अधूरा।

विचार: १०००/१ =० = ५., to के बाद से, हम १०००/६ के करीब फलों का चयन करने की कोशिश करते हैं (मैं जादू की कमी से परेशान था)। हालांकि, अगर बैग में अंतिम फल अपशिष्ट को कम कर सकता है, तो हम इसके बजाय इसका उपयोग करते हैं।

इस समाधान में जोड़े गए प्रत्येक फल के लिए बैग योग लक्ष्य हैं। मैं शायद यहीं रुक जाऊंगा। मैंने अपनी targetsसरणी खोजने के लिए Nelder-Mead का उपयोग किया :

[  165.79534144   343.58443287   522.58081597   680.76516204   845.93431713 1063.17204861]
def f(a, m, l, targets):
    bags = []
    bag = []
    bag_sum = 0
    while a:
        buffer = a[:l]
        finishers = tuple(filter(lambda w: bag_sum + w >= m, buffer))
        if finishers:
            next_fruits = [min(finishers)]

        else:
            ind = len(bag)
            next_fruits = [min(buffer, key=lambda w: abs(targets[ind]-bag_sum-w))]

        for next_fruit in next_fruits:
            bag.append(a.pop(a.index(next_fruit)))
            bag_sum += bag[-1]

        if sum(bag) >= m:
            bags.append(bag)
            bag = []  # Reset bag
            bag_sum = 0

    return bags

9956 बैग

from itertools import combinations

def f(a,m,l):
    bags = []
    bag = []
    while a:
        buffer = a[:l]
        next_fruit = None
        single_fruit = True

        finishers = [w for w in buffer if sum(bag) + w >= m ]
        if finishers: next_fruit = min(finishers)

        if not next_fruit:
            if len(buffer) >= 4 and sum(bag) < 600:
                next_fruits = min(combinations(buffer, 2), key=
                                  lambda ws: abs(2*169-sum(ws)))
                for fruit in next_fruits:
                    bag.append(a.pop(a.index(fruit)))

                single_fruit = False  # Skip adding single fruit

            else:
                next_fruit = min(buffer, key=lambda w: abs(171.5-w))

        if single_fruit:
            bag.append(a.pop(a.index(next_fruit)))

        if sum(bag)>=m:
            bags.append(bag)
            bag = []

    return bags


oranges = [int(x.strip()) for x in open("fruit.txt").readlines()]
bagLists = []
for lookahead in (2,3,4,5,6,7):
    bagLists.append(f(oranges[:], 1000, lookahead))


totalBagsOver1000 = sum(map(len, bagLists))
print('bags: ', (totalBagsOver1000))

9947 बैग कार्यक्रम विशेष रूप से आसान है:

def f(a,m,l):
    bags = []
    bag = []
    while a:
        buffer = a[:l]
        next_fruit = None

        finishers = [w for w in buffer if sum(bag) + w >= m ]
        if finishers: next_fruit = min(finishers)

        if not next_fruit:
            next_fruit = min(buffer, key=lambda w: abs(171.5-w))

        bag.append(a.pop(a.index(next_fruit)))

        if sum(bag)>=m:
            bags.append(bag)
            bag = []

    return bags

1
अच्छा! Btw, बस अंतिम आइटम उठा ताकि कचरे को कम करने के लिए अपने आप से काफी शक्तिशाली है और 9862 बैग देता है।
एंग्स

आप उन लोगों के साथ कैसे आए targets? यादृच्छिक डेटा पर प्रशिक्षण?
एलेक्स

1
@ एलेक्स मैंने ऐसा कहा: नेल्डर-मीड विधि (हानि समारोह के रूप में नकारात्मक बैग के साथ)
qwr

2

रूबी , 9967 बैग

def pick a, n
  if a.sum < n
    #return a.max
    d = n % 170
    return a.min_by{|w|
      [(w - d).abs, (w - d - 170).abs].min
    }
  end
  
  subsets = (0..a.length).map do |i|
    a.combination(i).to_a
  end.flatten(1)
  
  subsets.select!{|s|s.sum >= n}
  least_overkill = subsets.min_by{|s|s.sum}
  #puts "best: #{least_overkill.sort}"
  return least_overkill.min
end

def run list, weight, n
  bags = 0
  in_bag = 0
  while list.size > 0
    x = pick(list[0...n], weight - in_bag)
    i = list.index(x)
    raise new Exeption("not a valid weight") if(!i || i >= n)
    list.delete_at i
    in_bag += x
    if in_bag >= weight
      #puts in_bag
      in_bag = 0
      bags += 1
    end
  end
  return bags
end

इसे ऑनलाइन आज़माएं!

यदि आपके पास बैग को भरने के लिए पर्याप्त वजन है, तो सबसे हल्का सबसेट ढूंढें जो बैग को भर सकता है और उस सबसेट के सबसे हल्के नारंगी का उपयोग कर सकता है। अन्यथा, शेष वजन को 170 के एक से अधिक के करीब प्राप्त करें।


2

रैकेट / योजना, 9880 बैग

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

;; types

(define-struct bagger (fruit look tray bag bags)) ; fruit bagger

;; constants

(define MBW 1000) ; minimum bag weight
(define AFW 170) ; average piece-of-fruit weight
(define GAP (- MBW AFW)) ; targeted gap
(define FRUIT (file->list "fruit-supply.txt")) ; supplied fruit

;; utility functions

(define (weigh-it ls)
  (if (empty? ls)
      0
      (+ (car ls) (weigh-it (cdr ls)))))

(define (ref-to-car ls ref)
  (if (zero? ref)
      ls
      (let ((elem (list-ref ls ref)))
        (cons elem (remove elem ls)))))

;; predicates

(define (bag-empty? bgr) (empty? (bagger-bag bgr)))
(define (bag-full? bgr) (>= (weigh-it (bagger-bag bgr)) MBW))
(define (fruit-empty? bgr) (empty? (bagger-fruit bgr)))
(define (tray-empty? bgr) (empty? (bagger-tray bgr)))
(define (tray-full? bgr) (= (length (bagger-tray bgr)) (bagger-look bgr)))
(define (target-not-set? target value) (and (empty? target) (empty? value)))

;; pick best piece of fruit

(define (pf-rec tray bag i target value diff)
  (if (or (target-not-set? target value) (< diff value))
      (pick-fruit (cdr tray) bag (add1 i) i diff)
      (pick-fruit (cdr tray) bag (add1 i) target value)))

(define (pick-fruit tray bag i target value)
  (if (empty? tray)
      target
      (let ((weight (weigh-it (cons (car tray) bag))))
        (cond
          ((= weight MBW) i)
          ((> weight MBW) (pf-rec tray bag i target value (- weight MBW)))
          ((< weight MBW)
           (if (> weight GAP)
               (pf-rec tray bag i target value (- weight GAP))
               (pf-rec tray bag i target value (modulo (- MBW weight) AFW))))))))

;; load tray, bag, bags, etc.

(define (load-bag bgr)
  (let* ((tray (bagger-tray bgr))
         (bag (bagger-bag bgr))
         (weight (+ (weigh-it tray) (weigh-it bag))))
    (if (= weight MBW)
        (struct-copy bagger bgr
                     (tray empty)
                     (bag (append tray bag)))
        (let ((new-tray (ref-to-car tray (pick-fruit tray bag 0 empty empty))))
          (struct-copy bagger bgr
                       (tray (cdr new-tray))
                       (bag (cons (car new-tray) bag)))))))

(define (load-bags bgr)
  (struct-copy bagger bgr
               (bag empty)
               (bags (cons (bagger-bag bgr) (bagger-bags bgr)))))

(define (load-tray bgr)
  (struct-copy bagger bgr
               (fruit (cdr (bagger-fruit bgr)))
               (tray (cons (car (bagger-fruit bgr)) (bagger-tray bgr)))))

;; run the bagger factory

(define (run-bagger-aux bgr)
  (cond
    ((bag-full? bgr) (run-bagger-aux (load-bags bgr)))
    ((bag-empty? bgr)
     (cond
       ((tray-full? bgr) (run-bagger-aux (load-bag bgr)))
       ((tray-empty? bgr)
        (if (fruit-empty? bgr)
            (length (bagger-bags bgr))
            (run-bagger-aux (load-tray bgr))))
       (else
        (if (fruit-empty? bgr)
            (run-bagger-aux (load-bag bgr))
            (run-bagger-aux (load-tray bgr))))))
    (else
     (cond
       ((tray-full? bgr) (run-bagger-aux (load-bag bgr)))
       ((tray-empty? bgr)
        (if (fruit-empty? bgr)
            (run-bagger-aux (load-bags bgr))
            (run-bagger-aux (load-tray bgr))))
       (else
        (if (fruit-empty? bgr)
            (run-bagger-aux (load-bag bgr))
            (run-bagger-aux (load-tray bgr))))))))

(define (run-bagger fruit look)
  (run-bagger-aux (make-bagger fruit look empty empty empty)))

;; stackexchange problem run

(define (run-problem fruit looks)
  (if (empty? looks)
      0
      (+ (run-bagger fruit (car looks)) (run-problem fruit (cdr looks)))))

(run-problem FRUIT '(2 3 4 5 6 7)) ; result = 9880

1

हास्केल , 9777 बैग

यह मेरा पहला प्रयास था:

  • यह लालच से एक बैग से भरा बैग जब यह कर सकता था,
  • या जब यह नहीं हो सकता तो सभी संतरे को बैग में बहा दिया।
options[]=[(0,([],[]))]
options(first:rest)=[option|(sum,(now,later))<-options rest,
 option<-[(sum+first,(first:now,later)),(sum,(now,first:later))]]
bags _[_]_=[]
bags(w_sum,w_bag)(w_kilo:w_iyts)w_view=
 let(w_take,w_remd)=splitAt(w_view)w_iyts;
     w_fill=filter((>=(w_kilo-w_sum)).fst)(options w_take)
 in if null w_fill then bags(w_sum+sum w_take,w_bag++w_take)(w_kilo:w_remd)w_view
    else let(_,(w_now,w_later))=minimum w_fill in
         (w_bag++w_now):bags(0,[])(w_kilo:w_later++w_remd)w_view
main=print.sum$map(length.bags(0,[])(1000:batch))[2..7]

इसे ऑनलाइन आज़माएं!


1

हास्केल , 9981 बैग

एंजेल्सजोनाथन एलनजेसीईफोरट्रानएलेक्सरोमन कैज़बोर्रा कोडगॉल्फ पायथन विचार के एक ही प्रमुख ट्रेन के साथ कुछ जोड़ा गणितीय शुद्धता के लिए हास्केल को वापस चक्रवात कर सकता है।

  • नए संतरे को विचार में शामिल करने से पहले केवल एक नारंगी को छीना जाता है
  • पूर्वाग्रह पर्याप्त फल देना पसंद करते हैं ( (<miss)==False<True)
  • पूर्वाग्रह सबसे अधिक पूर्णांक भरने वाले फलों को पसंद करते हैं
  • उस पूर्णांक
    (m-n)/sqrt(n)==(n+1-m)/sqrt(n+1) <==> n=sqrt(m^2-1/4)-1/2 से एक https://en.wikipedia.org/wiki/Sum_of_normally_distributed_random_variables से उल्टा

    https://m.wolframalpha.com/input/?i=plot+abs (1-एक्स) * sqrt (1), पेट (2-एक्स) * sqrt (2), पेट (3-एक्स) * sqrt ( 3), एबीएस (4-x) * sqrt (4)

कुछ आवश्यक व्यर्थता के साथ अनुभवी

subsets[]=[[]];subsets(f:t)=[r|s<-subsets t,r<-[s,f:s]]
mean=uncurry(div).(id***max 1).(sum&&&length)
bags[]_ _=[];bags batch(miss:have)n=let
 goal=div miss$ceiling(sqrt((fromIntegral miss/170)^2+1/4)-1/2)
 best=minimumBy.comparing.(((<miss)&&&(abs.(goal-))).); desk=take n batch
 pick=best id.best(if sum desk<miss then mean else sum).filter(>[]).subsets$desk
 in if pick < miss then bags(delete pick batch)(miss-pick:pick:have)n
       else (pick:have):bags(delete pick batch)[miss+sum have]n
main=print$id&&&sum$map(length.bags batch[1000])[2..7]

इसे ऑनलाइन आज़माएं!

एक अलग संख्यात्मक लाभ प्राप्त करने के बिना, संतरे के 9981 जालों की कटाई हुई, जबकि मेरा 10k011 बैग पैकर अनफिट संतरे को वापस ले आया, जिसमें से खाली बैगों को बाहर निकाल दिया गया, person69850 by persona 20202729Jo Kingovs अयोग्य घोषित किया गया, जिसके बाद वह योग्य बाउंटी एलेक्स के पास गया।

GIMME BOUNTY!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.