การขยาย OEIS: การนับการเอียงเพชร


46

ฉันสัญญาว่านี่จะเป็นความท้าทายครั้งสุดท้ายของฉันเกี่ยวกับการเอียงกระเบื้อง (ในขณะนั้น) ในด้านที่สดใสความท้าทายนี้ไม่มีอะไรเกี่ยวข้องกับศิลปะ ASCII และไม่ใช่รหัสกอล์ฟดังนั้นนี่จึงแตกต่างอย่างสิ้นเชิง

ดังนั้นเพื่อเป็นการเตือนความจำหกเหลี่ยมทุกอันสามารถตั้งชื่อด้วยเพชรที่แตกต่างกันสามแบบ:

คำถามที่น่าสนใจที่จะถามคือมีจำนวนเท่าใดสำหรับขนาดหกเหลี่ยมที่กำหนด ดูเหมือนว่าตัวเลขเหล่านี้ได้รับการศึกษาอย่างเป็นธรรมอย่างทั่วถึงและสามารถพบได้ใน OEIS A008793

อย่างไรก็ตามปัญหาที่ได้รับ trickier ถ้าเราถามว่าหลาย tilings อยู่ถึงการหมุนและการสะท้อน ตัวอย่างเช่นสำหรับความยาวด้าน N = 2 มีการเอียง 20 ต่อไปนี้:

   ____     ____     ____     ____     ____     ____     ____     ____     ____     ____  
  /\_\_\   /\_\_\   /\_\_\   /\_\_\   /_/\_\   /_/\_\   /\_\_\   /_/\_\   /_/\_\   /_/\_\ 
 /\/\_\_\ /\/_/\_\ /\/_/_/\ /\/_/\_\ /\_\/\_\ /\_\/_/\ /\/_/_/\ /\_\/\_\ /\_\/_/\ /_/\/\_\
 \/\/_/_/ \/\_\/_/ \/\_\_\/ \/_/\/_/ \/\_\/_/ \/\_\_\/ \/_/\_\/ \/_/\/_/ \/_/\_\/ \_\/\/_/
  \/_/_/   \/_/_/   \/_/_/   \_\/_/   \/_/_/   \/_/_/   \_\/_/   \_\/_/   \_\/_/   \_\/_/ 
   ____     ____     ____     ____     ____     ____     ____     ____     ____     ____  
  /_/_/\   /\_\_\   /_/\_\   /_/_/\   /_/\_\   /_/\_\   /_/_/\   /_/_/\   /_/_/\   /_/_/\ 
 /\_\_\/\ /\/_/_/\ /_/\/_/\ /\_\_\/\ /\_\/_/\ /_/\/_/\ /_/\_\/\ /\_\_\/\ /_/\_\/\ /_/_/\/\
 \/\_\_\/ \/_/_/\/ \_\/\_\/ \/_/\_\/ \/_/_/\/ \_\/_/\/ \_\/\_\/ \/_/_/\/ \_\/_/\/ \_\_\/\/
  \/_/_/   \_\_\/   \_\/_/   \_\/_/   \_\_\/   \_\_\/   \_\/_/   \_\_\/   \_\_\/   \_\_\/ 

แต่สิ่งเหล่านี้จำนวนมากเหมือนกันภายใต้การหมุนและการสะท้อน หากเราคำนึงถึงความสมมาตรเหล่านี้จะมีเพียง6 การเอียงที่แตกต่างกัน:

   ____     ____     ____     ____     ____     ____  
  /\_\_\   /\_\_\   /\_\_\   /_/\_\   /_/\_\   /_/\_\ 
 /\/\_\_\ /\/_/\_\ /\/_/_/\ /\_\/_/\ /\_\/_/\ /_/\/\_\
 \/\/_/_/ \/\_\/_/ \/\_\_\/ \/\_\_\/ \/_/\_\/ \_\/\/_/
  \/_/_/   \/_/_/   \/_/_/   \/_/_/   \_\/_/   \_\/_/ 

   2        2        6        6        1        3

โดยที่ตัวเลขบ่งบอกถึงความหลายหลากของการเรียงต่อกัน โปรดทราบว่าสำหรับรูปหกเหลี่ยมที่มีขนาดใหญ่กว่านั้นยังมีความลาดเอียงที่มีหลายหลาก 4 และ 12

ปรากฏว่ามีการศึกษาจำนวนการเอียงขึ้นไปถึงความสมมาตรอย่างละเอียดน้อยลง รายการ OEIS A066931แสดงคำศัพท์ห้าคำเท่านั้น:

1, 1, 6, 113, 20174

ซึ่งในระยะแรกคือความยาวด้านและระยะเวลาที่ผ่านมาสำหรับความยาวด้านข้างN = 0N = 4

ฉันแน่ใจว่าเราทำได้ดีกว่านั้น!

งานของคุณคือการคำนวณจำนวนของการเอียงสำหรับความยาวด้านที่กำหนด

