সমষ্টি মুক্ত পার্টিশন সন্ধান করা হচ্ছে


17

নির্বাহী সারসংক্ষেপ

ইনপুট দেওয়া k, পূর্ণসংখ্যার একটি পার্টিশন খুঁজে 1থেকে nমধ্যে kবৃহত্তম জন্য সমষ্টি-মুক্ত সাব-সেট নির্বাচন n10 মিনিটের মধ্যে আপনি যা করতে পারেন।

পটভূমি: শুর সংখ্যা

একটি সেট Aহয় সমষ্টি-মুক্ত যদি তার স্ব-সমষ্টি A + A = { x + y | x, y in A}এটা সঙ্গে সাধারণ কোন উপাদানগুলি নেই।

প্রত্যেক ধনাত্মক পূর্ণ সংখ্যা জন্য kসেখানে পূর্ণসংখ্যা একটি বৃহত্তম S(k)যেমন যে সেট {1, 2, ..., S(k)}বিভক্ত করা যেতে পারে kসমষ্টি-মুক্ত সাব-সেট নির্বাচন। এই সংখ্যাটিকে কে শুর নাম্বার (OEIS A045652 ) বলা হয়।

উদাহরণস্বরূপ S(2) = 4,। আমরা {1, 2, 3, 4}হিসাবে পার্টিশন করতে পারি {1, 4}, {2, 3}, এবং এটি দুটি যোগ-মুক্ত সাবসেটগুলিতে অনন্য পার্টিশন, তবে আমরা এখন 5উভয় অংশে একটি যোগ করতে পারি না ।

চ্যালেঞ্জ

একটি নিরোধক প্রোগ্রাম লিখুন যা নিম্নলিখিতগুলি করে:

  • kইনপুট হিসাবে একটি ধনাত্মক পূর্ণসংখ্যা নিন Take
  • স্টডআউটে বর্তমান ইউনিক্স টাইমস্ট্যাম্প লিখুন
  • বর্তমান ইউনিক্স টাইমস্ট্যাম্পের সাথে প্রতিটি ক্রম অনুসরণ করে বৃদ্ধি 1করার nজন্য kযোগ-মুক্ত সাবসেটে পার্টিশনের একটি ক্রম আউটপুট দেয় n

বিজয়ী হ'ল এমন প্রোগ্রাম যা nইনপুট দেওয়ার সময় আমার কম্পিউটারে 10 মিনিটের মধ্যে বৃহত্তমের জন্য একটি পার্টিশন প্রিন্ট করে 5nতিনটি রানের গড় গড়ে সবচেয়ে বড় পার্টিশন খুঁজে পাওয়ার জন্য দ্রুততম সময়ের সাথে সম্পর্ক ছিন্ন করা হবে : এজন্য আউটপুটটিতে টাইমস্ট্যাম্প অন্তর্ভুক্ত করা উচিত।

গুরুত্বপূর্ণ বিশদ:

  • আমার উবুন্টু যথার্থতা রয়েছে, সুতরাং আপনার ভাষাটি সমর্থন না করা থাকলে আমি এটি স্কোর করতে অক্ষম।
  • আমার একটি ইন্টেল কোর 2 কোয়াড সিপিইউ রয়েছে, সুতরাং আপনি যদি মাল্টিথ্রেডিং ব্যবহার করতে চান তবে 4 টির বেশি থ্রেড ব্যবহার করার কোনও অর্থ নেই।
  • আপনি যদি চান যে আমি কোনও নির্দিষ্ট সংকলক পতাকা বা বাস্তবায়ন ব্যবহার করতে চাই, তবে ডকুমেন্টটি যা আপনার উত্তরে স্পষ্টভাবে উপস্থিত রয়েছে।
  • ইনপুট পরিচালনা করতে আপনার কোডটি আপনার বিশেষ ক্ষেত্রে করা উচিত নয় 5
  • আপনি যে প্রতিটি উন্নতি পেয়েছেন তা আউটপুট দেওয়ার দরকার নেই। যেমন ইনপুট জন্য 2আপনি কেবল পার্টিশনটি আউটপুট করতে পারেন n = 4। তবে, যদি আপনি প্রথম 10 মিনিটের মধ্যে কিছু না আউটপুট করেন তবে আমি এটি হিসাবে স্কোর করব n = 0

উত্তর:


8

পাইথন 3, সর্বাধিক সংখ্যা অনুসারে বাছাই করুন, n = 92 121

অপ্রত্যাশিতভাবে সর্বোচ্চ nপৌঁছেছে এমন একটি পরামর্শের জন্য মার্টিন বাটনারকে ধন্যবাদ ।

