কেবলমাত্র যত তাড়াতাড়ি পারাপারের সাথে টিক-টাক-টো


10

অনুযায়ী লুক অনুরোধ এবং পিটার টেইলরের উপরন্তু এই প্রতিদ্বন্দ্বিতা করতে।

ভূমিকা

গেমটি টিক-ট্যাক-টু প্রত্যেকেই জানেন, তবে এই চ্যালেঞ্জের মধ্যে আমরা একটি সামান্য বাঁকটি চালু করতে যাচ্ছি। আমরা কেবল ক্রস ব্যবহার করতে যাচ্ছি । প্রথম ব্যক্তি যিনি একটি সারিতে তিনটি ক্রস রেখেছেন তিনি হেরে যান। একটি আকর্ষণীয় সত্য যে কেউ হারানোর আগে ক্রসের সর্বোচ্চ পরিমাণ 6 এর সমান :

X X -
X - X
- X X

তার মানে 3 x 3 বোর্ডের জন্য সর্বাধিক পরিমাণ 6 । সুতরাং এন = 3 এর জন্য আমাদের 6 আউটপুট করা দরকার।

অন্য উদাহরণ, এন = 4, বা একটি 4 এক্স 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 এ পাওয়া যাবে ।

বিধি

  • এটি , তাই দ্রুততম জমাটি জয়!
  • আপনাকে অবশ্যই একটি সম্পূর্ণ প্রোগ্রাম সরবরাহ করতে হবে
  • আমাকে কীভাবে প্রোগ্রামটি চালাতে হবে তা দয়া করে সরবরাহ করুন। আমি সমস্ত প্রোগ্রামিং ভাষা এবং সেগুলি কীভাবে কাজ করে তার সাথে পরিচিত নই, তাই এখানে আমার একটু সাহায্য প্রয়োজন।
  • অবশ্যই, আপনার কোড প্রতিটি পরীক্ষার ক্ষেত্রে সঠিক ফলাফল গণনা করা প্রয়োজন।

জমাগুলি:

  • ফেয়ারসাম (সি ++ 11): 28 এস
  • পিটার টেলর (জাভা): 14 মি 31


যতদূর আমি বলতে পারি এটি দ্বিতীয় প্রশ্নের কেবল একটি ধাপ নয় , আপনি কেবল জয়ের শর্তটি বদলেছেন?
নীল

1
@ মুডিফিশ যদিও চ্যালেঞ্জটি নিজেই একই রকম, আমি আপনাকে নিশ্চিত করতে পারি যে এই চ্যালেঞ্জের জন্য আসা পদ্ধতিটি আমার অন্যান্য চ্যালেঞ্জের থেকে খুব আলাদা।
আদনান

3
@ মুদ্দিফিশ প্রাসঙ্গিক মেটা আলোচনা। "কেবল জয়ের শর্ত পরিবর্তন করা" একটি চ্যালেঞ্জের জন্য যথেষ্ট পরিবর্তন হতে পারে। যদিও প্রতিটি সম্ভাব্য চ্যালেঞ্জের জন্য একটি কোড-গল্ফ , দ্রুততম-অ্যালগরিদম এবং দ্রুততম কোড পোস্ট করা কোনও অর্থবোধ করে না, তবে কিছু ক্ষেত্রে রয়েছে, যেখানে দুটি কোণ থেকে কোনও সমস্যা অন্বেষণ করা সাইটে প্রচুর মান যুক্ত করতে পারে। আমি মনে করি এটি এমন একটি ঘটনা।
মার্টিন ইন্ডার

1
অপূর্ব চ্যালেঞ্জ! (+1)

উত্তর:


5

সি ++ 11, 28 সে

এটি সারিগুলির উপর ভিত্তি করে একটি গতিশীল প্রোগ্রামিং পদ্ধতিরও ব্যবহার করে। আমার পক্ষে 13 টি যুক্তি দিয়ে চালাতে 28 সেকেন্ড সময় লেগেছে। আমার প্রিয় কৌশলটি হ'ল nextফাংশন যা কোনও মুখোশ এবং কোনও -3-ইন-এ-সারি নিয়মকে সন্তুষ্ট করে লেক্সোগ্রাফিকভাবে পরবর্তী সারি বিন্যাসটি সন্ধান করার জন্য কিছুটা বিট বেশিং ব্যবহার করে।

নির্দেশনা

  1. এসইএইচ এবং পিক্সিক থ্রেড সহ সর্বশেষতম 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 এস

এটি মূলত এই প্রোগ্রামটি যা আমি ক্রমটি প্রসারিত করার জন্য এটির পরে ওইআইএস-এ পোস্ট করেছি, সুতরাং এটি অন্য লোকদের কাছে বীট করার পক্ষে একটি ভাল রেফারেন্স। আমি প্রথম কমান্ড-লাইন আর্গুমেন্ট হিসাবে বোর্ডের আকার নিতে এটি টুইট করেছি।

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 মিনিট সময় লাগে। এটি সম্ভবত এটি সমান্তরাল মূল্য হবে।


কত দিন ধরে আপনি এটি চালিয়ে যাচ্ছেন? আপনি এখনও ওইআইএস-এ শর্ত যুক্ত করছেন, আমি দেখছি।
mbomb007

1
@ এমবিম্ব ২০০7, আমি এখনও এটি চালাচ্ছি না। আপনি যেমন ওইআইএসের তারিখগুলি থেকে বলতে পারেন, এটি চালাতে বেশ কয়েক দিন সময় লেগেছিল n=16; আমি এক্সট্রাপোলেটেড করেছিলাম যে এটি প্রায় এক মাস সময় নিতে n=17পারে, তাই আমি এটির জন্য এটি চালানোর চেষ্টা করিনি। স্মৃতি ব্যবহারও একটি বড় উপদ্রব হয়ে উঠছিল। (পিএস আমি বর্তমানে আমার 4 টির 2 টির জন্য একটি নন-পিপিসি প্রোগ্রামিং চ্যালেঞ্জের জন্য ব্যবহার করছি: আজস্পিসি.কম / কনটেস্ট / টেট্রহেড্রা / স্ট্যান্ডিংস )
পিটার টেলর
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.