นี่คือเร็วที่สุดรหัสคะแนนของคุณจะยาวที่สุดNซึ่งรหัสของคุณให้ผลลัพธ์ถูกต้องภายใน30 นาทีบนเครื่องของฉัน ในกรณีที่มีการผูกผมจะยอมรับการส่งซึ่งเป็นผู้ผลิตผลการที่ Nเร็วที่สุด

ตามปกติคุณจะต้องไม่ฮาร์ดโค้ดผลลัพธ์ที่คุณรู้อยู่แล้วว่าจะชนะไทเบรกเกอร์ อัลกอริทึมที่แก้ปัญหาควรจะเหมือนกับหนึ่งที่แก้N = 3N = 5

การส่งของคุณต้องไม่ใช้หน่วยความจำมากกว่า 4GB ฉันจะให้เวลามากขึ้นในเรื่องนี้หากคุณทำงานใกล้เคียงกับขีด จำกัด นั้น แต่ถ้าคุณอยู่เหนือขีด จำกัด นั้นอย่างต่อเนื่องหรือถ้าคุณขัดขวางอย่างมีนัยสำคัญเกินกว่านั้นฉันจะไม่นับการNพิจารณาของคุณ

ฉันจะทดสอบการส่งทั้งหมดในเครื่อง Windows 8 ของฉันดังนั้นตรวจสอบให้แน่ใจว่าภาษาที่คุณเลือกพร้อมใช้งานบน Windows ได้อย่างอิสระ ข้อยกเว้นเพียงอย่างเดียวคือ Mathematica (เพราะฉันมีใบอนุญาต) โปรดรวมคำแนะนำสำหรับวิธีการรวบรวม / เรียกใช้รหัสของคุณ

แน่นอนคุณสามารถคำนวณเงื่อนไขเพิ่มเติมในเวลาของคุณเอง (สำหรับวิทยาศาสตร์และสำหรับคนอื่น ๆ เพื่อตรวจสอบหมายเลขของพวกเขากับ) แต่คะแนนคำตอบของคุณจะถูกกำหนดใน 30 นาที


4
โปรดทราบว่าเนื่องจากN = 6ให้ผลลัพธ์มากกว่า 10 ^ 12 โซลูชันที่ไม่สร้างสรรค์จึงจำเป็นต้องได้รับผลกระทบ
Peter Taylor

1
@ PeterTaylor ฉันหวังว่าจะช่วยให้มีพื้นที่มากขึ้นสำหรับการปรับปรุง บางทีคำตอบเชิงสร้างสรรค์สองสามข้อแรกที่สามารถทำ N = 5 เพื่อให้เข้าใจปัญหาได้มากขึ้นและจากนั้นอาจใช้วิธีผสมผสานแบบไฮบริดที่ไม่จำเป็นต้องสร้างการเอียงทั้งหมดแต่สามารถประมาณจำนวนทั้งหมดจากการสร้างเพียงไม่กี่ ... แล้วบางทีการวิเคราะห์บางอย่างถ้าเราโชคดีจริงๆ :)
Martin Ender

2
ความเสี่ยงของการระบุชัดเจนดูเหมือนว่าฉันแต่ละเรียงเช่นนี้สอดคล้องกับการฉายภาพของลูกบาศก์หน่วยเมื่อมองจากมุมมองที่ห่างไกลเช่นจาก (100, -100,100) ฉันพบว่าสิ่งนี้ช่วยแบ่งเบาภาระในการสร้างหลังคา
DavidC

1
@DavidCarraher แน่นอน โดยเฉพาะอย่างยิ่งการจัดดังกล่าวของก้อนหน่วยเป็น 3D แผนภาพหนุ่ม (อาจช่วยคนได้)
Martin Ender

@DavidCarraher ถ้าคุณดูรูปหกเหลี่ยมที่ใหญ่พอคุณจะเห็นว่ามี 2 วิธีในการตีความว่าเป็นแผนภาพเล็ก วิธีที่ชัดเจน (สำหรับฉันอย่างน้อย) คือการดูพื้นที่ราบที่ด้านบนและซ้ายโดยมี 2x2x1 ทรงลูกบาศก์หายไปจากมุมซ้ายบน แต่มีวิธีอื่นในการดู: โซนว่างในพื้นที่นั้นโดยมี 2x2x1 ทรงลูกบาศก์นั่งอยู่ในนั้น การเอียง 60 องศาอาจช่วยได้ มันทำให้ตาของฉันเจ็บ แต่ฉันคิดว่าแผนภาพสองอันประกอบกันอาจสะท้อนโดยหนึ่งในนั้น OEIS A008793 ระมัดระวังอย่างมากกับถ้อยคำของมัน: "จำนวนพาร์ติชันเครื่องบินที่มีไดอะแกรมเด็ก ... "
เลเวลริเวอร์เซนต์

