टिक-टीएसी-पैर की अंगुली जितनी जल्दी हो सके पार कर जाती है


10

के अनुसार ल्यूक के अनुरोध और पीटर टेलर के अलावा इस चुनौती के।

परिचय

खेल टिक-टैक-टो को सभी जानते हैं, लेकिन इस चुनौती में, हम थोड़ा ट्विस्ट लाने जा रहे हैं। हम केवल क्रॉस का उपयोग करने जा रहे हैं । पहला व्यक्ति जो एक पंक्ति में तीन पार करता है वह हार जाता है। एक दिलचस्प तथ्य यह है कि किसी को हारने से पहले क्रॉस की अधिकतम राशि 6 के बराबर होती है :

X X -
X - X
- X X

इसका मतलब है कि 3 x 3 बोर्ड के लिए, अधिकतम राशि 6 है । तो N = 3 के लिए, हमें 6 आउटपुट की आवश्यकता है।

एन = 4, या 4 x 4 बोर्ड के लिए एक और उदाहरण:

X X - X
X X - X
- - - -
X X - X

यह एक इष्टतम समाधान है, आप देख सकते हैं कि क्रॉस की अधिकतम राशि 9 के बराबर है । 12 x 12 बोर्ड के लिए एक इष्टतम समाधान है:

X - X - X - X X - X X -
X X - X X - - - X X - X
- X - X - X X - - - X X
X - - - X X - X X - X -
- X X - - - X - - - - X
X X - X X - X - X X - -
- - X X - X - X X - X X
X - - - - X - - - X X -
- X - X X - X X - - - X
X X - - - X X - X - X -
X - X X - - - X X - X X
- X X - X X - X - X - X

इसका परिणाम 74 है

काम

आपका कार्य जितनी जल्दी हो सके परिणामों की गणना करना है। मैं परीक्षण मामले पर आपका कोड चलाऊंगा 13। यह 5 बार किया जाएगा और फिर रन टाइम का औसत लिया जाएगा। वह आपका अंतिम स्कोर है। कम, बेहतर।

परीक्षण के मामलों

N     Output
1       1
2       4
3       6
4       9
5       16
6       20
7       26
8       36
9       42
10      52
11      64
12      74
13      86
14      100
15      114

अधिक जानकारी https://oeis.org/A181018 पर देखी जा सकती है ।

नियम

  • यह , इसलिए सबसे तेज़ सबमिशन जीत जाता है!
  • आपको एक पूर्ण कार्यक्रम प्रदान करना होगा ।
  • कृपया यह भी प्रदान करें कि मुझे कार्यक्रम कैसे चलाना है। मैं सभी प्रोग्रामिंग भाषाओं से परिचित नहीं हूं और वे कैसे काम करते हैं, इसलिए मुझे यहां थोड़ी मदद की जरूरत है।
  • बेशक, आपके कोड को प्रत्येक परीक्षण मामले के लिए सही परिणाम की गणना करने की आवश्यकता है ।

प्रविष्टियां:

  • feersum (C ++ 11): 28s
  • पीटर टेलर (जावा): 14 मीटर 31 एस


क्या यह सिर्फ दूसरे प्रश्न का एक धोखा नहीं है , जहाँ तक मैं बता सकता हूँ, आपने सिर्फ जीतने की स्थिति बदल दी है?
ब्लू

1
@ मड्डीफिश पूरी तरह से चुनौती एक ही है, मैं आपको यह सुनिश्चित कर सकता हूं कि इस चुनौती के लिए दृष्टिकोण मेरी अन्य चुनौती से बहुत अलग है।
अदनान

3
@ मुड्डीफिश प्रासंगिक चर्चा। "बस जीतने की स्थिति को बदलना" एक चुनौती के लिए एक महत्वपूर्ण बदलाव हो सकता है। हालांकि यह हर संभव चुनौती के लिए एक कोड-गोल्फ , सबसे तेज़-एल्गोरिथ्म और सबसे तेज़-कोड पोस्ट करने के लिए समझ में नहीं आता है , कुछ मामले हैं, जहां दो कोणों से एक समस्या की खोज करने से साइट पर बहुत अधिक मूल्य जुड़ सकता है। मुझे लगता है कि यह एक ऐसा मामला है।
मार्टिन एंडर

