नि: शुल्क पॉलीओमीनो के साथ एक एन एक्स एन वर्ग के अलग झुकाव की संख्या


17

नवीनतम "अच्छा" OEIS अनुक्रम, A328020 , कुछ ही मिनट पहले प्रकाशित हुआ था।

नि: शुल्क पॉलीओमीनो के साथ एक एन एक्स एन वर्ग के अलग झुकाव की संख्या।

यह क्रम वर्ग के समरूपता तक झुकाव को गिनता है। अनुक्रम में छह शब्द हैं, लेकिन मैं देखना चाहता हूं कि क्या यहां के लोग इसे आगे बढ़ा सकते हैं।

उदाहरण

के लिए n=422 ऐसे ग्रिड हैं, जैसा कि इस छवि में OEIS से दिखाया गया है। क्रेडिट: जेफ बोमैस्टर, ए 328020 का चित्रण (4)।A328020 (4)

चुनौती

जैसा यह पिछले चुनौती , इस चुनौती के लक्ष्य के इस दृश्य है, जो शुरू होता है में संभव के रूप में कई शब्दों के रूप में गणना करने के लिए है 1, 1, 2, 22, 515, 56734और जहां n-वें अवधि एन एक्स एन एन-polyominoes साथ ग्रिड के टाइलिंग की संख्या है।

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


3
तो यह वर्ग के modulo समरूपता है?
पीटर टेलर

@PeterTaylor, यह सही है। मैं इस सवाल में स्पष्ट नहीं है।
पीटर केजी

Naively मैं कहूंगा कि n'th प्रविष्टि की गणना करने के लिए number_of_fixed_n_polyominoes ^ ( n -1) संचालन होगा। तो n = 7 के लिए, वह 760 ^ 6 57 2 ^ 57.4 ऑपरेशन लेगा। आप शायद इसे बहुत कम कर सकते हैं, लेकिन इसके साथ शुरू करने के लिए एक बड़ी संख्या है ...
जी। स्लिपपेन

@Sliepen, मुझे उम्मीद है कि आप पीछे से बहुत कम करके काट सकते हैं। विशेष रूप से, बहुत सारे निश्चित बहुपद होते हैं जिन्हें कोने में नहीं रखा जा सकता है, और एक बार एक वैध पॉलीमिनो को कहीं रखा जाता है, तो यह बहुत हद तक बाधा डालता है कि इसके आगे क्या रखा जा सकता है।
पीटर केजी

@PeterKagey, आप सही कह रहे हैं। मुझे लगता है कि यह मदद करता है अगर, यह देखते हुए कि आपने पहले से ही n n-polyominoes रखा है, तो आप सबसे खराब स्थिति में एक polyomino रखने की कोशिश करने के लिए अगली स्थिति चुनते हैं, ताकि आप इसे बहुत कम कर सकें।
जी। स्लीपेन ने

जवाबों:


9

@ ग्रिम के कोड का विस्तार N = 8 हो जाता है

यह सिर्फ रेखांकित करता है कि @Grimy इनाम के हकदार हैं:

मैं प्रत्येक समाप्त पॉलीओमीनो के बाद, जाँच करने के लिए कोड का विस्तार करके खोज ट्री को प्रिंय कर सकता था, कि शेष मुक्त स्थान को N द्वारा विभाज्य नहीं आकार के घटकों में विभाजित नहीं किया गया है।

एक मशीन पर जहां मूल कोड ने N = 7 के लिए 2m11s लिया, इसमें 1m4s लगते हैं, और N = 8 की गणना 33h46m में की गई थी। परिणाम 23437350133 है।

यहाँ एक अंतर के रूप में मेरा जोड़ है:

--- tilepoly.c  2019-10-11 12:37:49.676351878 +0200
+++ tilepolyprune.c     2019-10-13 04:28:30.518736188 +0200
@@ -51,6 +51,30 @@
     return 1;
 } 

+static int check_component_sizes(u64 occupied, u64 total){
+    u64 queue[N*N];
+    while (total<N*N){
+        u64 count = 1;
+        u64 start = ctz(~occupied);
+        queue[0] = start;
+        occupied |= 1ul << start;
+        for(u64 current=0; current<count; ++current){
+            u64 free_adjacent = adjacency_matrix[queue[current]] & ~occupied;
+            occupied |= free_adjacent;
+            while (free_adjacent){
+                u64 next = ctz(free_adjacent);
+                free_adjacent &= ~(1ul << next);
+                queue[count++] = next;
+            }
+        }
+        if (count % N){
+            return 0;
+        }
+        total += count;
+    }
+    return 1;
+}
+
 static void recurse(u64 mino, u64 cell, u64 occupied, u64 adjacent, u64 forbidden)
 {
     if (cell >= N) {
@@ -61,6 +85,9 @@
             return;
         }

+        if(!check_component_sizes(occupied,N*mino))
+            return;
+
         u64 next = ctz(~occupied);
         board[next] = mino;
         recurse(mino, 1, occupied | 1ul << next, adjacency_matrix[next], 0);

इसे ऑनलाइन आज़माएं!


यह बहुत अच्छा है।
अनुश

अब हमें बस एक बहुआयामी simd संस्करण :) की आवश्यकता है
Anush