คำตอบ:


80

พีชคณิตทฤษฎีกราฟการผกผันของโมเบียสการวิจัยและ Java

กลุ่มสมมาตรของรูปหกเหลี่ยมคือกลุ่มไดฮีดรัลอันดับ 12 และสร้างขึ้นโดยการหมุน 60 องศาและกระจกเงาพลิกข้ามเส้นผ่านศูนย์กลาง มันมีกลุ่มย่อย 16 กลุ่ม แต่บางกลุ่มอยู่ในกลุ่มที่ไม่ใช่รูปสัณฐานเล็กน้อย (กลุ่มที่มีเพียงเงาสะท้อนมี 3 ตัวเลือกของแกน) ดังนั้นจึงมี 10 symmetries ที่แตกต่างกันโดยพื้นฐานซึ่งสามารถปูกระเบื้องรูปหกเหลี่ยมได้:

รูปภาพของ 10 สมมาตร

จำนวน tilings เพชรย่อยของตาข่ายสามเหลี่ยมที่สามารถคำนวณเป็นปัจจัยดังนั้นวิธีการเริ่มต้นของฉันคือการตั้งค่าหนึ่งปัจจัยสำหรับแต่ละสมมาตรของรูปหกเหลี่ยมในการคำนวณจำนวน tilings ที่มีอย่างน้อย symmetries เหล่านั้น ; และจากนั้นใช้Möbiusผกผันในพีชคณิตอุบัติการณ์ของ poset ของพวกเขา (โดยทั่วไปลักษณะทั่วไปของหลักการรวม-ยกเว้น) ที่จะทำงานออกจำนวน tilings ที่มีสัดส่วนกลุ่มคือว่าแต่ละ 10 กรณี อย่างไรก็ตามสมมาตรบางส่วนมีสภาพขอบที่น่ารังเกียจดังนั้นฉันจึงถูกบังคับให้รวมกันมากกว่าปัจจัยหลายประการ โชคดีที่ค่าที่ได้รับn < 10ให้ข้อมูลมากพอที่ฉันจะสามารถระบุลำดับที่เกี่ยวข้องใน OEIS และรวมกันเป็นรูปแบบปิด (สำหรับค่าบางส่วนของ "ปิด" ซึ่งอนุญาตให้ผลิตภัณฑ์มี จำกัด ) มีการพูดคุยกันถึงลำดับและการอ้างอิงถึงบทพิสูจน์ในการเขียนอย่างเป็นทางการซึ่งฉันเตรียมที่จะแสดงให้เห็นถึงการปรับปรุงลำดับของ OEIS

เมื่อการนับซ้ำได้รับการดูแลปรากฎว่าค่าสี่ในสิบนั้นถูกยกเลิกอย่างเรียบร้อยดังนั้นเราจะต้องคำนวณค่าที่เหลืออีกหกค่าจากนั้นทำการหาผลรวมถ่วงน้ำหนัก

รหัสนี้ใช้เวลาไม่ถึง 30 วินาทีสำหรับN=1000เครื่องของฉัน

import java.math.BigInteger;

public class OptimisedCounter {
    private static int[] minp = new int[2];

    public static void main(String[] args) {
        if (args.length > 0) {
            for (String arg : args) System.out.println(count(Integer.parseInt(arg)));
        }
        else {
            for (int n = 0; n < 16; n++) {
                System.out.format("%d\t%s\n", n, count(n));
            }
        }
    }

    private static BigInteger count(int n) {
        if (n == 0) return BigInteger.ONE;

        if (minp.length < 3*n) {
            int[] wider = new int[3*n];
            System.arraycopy(minp, 0, wider, 0, minp.length);
            for (int x = minp.length; x < wider.length; x++) {
                // Find the smallest prime which divides x
                for (wider[x] = 2; x % wider[x] != 0; wider[x]++) { /* Do nothing */ }
            }
            minp = wider;
        }

        BigInteger E = countE(n), R2 = countR2(n), F = countF(n), R3 = countR3(n), R = countR(n), FR = countFR(n);
        BigInteger sum = E.add(R3);
        sum = sum.add(R2.add(R).multiply(BigInteger.valueOf(2)));
        sum = sum.add(F.add(FR).multiply(BigInteger.valueOf(3)));
        return sum.divide(BigInteger.valueOf(12));
    }