শেষ আউটপুট:

[2, 3, 11, 12, 29, 30, 38, 39, 83, 84, 92, 93, 110, 111, 119, 120]
[1, 4, 10, 13, 28, 31, 37, 40, 82, 85, 91, 94, 109, 112, 118, 121]
[5, 6, 7, 8, 9, 32, 33, 34, 35, 36, 86, 87, 88, 89, 90, 113, 114, 115, 116, 117]
[14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108]
[41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81]

অ্যালগরিদম আমার আগের উত্তর হিসাবে একই, নীচে উদ্ধৃত:

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

... একটি ব্যতিক্রম সহ: বিন ক্রমটি বদলানো হয় না । পরিবর্তে, এটি এমনভাবে সাজানো হয় যে সর্বাধিক সংখ্যার সাথে থাকা বিনগুলি প্রথমে আসে। এটি n = 1218 সেকেন্ডে পৌঁছেছে !

কোড:

from copy import deepcopy
from random import shuffle, seed
from time import clock, time
global maxN
maxN = 0
clock()

def search(k,nextN=1,sets=None):
    global maxN
    if clock() > 600: return

    if nextN == 1: #first iteration
        sets = []
        for i in range(k):
            sets.append([[],[]])

    sets.sort(key=lambda x:max(x[0]or[0]), reverse=True)
    for i in range(k):
        if clock() > 600: return
        if nextN not in sets[i][1]:
            sets2 = deepcopy(sets)
            sets2[i][0].append(nextN)
            sets2[i][1].extend([nextN+j for j in sets2[i][0]])
            nextN2 = nextN + 1

            if nextN > maxN:
                maxN = nextN
                print("New maximum!",maxN)
                for s in sets2: print(s[0])
                print(time())
                print()

            search(k, nextN2, sets2)

search(5)

নোট: অননুমোদিত সংখ্যার পরিসীমা দেয় মধ্যে ব্যবহার করা যাবে সংখ্যার সর্বাধিক সংখ্যা দ্বারা বাছাই n=59, এবং কম দেয়া সংখ্যার সর্বাধিক সংখ্যা দ্বারা বাছাই nextNদেয় n=64। প্রত্যাখ্যানিত সংখ্যা তালিকার দৈর্ঘ্য অনুসারে বাছাই করা (যা পুনরাবৃত্তি হতে পারে) খুব দ্রুত একটি মার্জিত n=30প্যাটার্নে নিয়ে যায়।
এল'েন্ডিয়া স্টারম্যান

আউটপুট সময়ের ফর্ম্যাটটি সঠিক নয় (যুগের আগে থেকে কয়েক সেকেন্ড হওয়া উচিত, তবে আমি দেখছি Tue Nov 10 00:44:25 2015), তবে আমি n=922 সেকেন্ডেরও কম সময়ে দেখেছি ।
পিটার টেলর

আহ, আমি বুঝতে পেরেছি যে সময় ফর্ম্যাটটি ঠিক কতটা সময় নিয়েছিল তা দেখানোর মতো গুরুত্বপূর্ণ ছিল না। আমি এটি খুঁজে বের করতে এবং এটি পরিবর্তন করব। সম্পাদনা: ডিওহ আমি বাছাই করা ctimeউপর timeকারণ আউটপুট সুন্দর ছিল যখন timeছিল আমি ঠিক কি বেছে নিলে করা উচিত নয়।
এল'েন্ডিয়া স্টারম্যান

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

@ মার্টিনবাটনার: ...... আমি ... আহ ... কীভাবে বা কেন জানি না, তবে তা পায় n=121। ও
এল'েন্ডিয়া স্টারম্যান

7

পাইথন 3, 121, <0.001 সে

মার্টিন বাটনারকে উন্নততর হিউরিস্টিক ধন্যবাদ মানে আমাদের এমনকি এলোমেলোতার প্রয়োজন নেই।

আউটপুট:

1447152500.9339304
[1, 4, 10, 13, 28, 31, 37, 40, 82, 85, 91, 94, 109, 112, 118, 121]
[2, 3, 11, 12, 29, 30, 38, 39, 83, 84, 92, 93, 110, 111, 119, 120]
[5, 6, 7, 8, 9, 32, 33, 34, 35, 36, 86, 87, 88, 89, 90, 113, 114, 115, 116, 117]
[14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108]
[41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81]
1447152500.934646 121

কোড:

from copy import deepcopy
from random import seed, randrange
from time import clock, time
from cProfile import run

n = 5

seed(0)

def heuristic(bucket):
    return len(bucket[0]) and bucket[0][-1]

