明確なリバーシブルプリミティブバイナリネックレス


8

はじめに-ネックレスとは?

ネックレスはOEISの人々が夢中になっているものです。OEISチャレンジには、ネックレスのシーケンスが5つあります。

長さのバイナリネックレスは、またはnであるnビーズのループです。2つのネックレスは、一方を回転させてもう一方にすることができれば同じです。2つのリバーシブルネックレスは、一方を回転、反転、または反転して回転させてもう一方にすることができる場合は同じです。01

プリミティブネックレスは、一連のビーズのチェーンの複数のコピーとして表現できないネックレスです。ネックレスがプリミティブでないと見なされるためには、コピーがすべて同じ順序で(逆転なしで)組み立てられる必要があることに注意してください。

たとえば、このネックレスを見てみましょう0 1 1 0 1 10 1 12回繰り返されていると表現できるため、プリミティブではありません。0 1 0 1 1原始的です。

0 1 1 0同じ文字列0 11 0は見なされないため、プリミティブです。このネックレスは、1 1 0 0左に1つのビーズを回転させてこのネックレスにすることができるため、同等ですが、0 1 0 1(プリミティブではありませんが)同等ではありません。

チャレンジ

負でない整数を指定するとn、長さが異なる可逆的なプリミティブバイナリネックレスの数を返しnます。それぞれ単一の整数として入力および出力します。

このシーケンスの最初の数項は1, 2, 1, 2, 3, 6, 8, 16, 24, 42, 69, 124, 208, 378, 668, 1214, 2220, 41100インデックスです。

これはOEIS A001371です

Python 3のリファレンス実装 -非常に遅い


4
「プリミティブ」とは、部分的に回転させて元のネックレスを手に入れることができないということですよね?
ETHproductions 2017

@ETHproductions ...私はそのように考えたことはありません。はい、それは間違いなく正しい理解です。いいね!
HyperNeutrino 2017

なぜ0 1 0 1原始的ですか?0 1二度繰り返されていませんか?
Misha Lavrov 2017

@MishaLavrovありがとうございます。「プリミティブではない」という意味です。ありがとう
HyperNeutrino 2017

ಠ_ಠチャレンジとして投稿するOEISシーケンスを探していました。次に目にするのは...これ...ネックレスです。._。
完全に人間的な2017

回答:


6

Pythonの2178の 171 139 137バイト

lambda n:sum(1-any(i>int(b[j::-1]+b[:j:-1],2)or j*(i>=int(b[j:]+b[:j],2))for j in range(n))for i in range(2**n)for b in[bin(i+2**n)[3:]])

オンラインでお試しください!編集:@HalvardHummelのおかげで7 21バイトが節約されました。



1
@HalvardHummelおかげで、ワンライナーですべての順列を生成する方法を見つけることができませんでした。
Neil

5

JavaScript(ES6)、198 192バイト

完全に数学的な答えがどのようになるか知りたいと思っていました。だからここにあります。かなり長いが非常に速い。

n=>(g=d=>d&&(n%d?0:(q=n/d,C=(a,b)=>b?C(b,a%b):a<2,M=n=>n%++k?k>n?(q%2+3)/4*(1<<q/2)+(R=d=>d&&(q%d?0:(P=k=>k--&&C(q/d,k)+P(k))(q/d)<<d)+R(d-1))(q)/q/2:M(n):n/k%k&&-M(n/k))(d,k=1))+g(d-1))(n)||1

デモ

どうやって?

これは、次の式に基づいています。

A000029(n) =
  (n % 2 + 3) / 4 * 2 ** floor(n / 2) +
  sum(φ(n / d) * 2 ** d, for d in divisors(n)) / (2 * n)

A001371(n) =
  1 if n = 0
  sum(μ(d) * A000029(n / d), for d in divisors(n)) if n > 0

ここで、φオイラーのトーテント関数μメビウス関数です。

n => (g = d =>
  // if d = 0, stop the recursion of g()
  d && (
    // if d is not a divisor of n, ignore this iteration
    n % d ? 0 :
    (
      // define q = n / d, C = function that tests whether a and b are coprime,
      // M = Möbius function (requires k to be initialized to 1)
      q = n / d,
      C = (a, b) => b ? C(b, a % b) : a < 2,
      M = n => n % ++k ? k > n || M(n) : n / k % k && -M(n / k)
    )(d, k = 1) * ( // invoke M with d
      // first part of the formula for A000029
      (q % 2 + 3) / 4 * (1 << q / 2) +
      // 2nd part of the formula for A000029
      (R = d =>
        // if d = 0, stop the recursion of R()
        d && (
          // if d is not a divisor of q, ignore this iteration
          q % d ? 0 :
          // compute phi(q / d) * 2 ** d
          (P = k => k-- && C(Q, k) + P(k))(Q = q / d) << d
        // recursive call to R()
        ) + R(d - 1)
      )(q) / q / 2 // invoke R with q, and divide the result by q * 2
    )
  // recursive call to g()
  ) + g(d - 1)
)(n) || 1

