サンプルをインデックスに変換する


12

ボールを固定数ビンに入れています。これらのビンは空で始まります。

Empty bin (a=4): 0 0 0 0 

そして、一つずつボールをビンに追加します。

0 0 0 1  or
0 0 1 0  or
0 1 0 0  or
1 0 0 0

ビンが取る可能性のあるすべての状態を、重複せずに見逃すことなくすばやくループする方法が必要です。すべての可能なビンを列挙する必要はありません。そのため、代わりに各ビン構成にインデックスを割り当てます。

可能な構成を特定の方法で並べ替えて、インデックスを割り当てます。

  1. 合計で昇順で並べ替え0 0 0 0ます。最初に、1つのボールが追加された可能性のある構成、次に2などがあります。
  2. 次に、各合計内で、最初のビンから最後まで昇順でソートします。

    0 0 0 2
    0 0 1 1
    0 0 2 0 
    0 1 0 1
    0 1 1 0 
    0 2 0 0 
    etc
    
  3. 次に、インデックスはこのリストを昇順で割り当てられます。

    0 0 0 0  -> 1
    0 0 0 1  -> 2
    0 0 1 0  -> 3
    0 1 0 0  -> 4
    1 0 0 0  -> 5
    0 0 0 2  -> 6
    0 0 1 1  -> 7
    0 0 2 0  -> 8
    0 1 0 1  -> 9
    0 1 1 0  -> 10
    0 2 0 0  -> 11 
    

ルール

任意のサイズのリストを負でない整数で受け取り、そのインデックスを出力または出力する関数またはプログラムを作成します。aは少なくとも2であると仮定できます。最短のコードが優先されます。0インデックス付き出力または1インデックス付き出力を使用できますが、使用するものを指定します。NB:ここでの例はすべて1から始まります。

サンプルコード

ゴルフではない、R:

nodetoindex <- function(node){
  a <- length(node)
  t <- sum(node)
  if(t == 0) return(1)

  index <- choose(t-1 + a, a)

  while(sum(node) != 0){
    x <- node[1]
    sumrest <- sum(node)
    if(x == 0){
      node <- node[-1]
      next
    }
    a <- length(node[-1])
    index <- index + choose(sumrest + a, a) - choose(sumrest - x + a, a)
    node <- node[-1]
  }
  return(index + 1)
} 

テストケース

10 10 10 10 -> 130571
3 1 4 1 5 9 -> 424407
2 9 -> 69
0 0 0 -> 1
0 0 1 -> 2
0 0 0 0 0 0 -> 1
1 0 0 0 0 1 -> 23

カウントの桁数が異なる場合、連結の数値によるソートはどのように機能しますか?
TheBikingViking

@TheBikingVikingうーん、それについては考えていなかったので、サンプルコードとテストケースを反映するように表現を変更しました。各合計内で、構成は最初のビンで最初にソートされ、次に2番目のビンでソートされます。
JAD

回答:


3

ゼリー、8バイト

S0rṗLSÞi

オンラインでお試しください!

ブルートフォースソリューション。最初のテストケースはTIOには多すぎますが、ラップトップでローカルに検証しました。2番目のテストケースでは、デスクトップコンピューターでもRAMが多すぎます。

使い方

S0rṗLSÞi  Main link. Argument: A (array)

S         Compute the sum s of A.
 0r       Create the range [0, ..., s].
    L     Yield the length l of A.
   ṗ      Cartesian power; yield the array of all l-tuples over [0, ..., s], in
          lexicographical order.
     SÞ   Sort the l-tuples by their sums. The sorting mechanism is stable, so
          l-tuples with the same sum are still ordered lexicographically.
       i  Find the index of A in the generated array of tuples.

いいね RAMについてのあなたの発言は、この課題の原因を思い起こさせました。私の論文では、いくつかのa = 8および可能な限り高いボールについて、可能なすべての配列をループする必要がありました。配列をインデックスに変換し、それらをループするだけのアイデアは、RAMの制限からきました:P
JAD

これも、サンプルコードが非常に冗長な理由です:P
JAD

1

Clojure、152バイト

#(loop[v[(vec(repeat(count %)0))]i 1](if-let[r((zipmap v(range))%)](+ r i)(recur(sort(set(for[v v i(range(count v))](update v i inc))))(+ i(count v)))))

思ったほど簡単ではありません。ゴルフの少ないバージョン:

(def f (fn[t](loop[v[(vec(repeat(count t)0))]i 1]
               (if-let[r((zipmap v(range))t)](+ r i)
                 (recur (sort-by (fn[v][(apply + v)v]) (set(for[v v i(range(count v))](update v i inc))))
                        (+ i(count v)))))))

現在の状態をループしv、要素からvランクまでのハッシュマップを作成します。検索された状態が見つかった場合、そのランクが返されます(+以前に表示された状態の数)。見つからない場合は、可能な状態の新しいセットで再帰します。

ああ、実際には、各ループ内のすべての状態の合計が同じであるため、カスタムの並べ替え関数は必要ありません。これは[3 1 4 1 5 9]2.6秒しかかからなかったので、思ったほど遅くありません。


1

Mathematica、50バイト

デニスのジェリー回答のポート。

0~Range~Tr@#~Tuples~Length@#~SortBy~Tr~Position~#&

入力として整数のリストを取り、出力として単一の整数を持つ深さ2のリストを返す名前のない関数。たとえば、最後のテストケースの入力はで{1,0,0,0,0,1}あり、出力は{{23}}です。

わずかに未使用のバージョンは次のとおりです。

Position[SortBy[Tuples[Range[0,Tr[#]],Length[#]],Tr],#]&

多くの場合、接頭辞表記(のfunction@n代わりにfunction[n])と中置表記(のa~function~b代わりにfunction[a,b])を使用して、Mathematicaの個々のバイトを保存できます。ただし、これは、結果のコードが関数を適用するためのMathematicaの固有の優先順位とうまく一致する場合にのみ機能します。ここで、6組の角かっこを使用して、実際に削除することに驚いたすべてし、(心地よいかっこなしの)送信されたコードで6バイトを節約驚かされました。

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