def search():
    best = 0
    next_add = 1
    old_add = 0
    lists = [[[],set()] for _ in range(n)]
    print(time())
    while clock() < 600 and next_add != old_add:
        old_add = next_add
        lists.sort(key=heuristic, reverse=True)
        for i in range(n):
            if next_add not in lists[i][1]:
                lists[i][0].append(next_add)
                lists[i][1].update([next_add + old for old in lists[i][0]])
                if next_add > best:
                    best = next_add
                next_add += 1
                break

    for l in lists:
        print(l[0])
    print(time(), next_add-1, end='\n\n')

search()

পাইথন 3, 112

প্রথম 2 টি উপাদান + স্কিউ এর যোগফল অনুসারে বাছাই করুন

[40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79]
[7, 8, 9, 10, 11, 12, 13, 27, 28, 29, 30, 31, 32, 33, 80, 81, 82, 83, 84, 85, 86, 100, 101, 102, 103, 104, 105, 106]
[3, 4, 14, 19, 21, 26, 36, 37, 87, 92, 94, 99, 109, 110]
[2, 5, 16, 17, 20, 23, 24, 35, 38, 89, 90, 96, 97, 108, 111]
[1, 6, 15, 18, 22, 25, 34, 39, 88, 91, 93, 95, 98, 107, 112]
1447137688.032085 138.917074 112

আমি এল'েন্দিয়া স্টারম্যানের ডেটা স্ট্রাকচারটি অনুলিপি করেছিলাম যা জোড়াগুলির তালিকা নিয়ে গঠিত, যেখানে জোড়ার প্রথম উপাদানটি সেই বালতির উপাদানগুলি এবং দ্বিতীয়টি সেই বালতিটির যোগফল।

আমি একই "ট্রাঙ্কগুলি কী পরিমাণগুলি প্রাপ্য তা উপলভ্য" ট্র্যাকের সাথে শুরু করি। আমার বাছাই করা হিউরিস্টিক হ'ল একটি প্রদত্ত তালিকার মধ্যে ক্ষুদ্রতম দুটি উপাদানের যোগফল। আমি বিভিন্ন সম্ভাবনার চেষ্টা করতে একটি ছোট এলোমেলো স্কুও যুক্ত করি।

প্রতিটি পুনরাবৃত্তি প্রতিটি নতুন সংখ্যাটিকে এলোমেলো লোভের অনুরূপ প্রথম উপলভ্য বিনে রাখে। একবার এটি ব্যর্থ হয়ে গেলে, এটি কেবল পুনরায় আরম্ভ হয়।

from copy import deepcopy
from random import seed, randrange
from time import clock, time

n = 5

seed(0)

def skew():
    return randrange(9)

best = 0
next_add = old_add = 1
while clock() < 600:
    if next_add == old_add:
        lists = [[[],[]] for _ in range(n)]
        next_add = old_add = 1
    old_add = next_add
    lists.sort(key=lambda x:sum(x[0][:2]) + skew(), reverse=True)
    for i in range(n):
        if next_add not in lists[i][1]:
            lists[i][0].append(next_add)
            lists[i][1].extend([next_add + old for old in lists[i][0]])
            if next_add > best:
                best = next_add
                for l in lists:
                    print(l[0])
                print(time(), clock(), next_add, end='\n\n')
            next_add += 1
            break

বাহ, এটি আমার কোডের সাথে অত্যন্ত মিল দেখাচ্ছে similar : পি;) (আমার মোটেই আপত্তি নেই।)
এল'েন্ডিয়া স্টারম্যান

@ এল'এন্ডিয়াস্টারম্যান ক্রেডিট যুক্ত হয়েছে এটি একটি দুর্দান্ত ভিত্তি।
isaacg

7

জাভা 8, এন = 142 144

শেষ আউটপুট:

@ 0m 31s 0ms
n: 144
[9, 12, 17, 20, 22, 23, 28, 30, 33, 38, 41, 59, 62, 65, 67, 70, 72, 73, 75, 78, 80, 83, 86, 91, 107, 115, 117, 122, 123, 125, 128, 133, 136]
[3, 8, 15, 24, 25, 26, 31, 35, 45, 47, 54, 58, 64, 68, 81, 87, 98, 100, 110, 114, 119, 120, 121, 130, 137, 142]
[5, 13, 16, 19, 27, 36, 39, 42, 48, 50, 51, 94, 95, 97, 103, 106, 109, 112, 118, 126, 129, 132, 138, 140, 141]
[2, 6, 11, 14, 34, 37, 44, 53, 56, 61, 69, 76, 79, 84, 89, 92, 101, 104, 108, 111, 124, 131, 134, 139, 143, 144]
[1, 4, 7, 10, 18, 21, 29, 32, 40, 43, 46, 49, 52, 55, 57, 60, 63, 66, 71, 74, 77, 82, 85, 88, 90, 93, 96, 99, 102, 105, 113, 116, 127, 135]

