ফলের ব্যাগিং কারখানা


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
লোকেরা আসুন, আমি মনে করি এখনও কিছু কম ঝুলন্ত ফল অ্যালগরিদম এখনও
বাছাইয়ের

2
প্রোগ্রামগুলি কি গড় ওজন / বিতরণকে হার্ডকোড করতে পারে? (ধরে নিন যে এটি একই ধরণের ব্যাচে সমানভাবে কাজ করে, অবশ্যই হার্ডকোডিং সমস্ত কিছু অবৈধ কারণ এটি সীমিত
দর্শনের

@ ব্যবহারকারী 202729: হ্যাঁ তারা পারেন।
অ্যাঙ্গস

এবং সমস্ত কিছু হার্ডকোডিং যাই হোক না কেন একটি নিষিদ্ধ মান লুফোল ।
এঙ্গগুলি

লুকহেড কী তা আমি দেখতে পাচ্ছি না
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)))

চেষ্টা করে দেখুন!


খুব সুন্দর! এটি 772 এর চেহারা সহ 1672 পায়, এটি এর চেয়ে বেশি কখনও দেখেনি।
অ্যাঙ্গস

(দেখে মনে হচ্ছে যে আপনার powersetফাংশনের দ্বিতীয় len(list_)
তর্কটি

@ ব্যবহারকারী আমি পূর্ববর্তী সংস্করণে এই পরামিতিটি নিয়ে পরীক্ষা করেছি। সম্ভবত এটি পরে সরিয়ে ফেলবে
অ্যালেক্স

1
সেরা সাবসেটের বাইরে সেরা একক উপাদানের শক্তিশালী সমন্বয় আবিষ্কার করার জন্য এবং সেরা স্কোর অর্জনের জন্য অভিনন্দন! অনুগ্রহ তোমার।
অ্যাঙ্গস

একটি সহজ expected_mean(w)যা ভাল ফলাফল হিসাবে দেয়:return (w+2) / max(1, round((w+2) / mean))
অ্যাঙ্গস

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

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


পিপিসিজিতে আপনাকে স্বাগতম!
মার্টিন এন্ডার

@ মার্টিনএন্ডার স্বাগত উপস্থাপনের জন্য মার্টিনকে ধন্যবাদ জানায় :)
জেইসি

1
আহ হ্যাঁ আমি সেখানে একটি কৌশল মিস করেছি ... অন্য উত্তর হিসাবে আমার এতে কোনও সমস্যা নেই!
জোনাথন অ্যালান

1
@ জোনাথন অ্যালান ধন্যবাদ জোনাথন আমি আপনাকে সমস্ত ক্ষমা প্রার্থনা ছাড়াই কৃতিত্বের জন্য আমার উত্তরটি সংক্ষিপ্ত করে রেখেছি। এটি সাধারণ (১ 170০,১13) বিতরণ করে এটিকে উন্নত করা যেতে পারে - আমি নিশ্চিত যে পরবর্তী রান (গুলি) এর ক্ষেত্রে আরও ভাল ফল পাওয়ার সম্ভাবনা ব্যবহার করা যেতে পারে।
জেসি

@ জাসি বিপজ্জনকভাবে জুবেলারদের মিথ্যাচারের কাছাকাছি শব্দ শোনায়।
qwr

6

সি ++ 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 টি পুনরাবৃত্তির জন্য টিআইও লিঙ্ক: এটি অনলাইনে চেষ্টা করুন!


একটি ফাংশন সংজ্ঞায়িত করে (আসলে এটি কেবল কোনও ফাংশনের মতো লাগে, এটি একটি কাঠামো) pick_orangeযা vector<int> weightsকমলার ওজন দেওয়া হয় এবংint remain ওজন এবং ব্যাগের অবশিষ্ট ওজন সূচক দেয় যা বাছাই করা উচিত।

অ্যালগরিদম:

পুনরাবৃত্তি 500বার {
উত্পন্ন র্যান্ডম (জাল) কমলালেবু (গড় 170 এবং stddev 13 সাধারন বন্টনের) পর্যন্ত আছে N_NEW_ORANGES=7কমলালেবু
কোনো উপসেট যার সমষ্টি সবচেয়ে ছোট এবং চেয়ে ছোট বাছাই remain(ফাংশন backtrackযে না)
হিসাবে উপসেট সমস্ত কমলালেবু চিহ্নিত ভাল
}

কমলা সমান ওজনযুক্ত কমলার (আসল) কমলাগুলির হিসাবে ভাল হিসাবে চিহ্নিত হওয়ার পরে গড়
কমলা ফিরে আসে


প্রোগ্রামটিতে 3 টি হার্ডকোডযুক্ত ধ্রুবক রয়েছে যা সমস্যা থেকে অনুমান করা যায় না:

  • এলোমেলো বীজ (এটি গুরুত্বপূর্ণ নয়)
  • N_NEW_ORANGES(পূর্বাভাস দৈর্ঘ্য)। এটি বৃদ্ধির ফলে প্রোগ্রামটি দীর্ঘতর হয়ে যায় (কারণ ব্যাকট্র্যাক)
  • পুনরাবৃত্তি সংখ্যা। এটি বাড়ানোর ফলে প্রোগ্রামটি দীর্ঘতর হয়।

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