1
अद्भुत चुनौती! (+1)

जवाबों:


5

सी ++ 11, 28 एस

यह पंक्तियों के आधार पर एक गतिशील प्रोग्रामिंग दृष्टिकोण का भी उपयोग करता है। मेरे लिए तर्क 13 के साथ चलने में 28 सेकंड का समय लगा। मेरा पसंदीदा ट्रिक वह nextफंक्शन है जो लेक्सिकोग्राफिक रूप से अगली पंक्ति की व्यवस्था को खोजने के लिए थोडा सा कोसने का उपयोग करता है जो एक मास्क को संतुष्ट करता है और कोई 3-इन-इन-पंक्ति नियम नहीं है।

अनुदेश

  1. SEH और पॉज़िक्स थ्रेड्स के साथ नवीनतम MinGW-w64 स्थापित करें
  2. के साथ कार्यक्रम संकलित करें g++ -std=c++11 -march=native -O3 <filename>.cpp -o <executable name>
  3. साथ दौड़ो <executable name> <n>
#include <vector>
#include <stddef.h>
#include <iostream>
#include <string>

#ifdef _MSC_VER
#include <intrin.h>
#define popcount32 _mm_popcnt_u32
#else
#define popcount32 __builtin_popcount
#endif


using std::vector;

using row = uint32_t;
using xcount = uint8_t;

uint16_t rev16(uint16_t x) { // slow
    static const uint8_t revbyte[] {0,128,64,192,32,160,96,224,16,144,80,208,48,176,112,240,8,136,72,200,40,168,104,232,24,152,88,216,56,184,120,248,4,132,68,196,36,164,100,228,20,148,84,212,52,180,116,244,12,140,76,204,44,172,108,236,28,156,92,220,60,188,124,252,2,130,66,194,34,162,98,226,18,146,82,210,50,178,114,242,10,138,74,202,42,170,106,234,26,154,90,218,58,186,122,250,6,134,70,198,38,166,102,230,22,150,86,214,54,182,118,246,14,142,78,206,46,174,110,238,30,158,94,222,62,190,126,254,1,129,65,193,33,161,97,225,17,145,81,209,49,177,113,241,9,137,73,201,41,169,105,233,25,153,89,217,57,185,121,249,5,133,69,197,37,165,101,229,21,149,85,213,53,181,117,245,13,141,77,205,45,173,109,237,29,157,93,221,61,189,125,253,3,131,67,195,35,163,99,227,19,147,83,211,51,179,115,243,11,139,75,203,43,171,107,235,27,155,91,219,59,187,123,251,7,135,71,199,39,167,103,231,23,151,87,215,55,183,119,247,15,143,79,207,47,175,111,239,31,159,95,223,63,191,127,255};
    return uint16_t(revbyte[x >> 8]) | uint16_t(revbyte[x & 0xFF]) << 8;
}

// returns the next number after r that does not overlap the mask or have three 1's in a row
row next(row r, uint32_t m) {
    m |= r >> 1 & r >> 2;
    uint32_t x = (r | m) + 1;
    uint32_t carry = x & -x;
    return (r | carry) & -carry;
}

template<typename T, typename U> void maxequals(T& m, U v) {
    if (v > m)
        m = v;
}

struct tictac {
    const int n;
    vector<row> rows;
    size_t nonpal, nrows_c;
    vector<int> irow;
    vector<row> revrows;

    tictac(int n) : n(n) { }

    row reverse(row r) {
        return rev16(r) >> (16 - n);
    }