4 টি থ্রেডের উপরে বিতরণ করা একটি বদ্ধ র্যান্ডম অনুসন্ধান সম্পাদন করে। এটিতে উপযুক্ত পার্টিশনটি যখন এটি খুঁজে পাচ্ছে না তখন এটি অন্য পার্টিশনে যতটুকু পারে ডাম্প করে একবারে একটি পার্টিশনের nজন্য স্থান খালি করার চেষ্টা করে n

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

দ্রষ্টব্য: আউটপুটটি কঠোরভাবে নিয়ন্ত্রক নয় কারণ এতে একাধিক থ্রেড জড়িত রয়েছে এবং এগুলি nএখনও অবধি বিচলিত ক্রমে সেরা পাওয়া আপডেট করতে পারে; 144 এর শেষ স্কোরটি যদিও নির্বিচারে এবং মোটামুটি দ্রুত পৌঁছে যায়: আমার কম্পিউটারে 30 সেকেন্ড।

কোডটি হ'ল:

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

public class SumFree {

    private static int best;

    public static void main(String[] args) {
        int k = 5; // Integer.valueOf(args[0]);
        int numThreadsPeterTaylorCanHandle = 4;

        long start = System.currentTimeMillis();
        long end = start + TimeUnit.MINUTES.toMillis(10);

        System.out.println(start);

        Random rand = new Random("Lucky".hashCode());
        for (int i = 0; i < numThreadsPeterTaylorCanHandle; i++) {
            new Thread(() -> search(k, new Random(rand.nextLong()), start, end)).start();
        }
    }

