NxNxN Rubik多维数据集上的置换数量


35

介绍:

3x3x3魔方具有可能的排列,大约为43 亿个。您可能之前已经听说过这个数字,但是实际上是如何计算的呢?43,252,003,274,489,856,000

3x3x3魔方有六个面,每个面有九个贴纸。看(外部)件而不是贴纸,我们有六个中心件。八个角块;和十二个边缘碎片。由于中心不能移动,因此我们可以在计算中忽略它们。至于拐角和边缘:

  • 有()排列八个角的方法。每个角都有三个可能的方向,尽管(八个中的)只有七个可以独立地定向。在给定()可能性的情况下,第八个/最后一个角的方向取决于前面的七个。8!40,320372,187
  • 有()种方式来排列十二条边。从减半这是因为恰好在拐角处时,边缘必须始终保持均匀的排列。在给定()的可能性的情况下,第十二个/最终边缘的翻转取决于前面的十一个,因此可以独立翻转十一个边缘。12!2239,500,80012!21120482112,048

综上所述,我们有以下公式:

8!×37×12!2×211=43,252,003,274,489,856,000

资料来源:维基百科-Rubik的立方体排列

尽管这看起来可能已经很复杂了,但对于3x3x3多维数据集来说仍然相当简单。对于偶数立方体,公式略有不同。例如,这是4x4x4多维数据集的公式:

8!×37×24!2247=7,401,196,841,564,901,869,874,093,974,498,574,336,000,000,000

在短期内大约为7.40 quattudecillion

对于较大的NxNxN多维数据集(即当前的世界记录33x33x33),该公式将扩展很多。但是,为了避免太长的介绍时间,我将这些链接放在此处,其中使用结果公式解释了4x4x4多维数据集和某些其他大小的NxNxN多维数据集的排列:

您可能现在想知道:对于任何 x x多维数据集,是否都有基于的通用公式?当然有。这是三种完全不同的算法,所有算法都基于给出完全相同的结果:NNNNN

1:克里斯·哈德威克的公式:

(24×210×12!)N(mod2)×(7!×36)×(24!)14×(N22×N)(4!)6×14×(N2)2

在WolframAlpha上尝试一下。

2:克里斯托弗·莫拉(Christopher Mowla)的触发公式:

8!×37×(24!(4!)6)14×((N1)×(N3)+cos2(N×π2))×(24!)12×(N2sin2(N×π2))×(12!×210)sin2(N×π2)×124cos2(N×π2)

在WolframAlpha上尝试一下。

3:Christopher Mowla的素数公式:

212×(2×N×(N+7)1711×(1)N)×3N×(N+1)+2×512×(2×N×(N2)+1+(1)N)×718×(6×N×(N2)+3+5×(1)N)×1114×(2×N×(N2)1+(1)N)×9657718×(2×N×(N2)3+3×(1)N)

其中是。96577(13×17×19×23)

在WolframAlpha上尝试一下。

资料来源:Cubers-reddit-职位数量,上帝的人数等的数学计算公式

挑战:

选择并实现这三个公式之一(或您自己的导数),给定输入整数在,它们将输出正确的结果。N[2,100]

挑战规则:

  • 您可以随意使用这三个公式之外的其他公式,但请记住,这三个公式被证明是正确的。如果您使用其他公式,请添加一个从何处获得的链接(或者,如果您自己提出该公式,请添加深入的说明)。如果输出正确,我将检查范围内的所有整数。也许可以在oeis中找到有关此序列的灵感:A075152
  • 如果您的语言自动输出科学输出(即而不是4x4x4公式后面的数字),则允许这样做。但是,请在您的答案中添加其他代码,以将此科学的舍入转换为精确的输出,以便可以验证结果,因为不允许在代码中执行公式期间由于浮点精度而导致舍入错误-应该是实际结果精确。1.401...×1045
  • 您的程序/函数至少对于范围内的输入应该是正确的(尽管由于已经产生了一个巨大的资产号,所以如果您能够输出该数字,那么更大的也可能会起作用。一个正确)。[2,100]N=100N
  • 不允许您使用计数器循环所有可能的排列,因为这绝不会在合理的时间内输出任何内容。仅执行公式(提供的三个公式之一,其中一个公式的衍生物或全新公式),或仅在合理的时间内给出正确结果的另一种方法(当然无需硬编码) ) 被允许。我曾考虑过要添加一个来强制执行此操作,但是我个人反对 CodeGolf与结合使用,所以我不会。不过,请确保您的程序给出了答案,并且如果由于某种原因对于TIO而言太慢,请添加一些屏幕快照,并将本地计算机的输出作为验证。