1
ओह, यह वास्तव में अच्छा है! मैं वास्तव में इस अनुकूलन पर विचार करता था, लेकिन यह नहीं सोचा था कि यह उचित समय में N = 8 तक पहुंचने के लिए पर्याप्त होगा, इसलिए मैंने इसे लागू करने की जहमत नहीं उठाई।
ग्रिमि

14

सी, 7 पद

सातवां कार्यकाल 19846102 है । (पहले छह सवाल में कहा गया है 1, 1, 2, 22, 515, 56734)।

#include <stdio.h>
#include <string.h>
#include <stdint.h>

#define N 7
#define ctz __builtin_ctzl

typedef uint64_t u64;

static u64 board[N*N] = { 0 };
static u64 adjacency_matrix[N*N] = { 0 };
static u64 count = 0;

static u64 check_symmetry()
{
    static const u64 symmetries[7][3] = {
        { 0,     +N, +1 },
        { N-1,   -1, +N },
        { N-1,   +N, -1 },
        { N*N-1, -1, -N },
        { N*N-1, -N, -1 },
        { N*N-N, +1, -N },
        { N*N-N, -N, +1 },
    };

    int order[N];

    for (u64 i = 0; i < 7; ++i) {
        u64 start = symmetries[i][0];
        u64 dcol = symmetries[i][1];
        u64 drow = symmetries[i][2];
        memset(order, 0xFF, N*sizeof(int));

        for (u64 row = 0, col = 0; col < N || (col = 0, ++row < N); ++col) {
            u64 base = board[col + N*row];
            u64 symmetry = board[start + dcol*col + drow*row];
            u64 lex = 0;

            while (order[lex] != symmetry && order[lex] != -1)
                ++lex;
            order[lex] = symmetry;

            if (lex < base)
                return 0;

            if (base < lex)
                break;
        }
    }

    return 1;
} 

static void recurse(u64 mino, u64 cell, u64 occupied, u64 adjacent, u64 forbidden)
{
    if (cell >= N) {
        ++mino;

        if (mino == N) {
            count += check_symmetry();
            return;
        }

        u64 next = ctz(~occupied);
        board[next] = mino;
        recurse(mino, 1, occupied | 1ul << next, adjacency_matrix[next], 0);
        return;
    }

    adjacent &= ~occupied & ~forbidden;
    while (adjacent) {
        u64 next = ctz(adjacent);
        adjacent &= ~(1ul << next);
        forbidden |= 1ul << next;
        board[next] = mino;
        recurse(mino, cell + 1, occupied | 1ul << next, adjacent | adjacency_matrix[next], forbidden);
    }
}

int main(void)
{
    for (u64 i = 0; i < N*N; ++i) {
        if (i % N)
            adjacency_matrix[i] |= 1ul << (i - 1);
        if (i / N)
            adjacency_matrix[i] |= 1ul << (i - N);
        if (i % N != N - 1)
            adjacency_matrix[i] |= 1ul << (i + 1);
        if (i / N != N - 1)
            adjacency_matrix[i] |= 1ul << (i + N);
    }

    recurse(0, 2, 3, 4 | 3 << N, 0);
    printf("%ld\n", count);
}

इसे ऑनलाइन आज़माएं! (N = 6 के लिए, चूंकि N = 7 समय समाप्त होगा।)

मेरी मशीन पर, N = 6 ने 0.171s लिया, और N = 7 ने 2m23s लिया। N = 8 में कुछ सप्ताह लगेंगे।


3
यह अद्भुत है! मुझे बताएं कि क्या आप इसे OEIS में जोड़ना चाहते हैं - जिसके परिणामस्वरूप आप अपने आप को डॉकिंग कर सकते हैं - या यदि आप मुझे इसे जोड़ना चाहते हैं।
पीटर कैगी

@PeterKagey कृपया इसे जोड़ने के लिए स्वतंत्र महसूस करें: (:
ग्रिमी

आकर्षक चेक_स्मिथ्री फ़ंक्शन। क्या आप कृपया संक्षिप्त विवरण दे सकते हैं क्योंकि मैं दृष्टिकोण से परिचित नहीं हूँ?
जॉन रीस

1
@JohnRees यह बस परीक्षण करता है कि वर्तमान बोर्ड अपने सभी समरूपों के लिए शाब्दिक रूप से It है। इस प्रकार सममित बोर्डों के किसी भी सेट में, वास्तव में एक की गणना की जाती है: लेक्सिकोग्राफिक न्यूनतम।
ग्रिममी

1
एक-एक करके समाधानों की गणना करने की तुलना में बेहतर करने के लिए, कुछ प्रकार के मीट-इन-बीच की आवश्यकता होती है। समस्या यह है कि चीजों को विभाजित करने का कोई तरीका प्रतीत नहीं होता है, जो महत्वपूर्ण क्लस्टरिंग हो जाता है। जैसे इस उत्तर के रूप में एक ही विहित आदेश का उपयोग करते हुए, 3 हेक्सोमिनोइज़ रखकर मुझे प्रति मास्क हेक्सोमिनोस के औसत 3.7 सेट मिलते हैं। मैं यह निष्कर्ष निकालता हूं कि इस दृष्टिकोण को पीटने की संभावना नहीं है।
पीटर टेलर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.