    private static void search(int k, Random rand, long start, long end) {
        long now = System.currentTimeMillis();
        int localBest = 0;

        do {
            // create k empty partitions
            List<Partition> partitions = new ArrayList<>();
            for (int i = 0; i < k; i++) {
                partitions.add(new Partition());
            }

            Deque<Choice> pastChoices = new ArrayDeque<>();
            int bestNThisRun = 0;

            // try to fill up the partitions as much as we can
            for (int n = 1;; n++) {
                // list of partitions that can fit n
                List<Partition> partitionsForN = new ArrayList<>(k);
                for (Partition partition : partitions) {
                    if (!partition.sums.contains(n)) {
                        partitionsForN.add(partition);
                    }
                }

                // if we can't fit n anywhere then try to free up some space
                // by rearranging partitions
                Set<Set<Set<Integer>>> rearrangeAttempts = new HashSet<>();
                rearrange: while (partitionsForN.size() == 0 && rearrangeAttempts
                        .add(partitions.stream().map(Partition::getElements).collect(Collectors.toSet()))) {

                    Collections.shuffle(partitions, rand);
                    for (int candidateIndex = 0; candidateIndex < k; candidateIndex++) {
                        // partition we will try to free up
                        Partition candidate = partitions.get(candidateIndex);
                        // try to dump stuff that adds up to n into the other
                        // partitions
                        List<Integer> badElements = new ArrayList<>(candidate.elements.size());
                        for (int candidateElement : candidate.elements) {
                            if (candidate.elements.contains(n - candidateElement)) {
                                badElements.add(candidateElement);
                            }
                        }
                        for (int i = 0; i < k && !badElements.isEmpty(); i++) {
                            if (i == candidateIndex) {
                                continue;
                            }

                            Partition other = partitions.get(i);

                            for (int j = 0; j < badElements.size(); j++) {
                                int candidateElement = badElements.get(j);
                                if (!other.sums.contains(candidateElement)
                                        && !other.elements.contains(candidateElement + candidateElement)) {
                                    boolean canFit = true;
                                    for (int otherElement : other.elements) {
                                        if (other.elements.contains(candidateElement + otherElement)) {
                                            canFit = false;
                                            break;
                                        }
                                    }

                                    if (canFit) {
                                        other.elements.add(candidateElement);
                                        for (int otherElement : other.elements) {
                                            other.sums.add(candidateElement + otherElement);
                                        }
                                        candidate.elements.remove((Integer) candidateElement);
                                        badElements.remove(j--);
                                    }
                                }
                            }
                        }

                        // recompute the sums
                        candidate.sums.clear();
                        List<Integer> elementList = new ArrayList<>(candidate.elements);
                        int elementListSize = elementList.size();
                        for (int i = 0; i < elementListSize; i++) {
                            int ithElement = elementList.get(i);
                            for (int j = i; j < elementListSize; j++) {
                                int jthElement = elementList.get(j);
                                candidate.sums.add(ithElement + jthElement);
                            }
                        }

                        // if candidate can now fit n then we can go on
                        if (!candidate.sums.contains(n)) {
                            partitionsForN.add(candidate);
                            break rearrange;
                        }
                    }
                }

                // if we still can't fit in n, then go back in time to our last
                // choice (if it's saved) and this time choose differently
                if (partitionsForN.size() == 0 && !pastChoices.isEmpty() && bestNThisRun > localBest - localBest / 3) {
                    Choice lastChoice = pastChoices.peek();
                    partitions = new ArrayList<>(lastChoice.partitions.size());
                    for (Partition partition : lastChoice.partitions) {
                        partitions.add(new Partition(partition));
                    }
                    n = lastChoice.n;
                    Partition partition = lastChoice.unchosenPartitions
                            .get(rand.nextInt(lastChoice.unchosenPartitions.size()));
                    lastChoice.unchosenPartitions.remove(partition);
                    partition = partitions.get(lastChoice.partitions.indexOf(partition));
                    partition.elements.add(n);
                    for (int element : partition.elements) {
                        partition.sums.add(element + n);
                    }
                    if (lastChoice.unchosenPartitions.size() == 0) {
                        pastChoices.pop();
                    }
                    continue;
                }

                if (partitionsForN.size() > 0) {
                    // if we can fit in n somewhere,
                    // pick that somewhere randomly
                    Partition chosenPartition = partitionsForN.get(rand.nextInt(partitionsForN.size()));
                    // if we're making a choice then record it so that we may
                    // return to it later if we get stuck
                    if (partitionsForN.size() > 1) {
                        Choice choice = new Choice();
                        choice.n = n;
                        for (Partition partition : partitions) {
                            choice.partitions.add(new Partition(partition));
                        }
                        for (Partition partition : partitionsForN) {
                            if (partition != chosenPartition) {
                                choice.unchosenPartitions.add(choice.partitions.get(partitions.indexOf(partition)));
                            }
                        }
                        pastChoices.push(choice);

                        // only keep 3 choices around
                        if (pastChoices.size() > 3) {
                            pastChoices.removeLast();
                        }
                    }

                    chosenPartition.elements.add(n);
                    for (int element : chosenPartition.elements) {
                        chosenPartition.sums.add(element + n);
                    }
                    bestNThisRun = Math.max(bestNThisRun, n);
                }

                if (bestNThisRun > localBest) {
                    localBest = Math.max(localBest, bestNThisRun);

                    synchronized (SumFree.class) {
                        now = System.currentTimeMillis();

                        if (bestNThisRun > best) {
                            // sanity check
                            Set<Integer> allElements = new HashSet<>();
                            for (Partition partition : partitions) {
                                for (int e1 : partition.elements) {
                                    if (!allElements.add(e1)) {
                                        throw new RuntimeException("Oops!");
                                    }
                                    for (int e2 : partition.elements) {
                                        if (partition.elements.contains(e1 + e2)) {
                                            throw new RuntimeException("Oops!");
                                        }
                                    }
                                }
                            }
                            if (allElements.size() != bestNThisRun) {
                                throw new RuntimeException("Oops!" + allElements.size() + "!=" + bestNThisRun);
                            }

                            best = bestNThisRun;
                            System.out.printf("@ %dm %ds %dms\n", TimeUnit.MILLISECONDS.toMinutes(now - start),
                                    TimeUnit.MILLISECONDS.toSeconds(now - start) % 60, (now - start) % 1000);
                            System.out.printf("n: %d\n", bestNThisRun);
                            for (Partition partition : partitions) {
                                // print in sorted order since everyone else
                                // seems to to that
                                List<Integer> partitionElementsList = new ArrayList<>(partition.elements);
                                Collections.sort(partitionElementsList);
                                System.out.println(partitionElementsList);
                            }
                            System.out.printf("timestamp: %d\n", now);
                            System.out.println("------------------------------");
                        }
                    }
                }

                if (partitionsForN.size() == 0) {
                    break;
                }
            }
        } while (now < end);
    }

    // class representing a partition
    private static final class Partition {

        // the elements of this partition
        Set<Integer> elements = new HashSet<>();

        // the sums of the elements of this partition
        Set<Integer> sums = new HashSet<>();

        Partition() {
        }

        Partition(Partition toCopy) {
            elements.addAll(toCopy.elements);
            sums.addAll(toCopy.sums);
        }