一般规则:

  • 这是,因此最短答案以字节为单位。
    不要让代码高尔夫球语言阻止您发布使用非代码高尔夫球语言的答案。尝试针对“任何”编程语言提出尽可能简短的答案。
  • 标准规则适用于具有默认I / O规则的答案,因此允许您使用STDIN / STDOUT,具有适当参数的函数/方法以及返回类型的完整程序。你的来电。
  • 默认漏洞是禁止的。
  • 如果可能的话,请添加一个带有测试代码的链接(即TIO)。
  • 另外,强烈建议为您的答案添加说明。

测试用例:

这里的的测试用例的范围为(对于较大的测试用例,可以随意使用上面的WolframAlpha链接):N[2,10]

n=2
3674160

n=3
43252003274489856000

n=4
7401196841564901869874093974498574336000000000

n=5
282870942277741856536180333107150328293127731985672134721536000000000000000

n=6
157152858401024063281013959519483771508510790313968742344694684829502629887168573442107637760000000000000000000000000

n=7
19500551183731307835329126754019748794904992692043434567152132912323232706135469180065278712755853360682328551719137311299993600000000000000000000000000000000000

n=8
35173780923109452777509592367006557398539936328978098352427605879843998663990903628634874024098344287402504043608416113016679717941937308041012307368528117622006727311360000000000000000000000000000000000000000000000000

n=9
14170392390542612915246393916889970752732946384514830589276833655387444667609821068034079045039617216635075219765012566330942990302517903971787699783519265329288048603083134861573075573092224082416866010882486829056000000000000000000000000000000000000000000000000000000000000000

n=10
82983598512782362708769381780036344745129162094677382883567691311764021348095163778336143207042993152056079271030423741110902768732457008486832096777758106509177169197894747758859723340177608764906985646389382047319811227549112086753524742719830990076805422479380054016000000000000000000000000000000000000000000000000000000000000000000000000000000000

注意:由于这是一个挑战,因此基本上可以归结为:尽可能短地实现这三个公式之一(或派生式/您自己的方法仍会产生正确的结果)。


2
在x86-64中执行此操作将是一个有趣的挑战。我必须滚动自己的bigint(可能只是256位或512位int),并使它具有高尔夫球状。
moonheart08

1
@ moonheart08请注意,如果N = 100,则结果大约需要128 Kb(16 KB):https
所罗门·乌科

4
请注意,Mowla的“ trig”公式仅使用和对s 进行模糊处理。cos 2sin2cos2floor
attinat

4
@attinat,我认为这是一个更有用的观点,即和地板都使变得模糊Nmod2
Peter Taylor

2
@ChristopherMowla不要个人发表评论。我很惊讶您能够找到这些公式并首先做出如此准确的预测,而您的公式就是这一挑战的灵感之一。但是,这是代码问题,因此,如果它可以在答案中节省一个字节,那么可读性,性能,警告,最佳实践,历史意义以及有时只是常识都将被抛在脑后。;)attinatPeterTaylor只是根据您的公式提出了这样的建议,因为在编程语言中使用N mod 2比使用trig短得多。
Kevin Cruijssen

Answers:


12

Wolfram语言(Mathematica),59个字节

f@n_:=(s=24^6)(24!/s)^(m=n-2)f@m
f@2=7!3^6
f@3=4!12!2^10f@2