    private static BigInteger countE(int n) {
        int[] w = new int[3*n];
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j <= i + n; j++) w[j]--;
            for (int j = i + n + 1; j <= i + 2*n; j++) w[j]++;
        }
        return powerProd(w);
    }

    private static BigInteger countR2(int n) {
        int[] w = new int[3*n];
        for (int i = 0; i < n; i++) {
            w[3*i+2]++;
            for (int j = 3*i + 1; j <= 2*i + n + 1; j++) w[j]--;
            for (int j = 2*i + n + 1; j <= i + n + n; j++) w[j]++;
        }
        return powerProd(w);
    }

    private static BigInteger countF(int n) {
        int[] w = new int[3*n];
        for (int i = 0; i < n; i++) {
            for (int j = 2*i + 1; j <= 2*i + n; j++) w[j]--;
            for (int j = i + n + 1; j <= i + 2*n; j++) w[j]++;
        }
        return powerProd(w);
    }

    private static BigInteger countR3(int n) {
        if ((n & 1) == 1) return BigInteger.ZERO;
        return countE(n / 2).pow(2);
    }

    private static BigInteger countR(int n) {
        if ((n & 1) == 1) return BigInteger.ZERO;
        int m = n / 2;
        int[] w = new int[3*m-1];
        for (int i = 0; i < m; i++) {
            for (int j = 1; j <= 3*i+1; j++) w[j] += 2;
            for (int j = 1; j <= i + m; j++) w[j] -= 2;
        }
        return powerProd(w);
    }

    private static BigInteger countFR(int n) {
        if ((n & 1) == 1) return BigInteger.ZERO;
        int m = n / 2;
        int[] w = new int[3*n-2];
        for (int j = 1; j <= m; j++) w[j]--;
        for (int j = 2*m; j <= 3*m-1; j++) w[j]++;
        for (int i = 0; i <= 2*m-3; i++) {
            for (int j = i + 2*m + 1; j <= i + 4*m; j++) w[j]++;
            for (int j = 2*i + 3; j <= 2*i + 2*m + 2; j++) w[j]--;
        }
        return powerProd(w);
    }

    private static BigInteger powerProd(int[] w) {
        BigInteger result = BigInteger.ONE;
        for (int x = w.length - 1; x > 1; x--) {
            if (w[x] == 0) continue;

            int p = minp[x];
            if (p == x) result = result.multiply(BigInteger.valueOf(p).pow(w[p]));
            else {
                // Redistribute it. This should ensure we avoid negatives.
                w[p] += w[x];
                w[x / p] += w[x];
            }
        }

        return result;
    }
}

24
คุณเป็นเทพเจ้าอย่างแท้จริงในหมู่มนุษย์ ฉันหวังว่าจะเห็นทางออกของคุณที่ตีพิมพ์ในวารสารที่มีชื่อเสียง
Alex A.

นี่มันเจ๋งมาก. BTW รหัสของฉัน (ไม่ได้โพสต์ในปัจจุบัน) ให้ 22306956 สำหรับ N = 5: 22231176 (12) +275 (4) +75328 (6) +352 (2) ความแตกต่างของ 1 ซึ่งแปลก ฉันไม่ทราบว่าคุณกำลังทำอะไรที่นี่เหมาะสำหรับการแยกย่อยตามสัดส่วนหรือไม่ สำหรับ N = 4 ฉัน 16 ต่ำกว่าคุณและoeis.org/A066931/a066931.txtจากการอ้างอิงนั้นดูเหมือนว่าฉันมี 16 multiplicity มากเกินไป 12 ซึ่งฉันต้องแปลงเป็น 32 ของ 6 มากมายฉันไม่ ประหลาดใจเกินไปแม้แต่ N ก็ยิ่งยากสำหรับฉัน แต่ฉันไม่มีปัญหากับเลขคี่ N และฉันได้รับคำตอบที่ถูกต้องสำหรับ 0 <N <4 จะมองหาปัญหาที่ชัดเจนและโพสต์รหัสของฉันในวันพรุ่งนี้
เลเวลริเวอร์ St

@ สตีฟเวอร์ริลล์ถ้าฉันเข้าใจสัญลักษณ์สำหรับ N = 5 ฉันทำให้มันเป็น 22231176 (12) + 75328 (6) + 275 (4) + 176 (2) ฉันคิดว่าคุณล้มเหลวในการแบ่งดัชนี 2 ตัวด้วย 2 (FWIW สำหรับตัวเลขคี่พวกเขาทั้งหมดมีแกนสมมาตรผ่านจุดยอดสองจุดและสมมาตรแบบหมุนของลำดับ 3)
Peter Taylor

@ steveverrill และสำหรับ N = 4 ความคลาดเคลื่อนของคุณดูเหมือนจะพอดีกับจำนวนที่มีแกนสมมาตรผ่านจุดกึ่งกลางของสองขอบ
Peter Taylor

3
ประทับใจที่คุณแก้ไขสิ่งนี้ ฉันหวังว่าในที่สุดคุณจะโพสต์คำตอบที่ไม่ใช่นักคณิตศาสตร์สามารถปฏิบัติตาม
DavidC

15

C

บทนำ

ตามที่ให้ความเห็นโดย David Carraher วิธีที่ง่ายที่สุดในการวิเคราะห์การเรียงตัวหกเหลี่ยมดูเหมือนว่าจะใช้ประโยชน์จาก isomorphism กับแผนภาพสามมิติของหนุ่มสาวโดยทั่วไปเป็น x, y สี่เหลี่ยมที่เต็มไปด้วยแท่งความสูงจำนวนเต็ม เมื่อแกน z ถูกเคลื่อนเขา