    vector<int> sols_1row() {
        vector<int> v(1 << n);
        for (uint32_t m = 0; !(m >> n); m++) {
            auto m2 = m;
            int n0 = 0;
            int score = 0;
            for (int i = n; i--; m2 >>= 1) {
                if (m2 & 1) {
                    n0 = 0;
                } else {
                    if (++n0 % 3)
                        score++;
                }
            }
            v[m] = score;
        }
        return v;
    }

    void gen_rows() {
        vector<row> pals;
        for (row r = 0; !(r >> n); r = next(r, 0)) {
            row rrev = reverse(r);
            if (r < rrev) {
                rows.push_back(r);
            } else if (r == rrev) {
                pals.push_back(r);
            }
        }
        nonpal = rows.size();
        for (row r : pals) {
            rows.push_back(r);
        }
        nrows_c = rows.size();
        for (int i = 0; i < nonpal; i++) {
            rows.push_back(reverse(rows[i]));
        }
        irow.resize(1 << n);
        for (int i = 0; i < rows.size(); i++) {
            irow[rows[i]] = i;
        }
        revrows.resize(1 << n);
        for (row r = 0; !(r >> n); r++) {
            revrows[r] = reverse(r);
        }
    }

    // find banned locations for 1's given 2 above rows
    uint32_t mask(row a, row b) {
        return ((a & b) | (a >> 1 & b) >> 1 | (a << 1 & b) << 1) /*& ((1 << n) - 1)*/;
    }

    int calc() {
        if (n < 3) {
            return n * n;
        }
        gen_rows();
        int tdim = n < 5 ? n : (n + 3) / 2;
        size_t nrows = rows.size();
        xcount* t = new xcount[2 * nrows * nrows_c]{};
#define tb(nr, i, j) t[nrows * (nrows_c * ((nr) & 1) + (i)) + (j)]

        // find optimal solutions given 2 rows for n x k grids where 3 <= k <= ceil(n/2) + 1

        {
            auto s1 = sols_1row();
            for (int i = 0; i < nrows_c; i++) {
                row a = rows[i];
                for (int j = 0; j < nrows; j++) {
                    row b = rows[j];
                    uint32_t m = mask(b, a) & ~(1 << n);
                    tb(3, i, j) = s1[m] + popcount32(a << 16 | b);
                }
            }
        }
        for (int r = 4; r <= tdim; r++) {
            for (int i = 0; i < nrows_c; i++) {
                row a = rows[i];
                for (int j = 0; j < nrows; j++) {
                    row b = rows[j];
                    bool rev = j >= nrows_c;
                    auto cj = rev ? j - nrows_c : j;
                    uint32_t m = mask(a, b);
                    for (row c = 0; !(c >> n); c = next(c, m)) {
                        row cc = rev ? revrows[c] : c;
                        int count = tb(r - 1, i, j) + popcount32(c);
                        maxequals(tb(r, cj, irow[cc]), count);
                    }
                }
            }
        }
        int ans = 0;
        if (tdim == n) { // small sizes
            for (int i = 0; i < nrows_c; i++) {
                for (int j = 0; j < nrows; j++) {
                    maxequals(ans, tb(n, i, j));
                }
            }
        } else {
            int tdim2 = n + 2 - tdim;
            // get final answer by joining two halves' solutions down the middle
            for (int i = 0; i < nrows_c; i++) {
                int apc = popcount32(rows[i]);
                for (int j = 0; j < nrows; j++) {
                    row b = rows[j];
                    int top = tb(tdim2, i, j);
                    int bottom = j < nrows_c ? tb(tdim, j, i) : tb(tdim, j - nrows_c, i < nonpal ? i + nrows_c : i);
                    maxequals(ans, top + bottom - apc - popcount32(b));
                }
            }
        }
        delete[] t;
        return ans;
    }
};


int main(int argc, char** argv) {
    int n;
    if (argc < 2 || (n = std::stoi(argv[1])) < 0 || n > 16) {
        return 1;
    }
    std::cout << tictac{ n }.calc() << '\n';
    return 0;
}