在线尝试!

使用OEIS页面中的 Herbert Kociemba算法

这是递归公式:
a(1)=1; a(2)=7!*3^6; a(3)=8!*3^7*12!*2^10; a(n)=a(n-2)*24^6*(24!/24^6)^(n-2)

@Peter Taylor保存了6个字节

@Expired Data再保存一个字节



@ExpiredData非常好!我试图做同样的事情,但由于顺序不同而失败
J42161217

这个问题不需要您的支持f@1,因此您可以节省6个字节。显然,您还希望调整要使用的测试框架Range[2,10]
彼得·泰勒

@PeterTaylor很棒的观察。谢谢!
J42161217

不幸的是,需要定义@CSM f [3]。否则该公式将返回错误的结果
J42161217

9

x86机器码,119个字节

十六进制转储:

60 c6 02 02 33 db be 25 01 10 00 f6 c1 01 74 05
be 26 2a b2 36 33 ed 51 b1 06 33 ff 53 8a 04 1a
f6 e1 03 c7 b5 0a f6 f5 88 64 1a 02 66 98 8b f8
4b 79 ea 5b 43 43 f6 f5 66 89 02 84 c0 75 0c 60
8b fa 8d 72 01 8b cb f3 a4 61 4b 41 d1 ee 72 ca
75 f9 be 1d d4 0d 10 4d 79 be 59 49 49 8b e9 be
06 02 02 22 83 f9 02 73 ae c6 44 1a 01 00 80 0c
1a 30 4b 79 f9 61 c3

函数接收数necx在一个指向一个字符串来填充,和edx(即fastcall约定)。

在显示源代码之前,请先对其进行一些解释。它使用递归公式,该公式是通过以下方式编写的:

init = 2
m1 = 24^6 = 6*8*9*16*24*32*36
m2 = 24!/24^6 = 6*7*9*10*11*17*19*21*22*23*25*26*35
num(2) = init * 6*7*9*12*15*27
num(3) = init * 6*8*9*12*16*18*20*24*27*28*30*32*33*35*36
num(n+2) = num(n) * m1 * m2^n

因此,所有代码所要做的就是乘以小数。数字在6 ... 36范围内,该范围足够小以可以在32位位图中表示。我实际上并不存储表示乘以6的位-这使我可以将代码do-while无条件乘以6并排成一个循环。

大数字以十进制形式表示-每个字节都是从MSB开始的0 ... 9范围内的值。

从LSB到MSB进行乘法;假设每次乘法的位数将增加2。在乘以6这样的小倍数后,位数可能仅增加1。因此,如果MSB = 0,则它将整个中间结果向左移动。实际上可能发生的是位数完全没有增加,然后MSB仍为0,但是随着代码处理更多因素,此问题将自行解决。

因为乘法代码很大,所以我不想重复两次。我也不想将其移至函数,因为调用函数的机器代码很大。因此,我以仅需一次乘法代码的方式重新排列了外部循环。

C代码:

void num(int n, char* x)
{
    *x = 2;
    int len = 1;
    int exp_i;
    uint32_t m32_1;
    int m1;
    int carry;
    int temp;
    int str_i;
    bool cf;

    if (n % 2 == 0)
    {
        m32_1 = 0x100125; // 6*7*9*12*15*27
    }
    else
    {
        m32_1 = 0x36b22a26; // 6*8*9*12*16*18*20*24*27*28*30*32*33*35*36
    }

    exp_i = 0;
    while (true)
    {
        for (; exp_i >= 0; --exp_i)
        {
            m1 = 6;
            cf = true;
        do_mult:
            carry = 0;
            for (str_i = len - 1; str_i >= 0; --str_i)
            {
                temp = x[str_i] * m1 + carry;
                x[str_i + 2] = temp % 10;
                carry = temp / 10;
            }
            len += 2;
            x[1] = carry % 10;
            carry /= 10;
            x[0] = carry;
            if (carry == 0)
            {
                --len;
                for (str_i = 0; str_i < len; ++str_i)
                    x[str_i] = x[str_i + 1];
            }

        shift_m1:
            ++m1;
            cf = m32_1 & 1;
            m32_1 >>= 1;
            if (cf)
                goto do_mult;
            if (m32_1)
                goto shift_m1;

            m32_1 = 0x100dd41d; // 24!/24^6 = 6*7*9*10*11*17*19*21*22*23*25*26*35
        }
        --n;
        --n;
        exp_i = n;
        if (n < 2)
            break;
        m32_1 = 0x22020206; // 24^6

    }
    x[len] = 0;
    for (str_i = len - 1; str_i >= 0; --str_i)
    {
        x[str_i] += '0';
    }
}