ฉันเริ่มต้นด้วยอัลกอริทึมสำหรับการหาผลรวมที่ตอบสนองต่อการปรับเพื่อการนับสมมาตรมากกว่าอัลกอริทึมที่เผยแพร่ซึ่งอิงจากอคติกับหนึ่งในสามแกนคาร์ทีเซียน

ขั้นตอนวิธี

ฉันเริ่มต้นด้วยการเติมเซลล์ของระนาบ x, y, และ z ด้วย 1 ในขณะที่ส่วนที่เหลือของพื้นที่ประกอบด้วยศูนย์ เมื่อทำเสร็จแล้วฉันจะสร้างเลเยอร์ลวดลายทีละชั้นโดยแต่ละชั้นจะมีเซลล์ที่มีระยะห่างแมนฮัตตัน 3D ทั่วไปจากจุดกำเนิด เซลล์สามารถมี 1 หากสามเซลล์ด้านล่างนั้นยังมี 1 หากหนึ่งในนั้นมี 0 จากนั้นเซลล์จะต้องเป็น 0

ข้อดีของการสร้างลวดลายในลักษณะนี้คือแต่ละชั้นมีความสมมาตรเกี่ยวกับเส้น x = y = z ซึ่งหมายความว่าแต่ละชั้นสามารถตรวจสอบได้อย่างอิสระสำหรับสมมาตร

การตรวจสอบความสมมาตร

สมมาตรของของแข็งมีดังนี้: 3 การหมุนรอบเกี่ยวกับ x = y = z line -> 3 การหมุนรอบเกี่ยวกับจุดศูนย์กลางหกเหลี่ยม; และการสะท้อนกลับ 3 x เกี่ยวกับระนาบ 3 อันที่มีเส้น x = y = z และแกน x, y, z -> แต่ละเส้นสะท้อนเกี่ยวกับเส้นผ่านมุมหกเหลี่ยม

