Skolemシーケンスを生成する


10

スコーレムシーケンス

A スコーレムシーケンスは、一連のある2nすべての番号の数字iの間1とは、n正確に2回出現する、との2つの出現の間の距離がi正確であるiステップ。Skolemシーケンスの例をいくつか示します。

1 1
1 1 4 2 3 2 4 3
16 13 15 12 14 4 7 3 11 4 3 9 10 7 13 12 16 15 14 11 9 8 10 2 6 2 5 1 1 8 6 5

次のシーケンスはスコーレムシーケンスではありません

1 2 1 2      (The distance between the 1's is 2, not 1)
3 1 1 3      (The number 2 is missing)
1 1 2 1 1 2  (There are four 1's)

目的

プログラム、関数、または式を記述して、指定された長さのすべてのSkolemシーケンスの数をカウントします。より明確には、入力は整数nであり、出力は長さのSkolemシーケンスの数です2n。このシーケンスにはOEISエントリがあります。の場合n = 00またはのいずれかを返すことができます1。最初のいくつかの値から開始し0、あります

0, 1, 0, 0, 6, 10, 0, 0, 504, 2656, 0, 0, 455936, 3040560, 0, 0, 1400156768

ルールとスコアリング

これはコードゴルフです。出力形式は理由の緩いです。


気になるだけですが0, 1, 0, 0, 6...、あなたの質問には何がありますか?それはコードスニペットですか、もしそうなら、それはどの言語ですか?
PhiNotPi 2013年

2
出力の最初の項目がなぜ0ですか?0有効な入力として認める場合、出力はになります1
Peter Taylor

1
一部の(私のコードを含む)は、空のシーケンスがないと信じています。1で気分が良くなった場合は、それを返します。
2013年

2
すべてのコンテキストで AFAIKは、空のシーケンス/ nullオブジェクト/空のセットなど/ function-to / from-the-empty-set /空のグラフ/その他が1つしかないと想定しています。
Bakuriu 2013年

1
@boothby、あなたはクヌースをバカと呼んだの?
Peter Taylor

回答:


8

GolfScript、48 46文字

:b,1,{)2\?){{.2$&!{.2$|@@}*.+.4b?<}do;;}+%}@/,

高速バージョン(オンラインで試す)- n=8約2秒かかるなど、かなり高速に実行されます。そして、選ばれたアプローチは本当に少数の文字をとります。

このバージョンはビットマスクでも動作します。これは、1から可能な結果配列を作成しn=3ます。

1: 000011        000110 001100 011000 110000
2: 010111 101011 101110        011101 110101 111010

一部の結果(000011など)には2つの可能な継続がありますが、他の結果(つまり001100)には継続がなく、結果配列から削除されます。

コードの説明:

:b           # save the input into variable b for later use
,            # make the list 0..b-1 (the outer loop)
1,           # puts the list [0] on top of the stack - initially the only possible
             # combination
{)           # {...}@/ does the outer loop counting from i=1 to b
  2\?)       # computes the smalles possible bit mask m=2^i+1 with two bits set 
             # and distance of those equal to i (i.e. i=1: 11, i=2: 101, ...)
  {          # the next loop starts with this bitmask (prepended to code via
             # concatination {...}+
             # the loop itself iterates the top of the stack, i.e. at this point 
             # the result array                 
             # stack here contains item of result array (e.g. 00000011)
             # and bitmask (e.g. 00000101)
    {        # the inner-most loop tries all masks with the current item in the result set
      .2$&!  # do item and result set share not single bit? then - {...}*
      {
        .2$| # then generate the new entry by or-ing those two
        @@   # push it down on the stack (i.e. put working items to top)
      }*
      .+     # shift the bit mask left by one
      .4b?<  # if still in the range loop further
    }do;;    # removes the remainders of the loop (i.e. item processed and mask)
  }+%        # stack now contains the new result array
}@/
,            # length of result array, i.e. the number of Skolem sequences

より高速な提携ソリューションを受け入れる。
ブース

6

J式、47文字

 +/*/"1((=&{:+.2-#@])#;.2)\"1~.(i.!+:y)A.,~>:i.y

例:

    y=:5
    +/*/"1((=&{:+.2-#@])#;.2)\"1~.(i.!+:y)A.,~>:i.y
10

y=:5私のマシンでは約30秒かかります。