拆卸:

60                     pushad;
C6 02 02               mov byte ptr [edx], 2; // edx = x
33 DB                  xor ebx, ebx; // ebx = len - 1
BE 25 01 10 00         mov esi, 0x100125; // esi = m32_1
F6 C1 01               test cl, 1;
74 05                  jz skip1;
BE 26 2A B2 36         mov esi, 0x36b22a26; // esi = m32_1
                   skip1:
33 ED                  xor ebp, ebp; // ebp = exp_i

                   loop_n:

51                     push ecx;
                   loop_exp_i:
B1 06                  mov cl, 6; // cl = m1
                   do_mult:
33 FF                  xor edi, edi; // edi = carry
53                     push ebx; // ebx = str_i
                   loop_str_i:
8A 04 1A               mov al, [edx + ebx];
F6 E1                  mul cl;
03 C7                  add eax, edi;
B5 0A                  mov ch, 10;
F6 F5                  div ch;
88 64 1A 02            mov [edx + ebx + 2], ah;
66 98                  cbw;
8B F8                  mov edi, eax;
4B                     dec ebx;
79 EA                  jns loop_str_i;

5B                     pop ebx; // ebx = len - 1
43                     inc ebx;
43                     inc ebx;
F6 F5                  div ch;
66 89 02               mov [edx], ax;

84 C0                  test al, al;
75 0C                  jnz skip2;

60                     pushad;
8B FA                  mov edi, edx;
8D 72 01               lea esi, [edx + 1];
8B CB                  mov ecx, ebx;
F3 A4                  rep movsb;
61                     popad;
4B                     dec ebx;
                   skip2:

                   shift_m1:
41                     inc ecx;
D1 EE                  shr esi, 1;
72 CA                  jc do_mult;
75 F9                  jnz shift_m1;

BE 1D D4 0D 10         mov esi, 0x100dd41d;

4D                     dec ebp;
79 BE                  jns loop_exp_i;

59                     pop ecx; // ecx = n
49                     dec ecx;
49                     dec ecx;
8B E9                  mov ebp, ecx;
BE 06 02 02 22         mov esi, 0x22020206;
83 F9 02               cmp ecx, 2;
73 AE                  jae loop_n;

C6 44 1A 01 00         mov byte ptr [edx + ebx + 1], 0;
                   loop_to_ascii:
80 0C 1A 30            or byte ptr [edx + ebx], '0';
4B                     dec ebx;
                       dec         ebx  
79 F9                  jns loop_to_ascii;

61                     popad;
C3                     ret;

n = 100的运行时间约为4秒,结果是一个带有38416位数字的数字:

23491019577617(此处为许多数字)...(此处为零)0000000000000000


8

05AB1E,38个字节

初步尝试。
使用克里斯·哈德威克(Chris Hardwick)的公式
将尝试进一步打高尔夫球并解释我何时有空。

24©To12!PIÉm7!729®!InI·-4÷mP®IÍn4÷6*m÷

在线尝试!


8

朱1.083 76个字节

n->^(24576*~12,n%2)*3^6*~7(~24)^((m=n-2)n÷4)/24^(m^2÷4*6)
~n=prod(big,1:n)

在线尝试!

使用克里斯·哈德威克的公式。将输入作为大整数。