เพิ่มความสมมาตรได้สูงสุด 6 เท่า เพื่อให้สมมาตรเต็มรูปแบบของรูปหกเหลี่ยมต้องพิจารณาความสมมาตรอีกรูปแบบหนึ่ง ของแข็งแต่ละตัว (สร้างขึ้นจาก 1) มีของแข็งเสริม (สร้างขึ้นจาก 0's) โดยที่ N เป็นเลขคี่, ของแข็งประกอบจะต้องแตกต่างจากของแข็งเดิม (เพราะเป็นไปไม่ได้ที่พวกมันจะมีจำนวนลูกบาศก์เท่ากัน) กระนั้นเมื่อของแข็งประกอบสมบูรณ์หันกลับมาจะพบว่าการแทนแบบ 2 มิติของมันในรูปแบบของเพชรนั้นเหมือนกัน (ยกเว้นการดำเนินการสมมาตร 2 เท่า) กับของแข็งดั้งเดิม เมื่อ N ยังคงเป็นไปได้ที่ของแข็งจะผกผันได้

สามารถเห็นได้ในตัวอย่างสำหรับ N = 2 ในคำถาม หากมองจากด้านซ้ายหกเหลี่ยมแรกจะมีลักษณะเป็นก้อนแข็งที่มีก้อนเล็ก ๆ 8 ก้อนในขณะที่รูปหกเหลี่ยมสุดท้ายนั้นดูเหมือนเป็นเปลือกเปล่าที่มี 0 ก้อนเล็ก ๆ หากมองจากด้านขวาการย้อนกลับจะเป็นจริง รูปหกเหลี่ยมที่ 3, 4 และ 5 และรูปหกเหลี่ยมที่ 16, 17 และ 18 ดูเหมือนว่าพวกเขามีทั้ง 2 หรือ 6 ก้อนและประกอบกันใน 3 มิติ พวกมันเกี่ยวข้องกันใน 2 มิติโดยการดำเนินการสมมาตร 2 เท่า (การหมุน 2 เท่าหรือการสะท้อนเกี่ยวกับแกนผ่านขอบของรูปหกเหลี่ยม) ในทางกลับกันรูปหกเหลี่ยมที่ 9, 10, 11 และ 12 แสดงรูปแบบ 3 มิติซึ่ง เป็นส่วนเติมเต็มของตัวเองและดังนั้นจึงมีความสมมาตรที่สูงขึ้น (เหล่านี้จึงเป็นรูปแบบเดียวที่มีหลายหลากคี่)

โปรดทราบว่าการมี (N ^ 3) / 2 คิวบ์เป็นเงื่อนไขที่จำเป็นในการเติมเต็มด้วยตนเอง แต่โดยทั่วไปจะไม่เพียงพอหาก N> 2 ผลลัพธ์ของสิ่งนี้คือว่าสำหรับคี่ N, การเอียงเกิดขึ้นเสมอในคู่ (N ^ 3) / 2 ลูกบาศก์ต้องได้รับการตรวจสอบอย่างรอบคอบ

รหัสปัจจุบัน (สร้างผลรวมที่เหมาะสมสำหรับ N = 1,2,3,5 ข้อผิดพลาดตามที่กล่าวไว้สำหรับ N = 4)

int n;                     //side length

char t[11][11][11];        //grid sized for N up to 10

int q[29][192], r[29];     //tables of coordinates for up to 10*3-2=28 layers 

int c[9];                  //counts arrangements found by symmetry class. c[8] contains total.


//recursive layer counting function. m= manhattan distance, e= number of cells in previous layers, s=symmetry class.
void f(int m,int e,int s){

  int u[64], v[64], w[64]; //shortlists for x,y,z coordinates of cells in this layer
  int j=0;                 
  int x,y,z;

  for (int i=r[m]*3; i; i-=3){
    // get a set of coordinates for a cell in the current layer.
    x=q[m][i-3]; y= q[m][i-2]; z= q[m][i-1];
    // if the three cells in the previous layer are filled, add it to the shortlist u[],v[],w[]. j indicates the length of the shortlist.
    if (t[x][y][z-1] && t[x][y-1][z] && t[x-1][y][z]) u[j]=x, v[j]=y, w[j++]=z ;
  }


  // there are 1<<j possible arrangements for this layer.   
  for (int i = 1 << j; i--;) {

    int d = 0;

    // for each value of i, set the 1's bits of t[] to the 1's bits of i. Count the number of 1's into d as we go.
    for (int k = j; k--;) d+=(t[u[k]][v[k]][w[k]]=(i>>k)&1);

    // we have no interest in i=0 as it is the empty layer and therefore the same as the previous recursion step. 
    // Still we loop through it to ensure t[] is properly cleared.      

    if(i>0){
      int s1=s;    //local copy of symmetry class. 1's bit for 3 fold rotation, 2's bit for reflection in y axis.
      int sc=0;    //symmetry of self-complement.

      //if previous layers were symmetrical, test if the symmetry has been reduced by the current layer 
      if (s1) for (int k = j; k--;) s1 &= (t[u[k]][v[k]][w[k]]==t[w[k]][u[k]][v[k]]) | (t[u[k]][v[k]][w[k]]==t[w[k]][v[k]][u[k]])<<1;

      //if exactly half the cells are filled, test for self complement
      if ((e+d)*2==n*n*n){
        sc=1;
        for(int A=1; A<=(n>>1); A++)for(int B=1; B<=n; B++)for(int C=1; C<=n; C++) sc&=t[A][B][C]^t[n+1-A][n+1-B][n+1-C];
      }

      //increment counters for total and for symmetry class.
      c[8]++; c[s1+(sc<<2)]++;

      //uncomment for graphic display of each block stacking with metadata. not recommended for n>3.
      //printf("m=%d  j=%d  i=%d c1=%d-2*%d=%d c3=%d cy=%d(cs=%d) c3v=%d ctot=%d\n",m,j,i,c[0],c[2],c[0]-2*c[2],c[1],c[2],c[2]*3,c[3],c[8]);
      //printf("m=%d  j=%d  i=%d C1=%d-2*%d=%d C3=%d CY=%d(CS=%d) C3V=%d ctot=%d\n",m,j,i,c[4],c[6],c[4]-2*c[6],c[5],c[6],c[6]*3,c[7],c[8]);
      //for (int A = 0; A<4; A++, puts(""))for (int B = 0; B<4; B++, printf(" "))for (int C = 0; C<4; C++) printf("%c",34+t[A][B][C]);

      //recurse to next level.
      if(m<n*3-2)f(m + 1,e+d,s1);

    }
  } 
}

main()
{
  scanf("%d",&n);

  int x,y,z;

  // Fill x,y and z planes of t[] with 1's
  for (int a=0; a<9; a++) for (int b=0; b<9; b++) t[a][b][0]= t[0][a][b]= t[b][0][a]= 1;

  // Build table of coordinates for each manhattan layer
  for (int m=1; m < n*3-1; m++){
    printf("m=%d : ",m);
    int j=0;
    for (x = 1; x <= n; x++) for (y = 1; y <= n; y++) {
      z=m+2-x-y;
      if (z>0 && z <= n) q[m][j++] = x, q[m][j++] = y, q[m][j++]=z, printf(" %d%d%d ",x,y,z);
      r[m]=j/3;
    }
    printf(" : r=%d\n",r[m]);
  }

  // Set count to 1 representing the empty box (symmetry c3v)
  c[8]=1; c[3]=1; 

  // Start searching at f=1, with 0 cells occupied and symmetry 3=c3v
  f(1,0,3); 

  // c[2 and 6] only contain reflections in y axis, therefore must be multiplied by 3.
  // Similarly the reflections in x and z axis must be subtracted from c[0] and c[4].
  c[0]-=c[2]*2; c[2]*=3; 
  c[4]-=c[6]*2; c[6]*=3;



  int cr[9];cr[8]=0;
  printf("non self-complement                   self-complement\n");
  printf("c1  %9d/12=%9d           C1  %9d/6=%9d\n",   c[0], cr[0]=c[0]/12,     c[4], cr[4]=c[4]/6);
  if(cr[0]*12!=c[0])puts("c1 division error");if(cr[4]*6!=c[4])puts("C1 division error");

  printf("c3  %9d/4 =%9d           C3  %9d/2=%9d\n",   c[1], cr[1]=c[1]/4,      c[5], cr[5]=c[5]/2);
  if(cr[1]*4!=c[1])puts("c3 division error");if(cr[5]*2!=c[5])puts("C3 division error");

  printf("cs  %9d/6 =%9d           CS  %9d/3=%9d\n",   c[2], cr[2]=c[2]/6,      c[6], cr[6]=c[6]/3);
  if(cr[2]*6!=c[2])puts("cs division error");if(cr[6]*3!=c[6])puts("CS division error");

  printf("c3v %9d/2 =%9d           C3V %9d/1=%9d\n",   c[3], cr[3]=c[3]/2,      c[7], cr[7]=c[7]);
  if(cr[3]*2!=c[3])puts("c3v division error");  

  for(int i=8;i--;)cr[8]+=cr[i]; 
  printf("total =%d unique =%d",c[8],cr[8]);    
}

เอาท์พุต

โปรแกรมสร้างตารางผลลัพธ์ 8 รายการตาม 8 สมมาตรของของแข็ง ของแข็งสามารถมีสมมาตรใด ๆ ของ 4 ดังต่อไปนี้ (สัญกรณ์ Schoenflies)

c1: no symmetry
c3: 3-fold axis of rotation (produces 3-fold axis of rotation in hexagon tiling)
cs: plane of reflection (produces line of reflection in hexagon tiling)
c3v both of the above (produces 3-fold axis of rotation and three lines of reflection through the hexagon corners)

นอกจากนี้เมื่อของแข็งมีครึ่งหนึ่งของเซลล์ที่มี 1 และครึ่งหนึ่งเป็น 0 มีความเป็นไปได้ที่จะพลิก 1 และ 0 ทั้งหมดแล้วแปลงค่าพิกัดผ่านจุดศูนย์กลางของพื้นที่ลูกบาศก์ นี่คือสิ่งที่ฉันเรียกว่าเติมเต็มตัวเอง แต่ศัพท์ทางคณิตศาสตร์ที่มากกว่านั้นก็คือ

การดำเนินการแบบสมมาตรนี้ให้แกนหมุน 2 เท่าในการเรียงหกเหลี่ยม

รูปแบบที่มีความสมมาตรนี้จะแสดงรายการในคอลัมน์แยกต่างหาก พวกมันจะเกิดขึ้นเมื่อ N ยังเท่ากัน

การนับของฉันดูเหมือนจะปิดเล็กน้อยสำหรับ N = 4 ในการสนทนากับ Peter Taylor ดูเหมือนว่าฉันไม่ได้ตรวจจับการเอียงซึ่งมีความสมมาตรของเส้นผ่านขอบหกเหลี่ยมเท่านั้น นี่น่าจะเป็นเพราะฉันไม่ได้ทดสอบความสมบูรณ์ของตัวเอง (antisymmetry) สำหรับการดำเนินการอื่นที่นอกเหนือจาก (การผกผัน) x (อัตลักษณ์) การทดสอบเพื่อความสมบูรณ์ของตัวเองสำหรับ operatons (ผกผัน) x (การสะท้อนกลับ) และ (ผกผัน) x ) อาจเปิดเผยส่วนที่หายไป จากนั้นฉันคาดหวังว่าบรรทัดแรกของข้อมูลสำหรับ N = 4 จะมีลักษณะเช่นนี้ (ลดลง 16 ใน c1 และอีก 32 ใน C1):