アルゴリズムは可能な限り遅い:

  • ~.(i.!+:y)A.,~>:i.y1 2 .. y 1 2 .. y重複するエントリの順列をすべて生成して削除します
  • ((=&{:+.2-#@])#;.2)\"1 計算:
    • (...)\"1 すべての行のすべてのプレフィックス:
      • #;.2 最後の要素が出現する前に要素を数えます
      • #@] カウント数をカウントします(つまり、最後の要素の出現回数)
      • =&{: カウントリストと元のリストの「等しい」「最後の」要素を決定します。
      • +.論理ORです。=&{:+.2-#@]「[カウントリストと元のリストの]最後の要素が等しいか、[カウントリスト内の]要素が2つではなく1つしかない」と読み取ります。
  • */"1 条件テーブルの行を乗算(論理AND)して、Skolemシーケンスである順列を決定します。
  • +/ 1と0を合計します。

6

GolfScript(46文字)

:&1,\,{0,2@)?)2&*{2${1$^}%@+\2*}*;+}/{4&?(=},,

これはスタックで入力を受け取る式です。標準入力で入力を受け取る完全なプログラムに変換するには、先頭に~

それはかなり非効率的です-私がゴルフをしなかった56文字からゴルフで節約したほとんどの節約は、誤った結果をもたらさない方法でループの範囲を拡大することによってでしたが、計算を無駄にしました。

このアプローチは、デカルト積のビット単位のマスキングです。たとえばn=4、ゴルフではないコードの(マスクにバイナリを使用する)と、デカルト積の各要素のxorが計算されます[00000011 00000110 ... 11000000] x [00000101 00001010 ... 10100000] x ... x [00010001 ... 10001000]。8ビットの結果は、重複しないマスクによってのみ達成できます。

速度ではなくサイズを最適化するために、コードは部分積(S1 u S1xS2 u S1xS2xS3 ...)を累積し、各積を、実際に有効なシーケンスに寄与できる2nものだけではなく要素で構成し2n-1-iます。

速度

n=5私のコンピューターではゴルフバージョンが10秒で実行され、で5分以上実行されn=6ます。元の非ゴルフバージョンn=5は、1秒未満で計算されn=6、約1分で計算されます。中間結果に対する単純なフィルターを使用するとn=8、30秒で計算できます。ループを可能な限り制限し、中間の衝突をフィルタリングしながら、66文字(プログラムとして-式として65文字)に調整しました。

~:&1,\,{0,\).2\?)2&*@-{.{[\].~^.@~+<{;}*}+3$%@+\2*}*;\;}/{4&?(=},,

くそー。私の48char Jソリューションが投稿するのに十分であると思ったとき。
John Dvorak 2013年

くそー。47文字のネクタイはそれほど長くは続きませんでした。+1
John Dvorak 2013年

5

GolfScript、49文字

~:/..+?:d(,{d+/base(;:w;/,{.w?)w>1$?=},,/=},,/1=+

nSTDIN の数値が必要です。これはコードゴルフnです-5より大きいコードは試さないでください。


痛い、5以下?
ブース

@boothby最初の直接的な試みでした。多くの場合、サイズと比較して決定速度をとる必要があります。コードゴルフはほぼサイズです。そのため、高速バージョンも追加しました。これは元々は長かったのですが、現在はさらに短くなっています。
ハワード

0

セージ、70

これは私のオリジナルより少し短いです。

sum(1for i in DLXCPP([(i-1,j,i+j)for i in[1..n]for j in[n..3*n-i-1]]))

使い方:

0/1行列が与えられた場合、その行列の正確なカバーの問題は、すべて1のベクトルに(整数として)合計される行のサブセットを見つけることです。例えば、

11001
10100
01001
00011
00010

解決策があります

10100
01001
00010

問題に対する私のお気に入りのアプローチは、正確なカバー問題にそれらをキャストすることです。スコーレムシーケンスはこれを効率的に促進します。私は、解が長さのSkolemシーケンスで全単射である正確なカバー問題を作り2nます。たとえば、問題の行n=6

  a   |  b  
001000|001001000000 # S[b] = S[b+a+1] = a

ここで1の位置a < nは、その記号aが使用されることを意味します。残りの位置は、シーケンスの実際の位置に対応しています。正確なカバーは、各シンボルが1回だけ使用され、各場所が1回だけ入力されることに対応します。構造上、kロケーション内のシンボルはkそのパートナーから離れています。

セージでDLXCPPは、「ダンシングリンク」の実装です。これは、非常に優雅な方法で正確なカバー問題を解決します。これは私のお気に入りのアルゴリズムの1つであり、Sageの表面上にあることで、組み合わせの列挙が喜びになります。


うわー、ダンスリンク。使用するlen(list(...))と4文字節約されます。
レイ

@Ray len(list(...))n = 16で計算すると、私のコンピュータは単純に死んでしまいます。そして、それは完全にランタイムを殺すでしょう。
ブース

ジェネレータをリストに変換すると多くのメモリが消費されるためです。
Ray
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.