感谢H.PWiz -7个字节


1
~=n->factorial(big(n))-> ~n=prod(big,1:n)(24576*~12)^(n%2)->^(24576*~12,n%2)
H.PWiz

为什么用~=n->代替~n=
H.PWiz

@ H.PWiz,仅仅是因为我什至不知道它会以这种方式工作,并且在您之前的评论中也没有注意到这一点:)
Kirill L.




6

JavaScript(Node.js)77 75 73字节

n=>0xb88d4641131f0n**(n*(n-2n)/4n)*13824n**n*851558400n**(n%2n)*315n>>14n

在线尝试!基于克里斯托弗·莫拉的公式。以BigInt作为输入。测试线束从@Arnauld无耻地被盗。0xb88d4641131f0n3246670537110000n十进制。说明:我从最后一个质数指数开始并将其简化为n*(n-2n)/4n(这是整数除法,因此我不需要对奇数进行调整)。然后,我检查了其他素数,以查看它们的指数是否与此值相关(我将其称为o),并发现如果我允许使用奇偶校验n(我将其称为p)。指数的公式如下:

23:       o
19:       o
17:       o
13:       o
11:      2o +   p
 7:      3o +   p +  1
 5:      4o +  2p +  1
 3: 3n + 4o +  3p +  2
 2: 9n + 4o + 14p - 14

然后可以将幂按指数分组,例如p是的指数11*7*5**2*3**3*2**14


5

球拍151个 141字节

-7字节感谢fede s。!

(λ(n[e expt])(/(*(e 11771943321600(modulo n 2))3674160(e 620448401733239439360000(floor(/(*(- n 2)n)4))))(e 24(*(floor(/(sqr(- n 2))4))6))))

在线尝试!

使用克里斯·哈德威克公式的最长答案:)


1
您可以更改λ的定义(2个字节),并为其他参数使用默认值,以从三个expt调用中保存3个以上的字节(λ(n[e expt])...(e ...)...)
fede s。

@fedes。谢谢!
Galen Ivanov



3

CJam(47字节)