c1   224064/12=18672          C1  534/6=89

วิธีนี้จะทำให้จำนวนรวมสอดคล้องกับคำตอบของปีเตอร์และhttps://oeis.org/A066931/a066931.txt

กระแสไฟขาออกมีดังนี้

N=1
non self-complement     self-complement
c1      0/12= 0           C1  0/6= 0
c3      0/4 = 0           C3  0/2= 0
cs      0/6 = 0           CS  0/3= 0
c3v     2/2 = 1           C3V 0/1= 0
total =2 unique =1

non self-complement     self-complement
N=2
c1      0/12= 0           C1  0/6= 0
c3      0/4 = 0           C3  0/2= 0
cs     12/6 = 2           CS  3/3= 1
c3v     4/2 = 2           C3V 1/1= 1
total =20 unique =6

N=3
non self-complement     self-complement
c1    672/12=56           C1  0/6= 0
c3      4/4 = 1           C3  0/2= 0
cs    288/6 =48           CS  0/3= 0
c3v    16/2 = 8           C3V 0/1= 0
total =980 unique =113

N=4 (errors as discussed)
non self-complement     self-complement
c1   224256/12=18688          C1  342/6=57
c3       64/4 =16             C3  2/2= 1
cs     8064/6 =1344           CS  54/3=18
c3v      64/2 =32             C3V 2/1= 2
total =232848 unique =20158