        Set<Integer> getElements() {
            return elements;
        }
    }

    private static final class Choice {
        int n;
        List<Partition> partitions = new ArrayList<>();
        List<Partition> unchosenPartitions = new ArrayList<>();
    }
}

5

সি, এলোমেলো লোভী, n = 91

কেবল একটি বেসলাইন সমাধান সরবরাহ করার জন্য, এটি পুনরায় পুনরুদ্ধার করে n, বিনগুলি এবং তাদের পরিমাণগুলি নজর রাখে এবং nএকটি এলোমেলো বিনকে যুক্ত করে যেখানে এটি এখনও যোগফল হিসাবে উপস্থিত হয় না। এটি একবারে nসমস্ত kঅঙ্কে উপস্থিত হয়ে শেষ হয় এবং ফলাফল যদি nপূর্ববর্তী কোনও প্রয়াসের চেয়ে ভাল ছিল, তবে এটি STDOUT এ প্রিন্ট করে।

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

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

পার্টিশনটি এখানে n = 91:

1 5 12 18 22 29 32 35 46 48 56 59 62 69 72 76 79 82 86 89
2 3 10 11 16 17 25 30 43 44 51 52 57 64 71 83 84 90 91
6 8 13 15 24 31 33 38 40 42 49 54 61 63 65 77 81 88
9 14 19 21 27 34 37 45 60 67 70 73 75 78 80 85
4 7 20 23 26 28 36 39 41 47 50 53 55 58 66 68 74 87

এবং অবশেষে, এখানে কোড:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#define MAX_K 10
#define MAX_N 1024

int main(int argc, char **argv) {
    if (argc < 2)
    {
        printf("Pass in k as a command-line argument");
        return 1;
    }

    printf("%u\n", (unsigned)time(NULL)); 

    int k = atoi(argv[1]);

    int sizes[MAX_K];
    int bins[MAX_K][MAX_N];
    int sums[MAX_K][2*MAX_N];
    int selection[MAX_K];
    int available_bins;

    int best = 0;

    srand(1447101176);

    while (1)
    {
        int i,j;
        for (i = 0; i < k; ++i)
            sizes[i] = 0;
        for (i = 0; i < k*MAX_N; ++i)
            bins[0][i] = 0;
        for (i = 0; i < k*MAX_N*2; ++i)
            sums[0][i] = 0;
        int n = 1;
        while (1)
        {
            available_bins = 0;
            for (i = 0; i < k; ++i)
                if (!sums[i][n])
                {
                    selection[available_bins] = i;
                    ++available_bins;
                }

            if (!available_bins) break;

            int bin = selection[rand() % available_bins];

            bins[bin][sizes[bin]] = n;
            ++sizes[bin];
            for (i = 0; i < sizes[bin]; ++i)
                sums[bin][bins[bin][i] + n] = 1;

            ++n;
        }

        if (n > best)
        {
            best = n;
            for (i = 0; i < k; ++i)
            {
                for (j = 0; j < sizes[i]; ++j)
                    printf("%d ", bins[i][j]);
                printf("\n");
            }
            printf("%u\n", (unsigned)time(NULL));
        }
    }

    return 0;
}

নিশ্চিত হয়েছে n=91, 138 সেকেন্ডে পাওয়া গেছে। টাই ব্রেকিংয়ের জন্য প্রয়োজনীয় হলে আমি বিভিন্ন সিপিইউ লোডের কারণে বড় ত্রুটিগুলি এড়াতে পুনরায় সময় নেব
পিটার টেলর

3

সি ++, 135

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <set>
#include <vector>
#include <algorithm>


using namespace std;

vector<vector<int> > subset;
vector<int> len, tmp;
set<int> sums;

bool is_sum_free_with(int elem, int subnr) {
    sums.clear();
    sums.insert(elem+elem);
    for(int i=0; i<len[subnr]; ++i) {
        sums.insert(subset[subnr][i]+elem);
        for(int j=i; j<len[subnr]; ++j) sums.insert(subset[subnr][i]+subset[subnr][j]);
    }
    if(sums.find(elem)!=sums.end()) return false;
    for(int i=0; i<len[subnr]; ++i) if(sums.find(subset[subnr][i])!=sums.end()) return false;
    return true;
}