qi[1_7m!Z6#*_3*Cm!*2D#*]{2-_j24_m!\6#:P/@#*P*}j

在线演示

这实现了OEIS的Herbert Kociemba递归: 使用CJam的备忘录递归运算符。我已经按照与代码中相同的顺序对MathJax块中的术语进行了排序,以使阅读CJam的人员易于验证对应关系:任何进一步的剖析都不会更加清晰。

a(n)={1 if n{0,1}7!×36 if n=2a(n1)×3×12!×213 if n=3a(n2)×(24!246)n2×246 if n>3
j




2

C(gcc) -lgmp,279个字节

#include "gmp.h"
#define s mpz_init_set_str
#define m(X)mpz_##X
f(int N,m(t)_){m(t)x;m(init)(x);m(init_set_str)(_,N&1?"3LFbOUwC":"1",62);m(mul_si)(_,_,3674160);m(fac_ui)(x,24);m(pow_ui)(x,x,(N*N-2*N)/4);m(mul)(_,_,x);m(set_si)(x,24);N-=2;m(pow_ui)(x,x,6*N*N/4);m(tdiv_q)(_,_,x);}

在线尝试!


1
推荐N--*--N/4代替(N*N-2*N)/4,并删除N-=2#define s mpz_init_set_str
ceilingcat




1

外壳51 48 44字节

-H.PWiz -4个字节

÷^*6÷4□-2⁰Π4*^÷4-D⁰□⁰Π24*729*Π7^%2⁰*24576Π12

在线尝试!

这是克里斯·哈德威克(Chris Hardwick)的公式。另外,这是我的第一个外壳程序,因此任何提示将不胜感激。


1
这是一个简单的2个字节:÷^*6÷4□-2⁰Π4*^÷4-D⁰□⁰Π24*729*Π7^%2⁰*24*1024Π12
H.PWiz

1
或者,更好的是÷^*6÷4□-2⁰Π4*^÷4-D⁰□⁰Π24*729*Π7^%2⁰*24576Π12
H.PWiz

1

在此处输入图片说明

C ++,187185180176195(有一个错误)193175字节(在吊顶猫的帮助下)

这使用了GMP C ++包装器(GNU多精度库)以及@ J42161217(https://codegolf.stackexchange.com/a/183381/55953)使用的公式。

使用g++ -g rubix.cpp -lgmp -lgmpxx编译和链接

#include <gmpxx.h>
#define R return
using z=mpz_class;z p(z a,z b){z c=1;while(b--)c*=a;R c;}z r(z n){if(n==2)R 3674160;if(n==3)R z("pX4dIaR7jDk",62);R r(n-2)*p(24,6)*p(z("ErvSErbeq",62),n-2);}

松散,带有测试代码

#include <gmpxx.h>
#include <iostream>
mpz_class p(mpz_class a, mpz_class b) // returns a to power of b. Only works for b  = positive integer
{
    mpz_class c=1;

    while(b--)
        c*=a;

    return c;
}


mpz_class r(mpz_class n) // returns the rubix permutations for a cube of size n
{
    if(n==2)
        return 3674160; // 7!*3^6;

    if(n==3)
        return z("pX4dIaR7jDk",62); // 43252003274489856000 = 8!*3^7*12!*2^10

    return r(n-2) * p(24,6) * p(z("ErvSErbeq", 62), n-2);

    // "ErvSErbeq"base 62 = 3246670537110000 = (24!/24^6)        
}    

main()
{
    for(int i=2; i<34; i++)
        std::cout<<i<<'\t'<<r(i) << std::endl;
}

https://tio.run/##PZAxb4MwEIV3foWVDrETqBpARMImWZqha7t0iFQZ4xC3xrg2tJERf73UIVXfcE937zvpdEzrqGZsmu6EYrKvOKkbfbncn3dBb4WqgSsa7d6YpNZiBzR0gIYOlGhwgBUb/H0WksMyihBbFRQb3vVGAYZHB4xnFRr@Rqoo4n2SbdNN9pD7Jtk7uNCvafVEn7fvjx@LMItRbqCKYrTSME7D7OoeOpivl4Mp@eeMhFcAj//3AiJa2xlOm13QUKEgCoYAeJ1aA4XqgChiDARJUl/XazRnXrar8py1fUeIIGR57JaE@AUECLllXFUSB2Mw/bCTpLWdIjm/5ua/


您能否添加n=10测试用例的屏幕截图,以便我可以验证它是否有效?我猜由于使用的库,没有任何方法可以在C ++(clang)或C ++(gcc)TIO上实现此功能?
凯文·克鲁伊森

Argg。n的奇数值不起作用
CSM

1
多谢您提供萤幕撷取画面,也很高兴您可以找出错误并加以修正。向我+1。:)
Kevin Cruijssen


Ta @ceilingcat。#define返回不再需要,因为只有两个返回点
CSM

1

TI-BASIC,63 62 字节,(非竞争)

{fPart(.5Ans),1,1,-6}int(4⁻¹{8,4,Ans²-2Ans,(Ans-2)²:prod({9*11!2^15,7!3^6,24!,24}^Ans

将输入作为上的整数的表达式Ans。克里斯·哈德威克公式的实现。不竞争是因为运行它的硬件最多只能存储16个小数位,因此答案永远不会是100%准确的。

说明:

{fPart(.5Ans),1,1,-6}              # the list {(N (mod 2))/2,1,1,-6}
                                   # implicitly multiplied by
int(4⁻¹{8,4,Ans²-2Ans,(Ans-2)²     # the list {2,1,⌊¼(N²-2N)⌋,⌊¼(N-2)²⌋}
:                                  # store this list of the formula's exponents as Ans
     {9*11!2^15,7!3^6,24!,24}      # list of the formula's bases
                             ^Ans  # raised to their exponents
prod(                              # multiplied together
                                   # implicit print
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.