N=5
non self-complement     self-complement
c1  266774112/12=22231176        C1  0/6= 0
c3       1100/4 =275             C3  0/2= 0
cs     451968/6 =75328           CS  0/3= 0
c3v       352/2 =176             C3V 0/1= 0
total =267227532 unique =22306955

รายการสิ่งที่ต้องทำ (อัพเดท)

จัดระเบียบโค้ดปัจจุบันให้เป็นระเบียบ

เสร็จแล้วไม่มากก็น้อย

ใช้การตรวจสอบความสมมาตรของเลเยอร์ปัจจุบันและส่งผ่านพารามิเตอร์สำหรับความสมมาตรของเลเยอร์ก่อนหน้า (ไม่มีจุดตรวจสอบว่าเลเยอร์สุดท้ายนั้นไม่สมมาตรหรือไม่)

เสร็จสิ้นผลลัพธ์สำหรับคี่ N เห็นด้วยกับข้อมูลที่เผยแพร่

เพิ่มตัวเลือกเพื่อระงับการนับตัวเลขอสมมาตร (ควรรันเร็วกว่ามาก)

ซึ่งสามารถทำได้โดยการเพิ่มเงื่อนไขอื่นในการเรียกซ้ำ: if(s1 && m<n*3-2)f(m + 1,e+d,s1)ลดเวลาการทำงานสำหรับ N = 5 จาก 5 นาทีลงเหลือประมาณหนึ่งวินาที เป็นผลให้บรรทัดแรกของผลลัพธ์กลายเป็นขยะทั้งหมด (เช่นเดียวกับผลรวมโดยรวม) แต่ถ้ารวมแล้วเป็นที่รู้จักจาก OEIS จำนวนของการเอียงไม่สมมาตรสามารถสร้างขึ้นใหม่อย่างน้อยสำหรับคี่เอ็นที่แปลก

แต่สำหรับแม้แต่ N จำนวนของแข็งที่ไม่สมมาตร (ตามสมการ c3v) ที่เป็นส่วนประกอบที่สมบูรณ์จะหายไป สำหรับกรณีนี้โปรแกรมแยกต่างหากที่อุทิศให้กับของแข็งที่มี (N ** 3) / 2 เซลล์ที่มี 1 อาจมีประโยชน์ ด้วยสิ่งนี้ที่มีอยู่ (และนับอย่างถูกต้อง) อาจเป็นไปได้ที่จะลอง N = 6 แต่จะใช้เวลานานในการรัน

ใช้การนับเซลล์เพื่อลดการค้นหาสูงสุด (N ^ 3) / 2 ก้อน

ยังไม่เสร็จคาดว่าจะประหยัดได้

ใช้การตรวจสอบความสมมาตร (ของแข็งเสริม) สำหรับรูปแบบที่มี (N ^ 3) / 2 ลูกบาศก์อย่างแน่นอน

เสร็จสิ้น แต่ดูเหมือนจะมีการละเว้นให้ดู N = 4

ค้นหาวิธีเลือกตัวเลขที่ต่ำที่สุดจากคำที่ไม่สมมาตร

การออมไม่คาดว่าจะเป็นสิ่งที่ยอดเยี่ยม ตัวเลขที่ไม่สมส่วนจะช่วยกำจัดสิ่งนี้ได้ส่วนใหญ่ ภาพสะท้อนเดียวที่ถูกตรวจสอบคือระนาบผ่านแกน y (x และ z ถูกคำนวณในภายหลังโดยการคูณด้วย 3) ตัวเลขที่มีสมมาตรแบบหมุนเท่านั้นจะถูกนับในรูปแบบ enantiomeric บางทีมันอาจจะวิ่งเร็วเป็นสองเท่าหากนับเพียงครั้งเดียว

เพื่ออำนวยความสะดวกในเรื่องนี้อาจปรับปรุงวิธีการระบุพิกัดในแต่ละเลเยอร์ (จะสร้างกลุ่มที่เลวลงของ 6 หรือ 3 โดยอาจเป็นกลุ่มที่ 1 ในศูนย์กลางที่แน่นอนของเลเยอร์)

ที่น่าสนใจ แต่อาจมีคำถามอื่น ๆ ในเว็บไซต์เพื่อสำรวจ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.