7

जावा, 14 मी 31 से

यह अनिवार्य रूप से कार्यक्रम है जिसे मैंने अनुक्रम का विस्तार करने के लिए उपयोग करने के बाद OEIS को पोस्ट किया है, इसलिए यह अन्य लोगों को हरा देने के लिए एक अच्छा संदर्भ है। मैंने इसे पहले कमांड-लाइन तर्क के रूप में बोर्ड आकार लेने के लिए ट्विक किया है।

public class A181018 {
    public static void main(String[] args) {
        int n = Integer.parseInt(args[0]);
        System.out.println(calc(n));
    }

    private static int calc(int n) {
        if (n < 0) throw new IllegalArgumentException("n");
        if (n < 3) return n * n;

        // Dynamic programming approach: given two rows, we can enumerate the possible third row.
        // sc[i + rows.length * j] is the greatest score achievable with a board ending in rows[i], rows[j].
        int[] rows = buildRows(n);
        byte[] sc = new byte[rows.length * rows.length];
        for (int j = 0, k = 0; j < rows.length; j++) {
            int qsc = Integer.bitCount(rows[j]);
            for (int i = 0; i < rows.length; i++) sc[k++] = (byte)(qsc + Integer.bitCount(rows[i]));
        }

        int max = 0;
        for (int h = 2; h < n; h++) {
            byte[] nsc = new byte[rows.length * rows.length];
            for (int i = 0; i < rows.length; i++) {
                int p = rows[i];
                for (int j = 0; j < rows.length; j++) {
                    int q = rows[j];
                    // The rows which follow p,q cannot intersect with a certain mask.
                    int mask = (p & q) | ((p << 2) & (q << 1)) | ((p >> 2) & (q >> 1));
                    for (int k = 0; k < rows.length; k++) {
                        int r = rows[k];
                        if ((r & mask) != 0) continue;

                        int pqrsc = (sc[i + rows.length * j] & 0xff) + Integer.bitCount(r);
                        int off = j + rows.length * k;
                        if (pqrsc > nsc[off]) nsc[off] = (byte)pqrsc;
                        if (pqrsc > max) max = pqrsc;
                    }
                }
            }

            sc = nsc;
        }

        return max;
    }

    private static int[] buildRows(int n) {
        // Array length is a tribonacci number.
        int c = 1;
        for (int a = 0, b = 1, i = 0; i < n; i++) c = a + (a = b) + (b = c);

        int[] rows = new int[c];
        int i = 0, j = 1, val;
        while ((val = rows[i]) < (1 << (n - 1))) {
            if (val > 0) rows[j++] = val * 2;
            if ((val & 3) != 3) rows[j++] = val * 2 + 1;
            i++;
        }

        return rows;
    }
}

बचाओ A181018.java; संकलन के रूप में javac A181018.java; के रूप में चलाते हैं java A181018 13। मेरे कंप्यूटर पर इस इनपुट को निष्पादित करने में लगभग 20 मिनट लगते हैं। यह शायद इसे समानांतर करने लायक होगा।


आप इसे कब तक चला रहे हैं? आप अभी भी OEIS में शब्द जोड़ रहे हैं, मैं देख रहा हूँ।
mbomb007

1
@ mbomb007, मैं अभी भी इसे नहीं चला रहा हूं। जैसा कि आप OEIS तिथियों से बता सकते हैं, इसे चलाने में कई दिन लगे n=16; मैंने कहा कि इसके लिए लगभग एक महीने का समय लगेगा n=17, इसलिए मैंने इसके लिए इसे चलाने की कोशिश नहीं की। स्मृति उपयोग भी एक प्रमुख उपद्रव बन रहा था। (PS मैं इस समय गैर-पीपीसीजी प्रोग्रामिंग चुनौती के लिए अपने 4 में से 2 का उपयोग कर रहा हूं: azspcs.com/Contest/Tetrahedra/Standings )
पीटर टेलर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.