注意:現在のゴルフバージョンでは、コードの2番目の部分がM()内に直接埋め込まれています。しかし、それによりコードが読みにくくなります。


4

Mathematicaの、128の 125 124 109 99バイト

1~Max~(L=Length)@(U=Union)[U[#,Reverse/@#]&/@MaximalBy[U@Partition[#,L@#,1,1]&/@{0,1}~Tuples~#,L]]&

使い方

  • {0,1}~Tuples~# 指定された長さのすべてのバイナリシーケンスを検索します
  • U@Partition[#,L@#,1,1]&/@... それらのそれぞれのすべての可能な回転を見つけます
  • MaximalBy[...,L]ローテーションが最も明確なエントリを選択します。これらは原始的なネックレスに対応しています。
  • U[#,Reverse/@#]&/@... 各エントリのローテーションとその逆を標準的な順序に入れます...
  • (L=Length)@(U=Union)[...] ...重複したプリミティブネックレスを削除して、残りの要素を数えることができるようにします。
  • 1~Max~... 第0項を正しくするために、結果が少なくとも1であることを確認します。

-Jonathan Frechのおかげで-2バイト、そして彼から学んだ私のおかげで-2

切り替え および関連する変更からさらに-15バイトMaximalBy

-10から切り替え Partition


1
に置き換えLengthL定義するL=Length;と、バイトを節約できると思います。
Jonathan Frech 2017


125、Lengthのインスタンスの1つをゴルフするのを忘れたので。ありがとう!
ミシャラブロフ2017

そして今では124です。私はあなたの例から学び、別のものをに==1変えたから<2です。
ミシャラブロフ2017

3

Husk、21バイト

Ṡ#▲mLüOmȯṁSe↔U¡ṙ1ΠRḋ2

オンラインでお試しください! リンクは0から10までの結果を示します。

説明

Ṡ#▲mLüOmȯṁSe↔U¡ṙ1ΠRḋ2  Implicit input, say n=4.
                  Rḋ2  The list [1,0] repeated n times: [[1,0],[1,0],[1,0],[1,0]]
                 Π     Cartesian product: [[1,1,1,1],[0,1,1,1],[1,0,1,1],...,[0,0,0,0]]
       mȯ              For each list, say x=[0,1,0,0]:
              ¡ṙ1        Iterate rotation by one step: [[0,1,0,0],[1,0,0,0],[0,0,0,1],[0,0,1,0],[0,1,0,0],...
             U           Take prefix of unique values: [[0,1,0,0],[1,0,0,0],[0,0,0,1],[0,0,1,0]]
         ṁSe↔            After each element, insert its reversal: [[0,1,0,0],[0,0,1,0],[1,0,0,0],[0,0,0,1],[0,0,0,1],[1,0,0,0],[0,0,1,0],[0,1,0,0]]
     üO                Remove duplicates with respect to sorting.
   mL                  Get length of each list of lists.
Ṡ#▲                    Count the number of maximal lengths.


1

JavaScript(ES7)、180バイト

n=>[...Array(2**n)].filter((_,m)=>![...m=m.toString(2).padStart(n,0)].some(_=>s[m=m.replace(/(.)(.*)/,"$2$1")]|s[[...m].reverse().join``])&!/^(.+)\1+$/.test(m)&(s[m]=1),s=[]).length

説明:

n=>[...Array(2**n)].filter((_,m)=>(     // For every number m from 0 to 2^n-1
    m=m.toString(2).padStart(n,0),      // Take the binary representation (padded)

    ![...m].some(_=>(                   // Repeat once for every digit in m
        m=m.replace(/(.)(.*)/,"$2$1"),  // Rotate m one step
        s[m]|s[[...m].reverse().join``] // Search for m and the reverse of m in the
    ))                                  // lookup table

    &!/^(.+)\1+$/.test(m)               // Test if m is primitive
    &(s[m]=1)                           // Add m to the lookup table

),s=[]).length                          // Get the length of the list of numbers that
                                        // satisfy the above conditions

f=n=>[...Array(2**n)].filter((_,m)=>![...m=m.toString(2).padStart(n,0)].some(_=>s[m=m.replace(/(.)(.*)/,"$2$1")]|s[[...m].reverse().join``])&!/^(.+)\1+$/.test(m)&(s[m]=1),s=[]).length
<input id=i type=number value=5/><button onclick="o.innerText=f(i.value)">Test</button><br><pre id=o></pre>

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.