শেষ পর্যন্ত একটি নতুন জিসিসি পাওয়ার পরে এটি সংকলন করতে পেল। এলোমেলো বীজ সহ 50 রানের উপরে এটি 9961.58 গড়ে পেয়েছে। এখনও খুব চিত্তাকর্ষক। যদিও আমাকে বিস্মিত করেছে - আপনার অ্যালগরিদম মূলত প্রতিটি ব্যাগে আবার নিজেকে প্রশিক্ষণ দেয়, এমন কোনও সেরা মান আছে যা মুখস্থ হতে পারে?
অ্যাঙ্গস

@ আমার মনে হয় না এমন কোনও উপায় আছে যা এই ক্ষেত্রে সাহায্যের জন্য মুখস্ত ব্যবহার করতে পারে। কোন ধারণা?
ব্যবহারকারী 202729

আমার ওএস জিসিসি 5.4.0 নিয়ে আসে, এতে কিছু সমস্যা ছিল 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 ব্যাগ

জোনাথন এবং জাইসির জবাবগুলির ভিত্তিতে বিল্ডিং:

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 ইউনিটের ফলটি লুকের তালিকার তালিকার শুরুতে খুব কাছাকাছি থাকে, তবে minএটি 101 এর পরিবর্তে এটি নির্বাচন করবে this যদি এটি ঘটে থাকে তবে আমাদের প্রয়োজন বাকী 1 ইউনিটটি পূরণ করতে এখন আর একটি ফলের প্রয়োজন হবে। এই ক্ষেত্রে উচ্চমূল্যের ফলের পক্ষে আমি প্রোগ্রামটি পরিবর্তন করেছি।

এটি বাছাই করে এবং তারপরে পাওয়ারসেটিংয়ের পূর্বে তালিকার তালিকার বিপরীত করে এটি করে।


4

পিএইচপি, 9975 ব্যাগ

  • সম্ভব হলে ৫ টি কমলার জন্য যান
  • ব্যাগ শুরু করার সময় চূড়ান্ত মান বাছাই করুন, পরে ভারসাম্য করুন
  • সম্ভব হলে তাত্ক্ষণিকভাবে ব্যাগ পূরণ করুন
  • ব্যাগের ওজন আনুমানিক বক্ররেখার কাছাকাছি রাখার চেষ্টা করুন (5 ব্যাগের জন্য n * 200, 6 ব্যাগের জন্য n * 167)

সমস্ত জমাগুলির মধ্যে দীর্ঘতম তবে পাঠযোগ্য read

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 টি আইটেম ব্যাগ কাজ করার চেষ্টা করেছিলাম। নিখরচায় সময়ের উন্নতি আসবে :)
ম্লেকো

3

পাইথন 3, 9855 9928 9947 9956 9964 ব্যাগ

জোনাথন অ্যালানের স্টার্টার কোডের উপর ভিত্তি করে, তবে পাঠযোগ্য হতে পারে না।

আইডিয়া: 1000/170 = 5.88 থেকে, আমরা 1000/6 এর কাছাকাছি ফল নির্বাচন করার চেষ্টা করি (আমি ম্যাজিক ধ্রুবকগুলিতে ফিডলাম)। তবে, ব্যাগের শেষ ফলটি যদি বর্জ্য হ্রাস করতে পারে তবে আমরা তার পরিবর্তে এটি ব্যবহার করি।

এই দ্রবণটিতে যুক্ত প্রতিটি ফলের জন্য ব্যাগের যোগফল রয়েছে। আমি সম্ভবত এখানে থামব। আমি আমার targetsঅ্যারের সন্ধান করতে নেল্ডার-মাড ব্যবহার করেছি :

[  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
ভাল! বিটিডব্লিউ, কেবলমাত্র সর্বশেষ আইটেমটি বাছাই করা যাতে বর্জ্য হ্রাস করা যায় তা নিজেই বেশ শক্তিশালী এবং 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 ব্যাগ

Angsজনাথন অ্যালানJayCefortraanঅ্যালেক্স রোমান Czyborra codegolf পাইথন কিছু যোগ গাণিতিক বিশুদ্ধতা চিন্তার একই প্রধান ট্রেন বরাবর জন্য Haskell, ফিরে cyclize পারে

  • নতুন কমলা বিবেচনায় যুক্ত হওয়ার আগে কেবল একটি কমলা বাদ দেওয়া হয়
  • পক্ষপাত পর্যাপ্ত ফল পছন্দ ((<miss)==False<True )
  • পক্ষপাতগুলি সম্ভবত ফলগুলি সবচেয়ে বেশি সংখ্যায় পূর্ণ হয়
  • সেই পূর্ণসংখ্যার জন্য
    (m-n)/sqrt(n)==(n+1-m)/sqrt(n+1) <==> n=sqrt(m^2-1/4)-1/2 কোনও https://en.wikedia.org/wiki/Sum_of_normally_distributes_random_variables থেকে বিপরীত করুন

    https://m.wolframalpha.com/input/?i=plot+abs (1-X) * বর্গমূল (1), ABS (2-এক্স) * বর্গমূল (2), ABS (3-এক্স) * SQRT ( 3) ABS (4-X) * বর্গমূল (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 ব্যাগ অযোগ্য কমলালেবু দখল প্যাকার বন্ধ না ব্যাগ থেকে বের করে ব্যাক দ্বারা অনুপযুক্ত ঘোষণা করা হয় user69850 মধ্যে ব্যক্তিত্বের user202729জো রাজাovs hencefore প্যানেলস খয়রাত গিয়েছিলাম অ্যালেক্স

গিমের পরিমাণ!

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.