int main()
{
    int k = 0; cin >> k;

    int start=time(0);
    cout << start << endl;

    int allmax=0, cnt=0;
    srand(0);

    do {
        len.clear();
        len.resize(k);
        subset.clear();
        subset.resize(k);
        for(int i=0; i<k; ++i) subset[i].resize((int)pow(3, k));

        int n=0, last=0, c, y, g, h, t, max=0;
        vector<int> p(k);

        do {
            ++n;
            c=-1;
            for(int i=0; i++<k; ) {
                y=(last+i)%k;
                if(is_sum_free_with(n, y)) p[++c]=y;
            }

            if(c<0) --n;

            t=n;

            while(c<0) {
                g=rand()%k;
                h=rand()%len[g];
                t=subset[g][h];
                for(int l=h; l<len[g]-1; ++l) subset[g][l]=subset[g][l+1];
                --len[g];
                for(int i=0; i++<k; ) {
                    y=(g+i)%k;
                    if(is_sum_free_with(t, y) && y!=g) p[++c]=y;
                }
                if(c<0) subset[g][len[g]++]=t;
            }

            c=p[rand()%(c+1)];
            subset[c][len[c]++]=t;

            last=c;

            if(n>max) {
                max=n;
                cnt=0;
                if(n>allmax) {
                    allmax=n;
                    for(int i=0; i<k; ++i) {
                        tmp.clear();
                        for(int j=0; j<len[i]; ++j) tmp.push_back(subset[i][j]);
                        sort(tmp.begin(), tmp.end());
                        for(int j=0; j<len[i]; ++j) cout << tmp[j] << " ";
                        cout << endl;
                    }
                    cout << time(0) << " " << time(0)-start << " " << allmax << endl;
                }

            }

        } while(++cnt<50*n && time(0)-start<600);

        cnt=0;

    } while(time(0)-start<600);

    return 0;
}

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

আমি এটিকে জোর করে প্রোটোটাইপ করেছি এবং এটি আশাব্যঞ্জক বলে মনে হয়েছিল, তাই এটির গতি বাড়ানোর জন্য আমি এটি সি ++ তে অনুবাদ করেছিলাম। একটি ব্যবহার std::setএমনকি এটি আরও গতিপ্রাপ্ত করা উচিত।

এন = 135 এর জন্য আউটপুট (আমার [পুরানো] মেশিনে প্রায় 230 সেকেন্ড পরে)

2 6 9 10 13 17 24 28 31 35 39 42 43 46 50 57 61 68 75 79 90 94 97 101 105 108 119 123 126 127 130 131 134 
38 41 45 48 51 52 55 56 58 59 62 64 65 66 67 69 70 71 72 74 78 80 81 84 85 87 88 91 95 98 
5 12 15 16 19 22 23 25 26 29 33 33 73 83 93 100 103 107 110 111 113 114 117 120 121 124 
1 4 11 14 21 27 34 37 40 47 53 60 76 86 89 96 99 102 109 112 115 122 125 132 135 
3 7 8 18 20 30 32 44 49 49 63 63 82 82 92 104 106 116 118 128 129 133 

আমি বৈধতাটি যাচাই করিনি, তবে এটি ঠিক আছে।


2

পাইথন 3, এলোমেলো লোভী, n = 61

শেষ আউটপুট:

[5, 9, 13, 20, 24, 30, 32, 34, 42, 46, 49, 57, 61]
[8, 12, 14, 23, 25, 44, 45, 47, 54]
[2, 6, 7, 19, 22, 27, 35, 36, 39, 40, 52, 53, 56]
[3, 10, 15, 16, 17, 29, 37, 51, 55, 59, 60]
[1, 4, 11, 18, 21, 26, 28, 31, 33, 38, 41, 43, 48, 50, 58]

এটি কার্যকরভাবে মার্টিন বাটনারদের মতো একই অ্যালগরিদম ব্যবহার করে তবে আমি এটি স্বাধীনভাবে বিকাশ করেছি।

আছে kবিন এ পর্যন্ত এটি উভয় সংখ্যার আছে এবং সংখ্যার এটা যে আর যেতে পারে না। পুনরাবৃত্তির প্রতিটি গভীরতায় (এটি মূলত একটি গভীরতার প্রথম সন্ধান), বিন ক্রমটি বদলে দেওয়া হয় এবং পরবর্তী সংখ্যা ( nextN) ক্রমান্বয়ে) এটি নিতে পারে এমন বিনুতে ফেলে দেওয়া হয় এবং তারপরে আরও এক ধাপ আরও গভীর হয়। যদি কিছু না থাকে তবে এটি এক ধাপ ব্যাক আপ করে ফিরে আসে।

from copy import deepcopy
from random import shuffle, seed
from time import clock, time
global maxN
maxN = 0
clock()
seed(0)

