योग-मुक्त विभाजन खोजना


17

कार्यकारी सारांश

इनपुट को देखते हुए k, पूर्णांकों का एक विभाजन को खोजने 1के लिए nमें kसबसे बड़ा के लिए योग से मुक्त सबसेट n10 मिनट के भीतर आप कर सकते हैं।

बैकग्राउंडर: शूर नंबर

एक सेट Aहै योग से मुक्त करता है, तो उसकी स्व-राशि A + A = { x + y | x, y in A}इसके साथ आम में कोई तत्व है।

प्रत्येक सकारात्मक पूर्णांक के लिए kसबसे बड़ा पूर्णांक होता है S(k)जैसे कि सेट {1, 2, ..., S(k)}को kयोग-मुक्त सबसेट में विभाजित किया जा सकता है । इस नंबर को k th Schur नंबर (OEIS A045652 ) कहा जाता है ।

उदाहरण के लिए, S(2) = 4। हम के {1, 2, 3, 4}रूप में विभाजन कर सकते हैं {1, 4}, {2, 3}, और वह दो योगों वाले सबसे अच्छे उप-योगों में अद्वितीय विभाजन है, लेकिन अब हम 5किसी भी हिस्से में नहीं जोड़ सकते हैं ।

चुनौती

एक निर्धारक कार्यक्रम लिखिए जो निम्नलिखित कार्य करता है:

  • kइनपुट के रूप में एक सकारात्मक पूर्णांक लें
  • स्टडआउट के लिए वर्तमान यूनिक्स टाइमस्टैम्प लिखें
  • के विभाजन का एक अनुक्रम आउटपुट 1के लिए nमें kबढ़ाने के लिए योग से मुक्त सबसेट n, वर्तमान यूनिक्स टाइमस्टैम्प के साथ प्रत्येक अनुक्रम के बाद।

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

महत्वपूर्ण विवरण:

  • मेरे पास Ubuntu Precise है, इसलिए यदि आपकी भाषा समर्थित नहीं है तो मैं इसे स्कोर नहीं कर पाऊंगा।
  • मेरे पास एक Intel Core2 क्वाड सीपीयू है, इसलिए यदि आप मल्टीथ्रेडिंग का उपयोग करना चाहते हैं तो 4 थ्रेड से अधिक का उपयोग करने का कोई मतलब नहीं है।
  • यदि आप चाहते हैं कि मैं किसी विशेष संकलक झंडे या कार्यान्वयन का उपयोग करूं, तो आपके उत्तर में स्पष्ट रूप से दस्तावेज।
  • इनपुट को संभालने के लिए आपको अपना कोड विशेष-मामला नहीं बनाना चाहिए 5
  • आपको अपने द्वारा खोजे गए हर सुधार को आउटपुट करने की आवश्यकता नहीं है। उदाहरण के लिए इनपुट के लिए 2आप केवल विभाजन को ही आउटपुट कर सकते हैंn = 4 । हालाँकि, यदि आप पहले 10 मिनट में कुछ भी आउटपुट नहीं करते हैं, तो मैं इसे स्कोर करूँगा n = 0

जवाबों:


8

पायथन 3, सबसे बड़ी संख्या द्वारा क्रमबद्ध, n = 92 121

एक सुझाव है कि अप्रत्याशित रूप से अधिकतम सुधार के लिए मार्टिन Büttner के लिए धन्यवाद 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 सेकंड से भी कम समय में देखा ।
पीटर टेलर

आह, मुझे लगा कि समय प्रारूप उतना महत्वपूर्ण नहीं था जितना कि यह दिखाने में कि यह कितना समय लगा। मैं इसे समझूंगा और इसे बदलूंगा। संपादित करें: D'oh। मैंने चुना ctime, timeक्योंकि जब timeमैं उठाया जाना चाहिए था तो आउटपुट प्रेटियर था।
एल'एंडिया स्ट्रोमैन

आप जानते हैं, आप बिन में सबसे बड़ी संख्या के आधार पर भी छांट सकते हैं, क्योंकि सबसे बड़ी अस्वीकृत संख्या हमेशा दो बार होगी।
मार्टिन एंडर

@ मार्टिनबटनर: ...... मैं ... उह ... मुझे नहीं पता कि कैसे या क्यों, लेकिन यह हो जाता है n=121। oO
एल'एंडिया स्ट्रोमैन

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