def search(k,nextN=1,sets=None):
    global maxN
    if clock() > 600: return

    if nextN == 1: #first iteration
        sets = []
        for i in range(k):
            sets.append([[],[]])

    R = list(range(k))
    shuffle(R)
    for i in R:
        if clock() > 600: return
        if nextN not in sets[i][1]:
            sets2 = deepcopy(sets)
            sets2[i][0].append(nextN)
            sets2[i][1].extend([nextN+j for j in sets2[i][0]])
            nextN2 = nextN + 1

            if nextN > maxN:
                maxN = nextN
                print("New maximum!",maxN)
                for s in sets2: print(s[0])
                print(time())
                print()

            search(k, nextN2, sets2)

search(5)

2

পাইথন, এন = 31

import sys
k = int(sys.argv[1])

for i in range(k):
    print ([2**i * (2*j + 1) for j in range(2**(k - i - 1))])

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

প্রথম, নোট করুন যে কোনও দুটি বিজোড় সংখ্যার যোগফল সমান, তাই আমরা প্রথম ব্লকে সমস্ত বিজোড় সংখ্যাগুলি ফেলে দিতে পারি। তারপরে, যেহেতু অবশিষ্ট সমস্ত সংখ্যা সমান, তাই আমরা এগুলিকে ২ দিয়ে ভাগ করতে পারি Once আবার, আমরা ফলস্বরূপ সমস্ত বিজোড় সংখ্যা দ্বিতীয় ব্লকে ফেলে দিতে পারি (তাদের 2 দিয়ে আবার গুণ করে), অবশিষ্ট সংখ্যাগুলিকে 2 দিয়ে বিভক্ত করতে পারি (অর্থাত্ , সামগ্রিকভাবে 4 দ্বারা, তৃতীয় ব্লকে বিজোড়গুলি নিক্ষেপ করুন (তাদের 4 দ্বারা পুনরায় গুণিত করার পরে) এবং আরও ... বা, আপনি যে শব্দগুলি বোঝেন, আমরা সেই সমস্ত সংখ্যা রেখেছি যার নূন্যতম-উল্লেখযোগ্য সেট বিট প্রথম ব্লকের মধ্যে প্রথম বিট, সমস্ত নম্বর যার নূন্যতম-উল্লেখযোগ্য সেট বিট দ্বিতীয় ব্লকের মধ্যে দ্বিতীয় বিট, এবং আরও কিছু ...

জন্য ব্লক, আমরা সমস্যাতে পড়েছেন একবার আমরা পৌঁছানোর এন = 2 , এর চেয়ে কম গুরুত্বপূর্ণ সেট বিট থেকে এন হয়
( + 1 টি) -th বিট, যা কোনো ব্লক সঙ্গে সঙ্গতিপূর্ণ নয়। অন্য কথায়, এই স্কিম আপ কাজ করে
যাও এন = 2 , 1. সুতরাং কিছুদিনের জন্য - = 5 আমরা কেবল একটি অনুর্বর পেতে এন = 31 , এই নম্বর দিয়ে ব্যাখ্যা মূলকভাবে বৃদ্ধি । এটি এটিও প্রতিষ্ঠিত করে যে এস ( কে ) ≥ 2 কে - 1 (তবে আমরা আসলে খুব সহজেই এর চেয়ে আরও ভাল নিম্ন সীমাটি পেতে পারি))

রেফারেন্সের জন্য, এখানে কে = 5 এর ফলাফল :

[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]
[2, 6, 10, 14, 18, 22, 26, 30]
[4, 12, 20, 28]
[8, 24]
[16]

অতিরিক্ত একটি বের করার সহজ উপায় রয়েছে: বিজোড় সংখ্যাগুলির শীর্ষের অর্ধেকটি অন্য কোনও বিভাগে নিয়ে যান (যেহেতু তাদের যোগফল ইতিমধ্যে বিভাগের যে কোনও সংখ্যার চেয়ে বড় হতে বাধ্য) এবং নীচের অর্ধেকের মধ্যে 2 ^ কে যোগ করুন বিজোড় সংখ্যা একই ধারণা সম্ভবত অন্য এলজি কে নম্বর পেতে বা এমনকি অন্য কেও পেতে বাড়ানো যেতে পারে।
পিটার টেলর

@ পিটারটেলর হ্যাঁ, পোস্ট করার পরে আমি বুঝতে পেরেছিলাম যে এটি আসলে বেশ তুচ্ছ। এটি করার সমতুল্য [1], [2,3], [4,5,6,7], ..., যা সম্ভবত সহজ, কেবল বিপরীত বিট এবং ব্লক ক্রমের সাথে। এটি কীভাবে বাড়ানো যেতে পারে তা দেখতে সহজ।
এলো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.