वाह, यह मेरे कोड के समान दिखता है। : पी;) (मैं बिल्कुल भी बुरा नहीं
मानता

@ El'endiaStarman क्रेडिट जोड़ा गया। यह एक अच्छा आधार है।
isaacg 7

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 एक समय में एक विभाजन के जितना कि वह अन्य विभाजन में से बाहर निकाल सकता है।

संपादित करें: के लिए स्थान खाली करने के लिए एल्गोरिथ्म tweaked 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

सी, यादृच्छिक लालची, एन = 91

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

इनपुट kको कमांड-लाइन तर्क के माध्यम से प्रदान किया जाता है। अधिकतम संभव kवर्तमान में 10 तक हार्डकोड किया गया है क्योंकि मैं बहुत आलसी था डायनेमिक मेमोरी आवंटन, लेकिन यह आसानी से तय किया जा सकता है।

मुझे लगता है कि मैं अब एक बेहतर बीज के लिए शिकार करने जा सकता हूं, लेकिन यह उत्तर शायद वैसे भी प्रतिस्पर्धी नहीं है, इसलिए meh।

यहाँ इसके लिए विभाजन है 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 को बेतरतीब ढंग से चुने गए सबसेट पर लागू करता है। यदि यह संभव नहीं है तो यह सबसेट से रैंडम नंबरों को हटा देता है और उन्हें दूसरों को इस उम्मीद में जोड़ देता है कि कहीं न कहीं अपग्रेड करने में सक्षम बनाता है।

मैंने इसे awk में प्रोटोटाइप किया, और क्योंकि यह आशाजनक लग रहा था, मैंने इसे गति देने के लिए इसे C ++ में अनुवादित किया। का उपयोग करना std::setचाहिए और भी अधिक गति।

N = 135 के लिए आउटपुट (मेरी [पुरानी] मशीन पर लगभग 230 सेकंड के बाद)

२ ६ ९ १० १३ १ 28 २४ २ 31 ३१ ३५ ३ ९ ४ ९ ४२ ५० ५ 68 ५ 75 ६ 79 90 79 94 94 101 94 10 10 10 17 17 108 17 17 17 17 108 108 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 पूर्व विश्व 17 ए.टी. 
38 41 45 48 51 52 55 56 58 59 64 64 65 66 67 70 70 72 72 78 80 80 81 84 87 87 88 91 95 98 
५ १२ १५ १६ १ ९ २२ २३ २६ २६ २ ९ ३६ ३६ 22३ ३ ९ 100३ १ ९९ १ १० 111 १० 111 ११० १११ १११ ११४ ११४ १२१ १२१ १२४ १२४ 
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 82 १ 92 २० ३० ३२ ४४ ४४ ५३ 8२ 104२ ९ २ १२४ १०६ ११ 129 १२ 133 १२। १३३ १३३ 

मैंने वैधता की जाँच नहीं की, लेकिन यह ठीक होना चाहिए।


2

अजगर 3, यादृच्छिक लालची, एन = 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))])

ठीक है, इसलिए यह मोटे तौर पर विजेता नहीं है, लेकिन मैंने महसूस किया कि यह वैसे भी यहां था। मैंने स्वतंत्रता को टाइमस्टैम्प को शामिल नहीं करने के लिए लिया है, क्योंकि यह तुरंत समाप्त हो जाता है, और चूंकि यह एक वास्तविक दावेदार नहीं है।

सबसे पहले, ध्यान दें कि किसी भी दो विषम संख्याओं का योग सम है, इसलिए हम पहले खंड में सभी विषम संख्याओं को डंप कर सकते हैं। फिर, चूंकि शेष सभी संख्याएं समान हैं, इसलिए हम उन्हें 2 से विभाजित कर सकते हैं। एक बार फिर, हम सभी परिणामी विषम संख्याओं को दूसरे ब्लॉक में फेंक सकते हैं (2 से उन्हें फिर से गुणा करने के बाद), शेष संख्याओं को 2 से विभाजित करें (अर्थात कुल मिलाकर, 4), तीसरे खंड में विषम लोगों को फेंक दें (4 से उन्हें फिर से गुणा करने के बाद), और इसी तरह ... या, उन शब्दों को कहने के लिए जिन्हें आप समझते हैं, हमने उन सभी नंबरों को रखा है जिनका कम से कम महत्वपूर्ण सेट बिट पहले ब्लॉक में पहला बिट है, सभी संख्याएं जिनके सबसे कम-महत्वपूर्ण सेट बिट दूसरे ब्लॉक में दूसरा बिट है, और इसलिए ...

के लिए कश्मीर ब्लॉक, हम मुसीबत में पड़ बार हम तक पहुंचने n = 2 कश्मीर , कम से कम-महत्वपूर्ण सेट बिट के बाद से n है
( कश्मीर + 1) वें बिट, जो किसी भी ब्लॉक के अनुरूप नहीं है। दूसरे शब्दों में, इस योजना के काम करता है
के लिए एन = 2 कश्मीर , 1. तो थोड़ी देर के लिए - कश्मीर = 5 हम केवल एक अल्प मिलता एन = 31 है, यह संख्या के साथ तेजी से बढ़ता है कश्मीर । यह यह भी स्थापित करता है कि S ( k ) establish 2 k - 1 (लेकिन हम वास्तव में इससे काफी कम आसानी से बेहतर सीमा पा सकते हैं।)

संदर्भ के लिए, यहाँ k = 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 ^ k जोड़ें विषम संख्या। एक ही विचार शायद एक और lg k नंबर पाने के लिए बढ़ाया जा सकता है, या शायद एक और k।
पीटर टेलर

@PeterTaylor हाँ, मैंने पोस्ट करने के बाद महसूस किया कि यह वास्तव में बहुत तुच्छ है। यह करने के बराबर है [1], [2,3], [4,5,6,7], ..., जो शायद सरल है, बस रिवर्स बिट और ब्लॉक ऑर्डर के साथ। यह देखना आसान है कि इसे कैसे बढ़ाया जा सकता है।
एल एन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.