コードゴルフ:ボールの配布(I)


12

チャレンジ

このタスクでは、すべてのセルが少なくとも1つのボールを持つ状態で、AのボールをBのセルに分配する方法の数を計算しました。

入力AとBは空白で区切られた1行で与えられ、入力はEOFで終了します。

こちらでソリューションを確認できます。

入力

0 0
1 0
12 4
6 3
18 17
20 19
15 13
18 9
20 20
17 14
9 2
14 13
18 11

出力

1
0
14676024
540
54420176498688000
23112569077678080000
28332944640000
38528927611574400
2432902008176640000
21785854970880000
510
566658892800
334942064711654400

制約

  • すべてのAとBは区別できます。
  • 0 <= A、B <= 20
  • 任意の言語を使用できます
  • 最短のソリューションが勝ちます!

1
時間制限はありますか?

@ティムノルデンファー:更新:-)
キクソティック

そのリンクは私には無効です。
mellamokb

3
@Debanjan SPOJからの質問をここに貼り付けるというアイデアは好きではありません。人々はそこで競​​争するためにコードを提出しますが、それは彼らにとって不公平です。
fR0DDY

1
@Debanjan、私はあなたのリファレンスを参照してください、あなたに上げMathworld(式を。5それは言ってS(n,0)いる1場合n=00そうでありません)。必要に応じて、Stirling2が指数関数型Riordanグループの関連サブグループにあるという強力なステートメントのリファレンスを見つけることができます。
ピーターテイラー

回答:


4

JavaScript(90 93

function f(a,b){n=m=r=1;for(i=b;i>0;n*=-1){r+=n*m*Math.pow(i,a);m=m*i/(b-i--+1)}return--r}

http://jsfiddle.net/RDGUn/2/

明らかに、APLなどの数学ベースの言語は、構文の冗長性と組み込みの数学的構造の欠如のために私を打ち負かすでしょう:)

編集また、関数に渡されるパラメーター以外の入力関連の機能はありません。JavaScriptで標準入力を使用する方法がわかりません...

編集:式に移動i--m=m*ます。に移動n*=-1forます。r=1割り当ての結合を開始し、戻り時に不要なものを削除します。(3文字保存)


spidermonkeyシェルを使用できます-少なくともとがreadlineありprintます。ここの他の人が何を使っているのか分かりません。
ジェシーミリカン

@ジェシー:興味深い。とにかく負けます
mellamokb

promptそしてalert、彼らはあなたが一般的にJavaScriptでブロッキングIOを使用したことがなかったという事実にもかかわらず、通話IO典型的なブロックしているとして、JavaScriptのの「標準」のIOです。
zzzzBov

4

Golfscript- 56 50 49 48 41 40 38 37 chars

n%{~),{!}%\{0.@{.@+2$*@)@}/;;]}*)p;}/

注:これは複数行の入力を処理し、高速(テストケースを実行するのに1/8秒)であり、正当な入力に対して中断しません。

(最初のバージョンは、私の最初のGolfscriptプログラムでもありました。見逃したいくつかのトリックを指摘してくれたeBusinessに感謝します)。

これを有益な教育記事にするために、その仕組みについて説明します。繰り返しから始めf(n, k) = k * (f(n-1, k) + f(n-1, k-1))ます。これは、場所にいることを言うようcombinatorically理解できるnで区別できるボールkの各バケットは、少なくとも1個のボールを含むように区別可能なバケツ、あなたはのいずれかの選択k(第1ボール用バケットk *)、その後、どちらかそれは(少なくとも1個の以上のボールが含まれていますf(n-1, k))またはそれは(f(n-1, k-1))しません。

この結果の値はグリッドを形成します。撮影n行インデックスとして、およびkそれが起動0から両方の列インデックスとインデックスとして

1   0   0   0    0    0   0 ...
0   1   0   0    0    0   0 ...
0   1   2   0    0    0   0 ...
0   1   6   6    0    0   0 ...
0   1  14  36   24    0   0 ...
0   1  30 150  240  120   0 ...
0   1  62 540 1560 1800 720 ...
.   .   .   .    .    .   . .
.   .   .   .    .    .   .  .
.   .   .   .    .    .   .   .

だからプログラムに目を向けて、

n%{~ <<STUFF>> }/

行に入力を分割し、各ライン評価するためには、パッティングnkスタックに、次に呼び出す<<STUFF>>以下の通りであります:

),{!}%\{0.@{.@+2$*@)@}/;;]}*)p;

これにより、そのグリッドのth行の最初のk+1エントリが計算されますn+1。最初のスタックはn kです。0 がある場所の
),スタックをn [0 1 2 ... k]
{!}%与えます。を最上部に移動し、実行回数にします。 現在、スタックはテーブルの行です。その配列の前にいくつかの0を置きます。最初のものはとなり、2番目のものはとなります。配列の要素をループします。それぞれについて、スタックの一番上に置き、ループ本体を実行します。取るためにスタック操作を退屈され、歩留まりのオフポップ左オーバーn [1 0 0 ... 0]k
\{ <<MORE STUFF>> }*n<<MORE STUFF>>
[f(i,0) f(i,1) ... f(i,k)]
0.@jf(i,j-1)
{ <<FINAL LOOP>> }/
.@+2$*@)@... j f(i,j-1) f(i,j)... j*(f(i,j-1)+f(i,j)) j+1 f(i,j)
;;]k+1 f(i,k)そして、すべてを配列に集めて、次のループの準備をします。
最後に、nテーブルのth行目を生成し
)p;たら、最後の要素を取得して印刷し、残りの行を破棄します。

後世のために、この原則に関する3つの38文字のソリューション:
n%{~),{!}%\{0.@{.@+@.@*\)@}/;;]}*)p;}/
n%{~),{!}%\{0:x\{x\:x+1$*\)}/;]}*)p;}/
n%{~),{!}%\{0.@{@1$+2$*\@)}/;;]}*)p;}/


1
初心者にはかなり良いです、いくつかの可能な小さな縮小があります、すぐに見つけます[0]-> 1,、zipの後のスペースは削除することができ、kの代わりに演算子に保存するだけであれば他のスペースを削除することができます。まだコードをステップ実行していませんが、いくつかのスポットの配列に値を入れずに、値を使用するだけで済むかもしれません。
aaaaaaaaaaaa

1
+1、私はGolfscriptを理解していませんが、これは十分に速く見えますが、非常に短いようです。
キクソティック

@eBusinessと@Peter Taylor:別のメモで..学習しやすい規模でGolfscriptをどの程度評価していますか?
キクソティック

@Debanjan、あなたが既に知っていることに依存します。機能的なスタックベースの言語です。以前に関数型言語を使用したことがあり(SML-OO言語で関数型コードを記述した)、以前にスタックベースの言語を使用した(JasminでアセンブルされたJavaバイトコード、PostScript)ため、唯一の本当の障害私が直面しているのは、どのオペレーターが利用できるかを学ぶことです。Algolファミリーの言語(C、Javaなど)しかわからない場合は、一度にジャンプする3つのハードルがあります。
ピーターテイラー

@Debanjan-見た目よりもはるかに簡単です。コードをほぼすぐに書き始めることができますが、もちろん、小さなコツをすべて学ぶには時間がかかります。
aaaaaaaaaaaa

3

J、40

4 :'|-/x(^~*y!~])i.1x+y'/&.".;._2(1!:1)3 

例えば

4 :'-/((x^~|.@:>:)*y&(!~))i.y'/x:".>{.;:(1!:1)3
15 13
28332944640000

すべてのテストケースで1秒未満。

編集

  • (52→47)で削減-/の代わりに、交互の(1 _1)*(JBのアイデアを)
  • (47→53)複数行の入力要件に気づいた:-/
  • (53→48)二項式の対称性を活用します。
  • (48→48)黙って!
  • (48→41)
  • (41→40)スクイーズ増分+変換1x+

1
おい!それが私のアイデアでした!O :-)
JB

わかりました、1x+それからそれを盗みます、しかし、それは私が1文字を買い戻すだけです、あなたが5を取りました!
JB

3

Common Lisp(83)

(defun b (x y)
  (if (= (* x y) 0)
      (if (= (+ x y) 0) 1 0)
      (* y (+ (b (decf x) y) (b x (1- y)))))))

基本ケースをテストするより短い方法があるはずですが、私には何も起こりません。


3

J、38〜42

インタラクティブ言語と出力プレゼンテーションに関する厳密な設定に応じて、Jスペクターのソリューションから選択してください。

  • 38最短インタラクティブ:4 :'|-/(!&y*^&x)i.1x+y'/&".;._2(1!:1)3
    jconsoleを起動して入力し、入力を貼り付けます(Cdで終わります)。出力はスペースで区切られています(Jはベクトル言語であり、入力全体に対して計算を実行し、1Dベクトルとして返します。デフォルトの表示は1行です)。わかりました。この問題の精神は、プレゼンテーションではなく計算です。ただし、代わりに改行を使用する場合:
  • 39インタラクティブが長くなりました:Compose()をUnder()に4 :'|-/(!&y*^&x)i.1x+y'/&.".;._2(1!:1)3
    置き換えると、文字列のベクトルが返され、その表示は別々の行になります。&&.
  • 42バッチモード:4 :'echo|-/(!&y*^&x)i.1x+y'/&".;._2(1!:1)3
    コマンドラインから次のように実行します$ jconsole balls.ijs < balls.in

これに賛成票を投じた場合は、Eelvexのソリューションにもクレジットを与えてください


&.インタラクティブモードで適切に動作するには、Underが必要です。
エルベックス

@Eelvexでは、「適切に」の異なる解釈が必要です。jconsoleを起動し、コードを貼り付け、入力、Cdを貼り付け、出力を受け取ります。必要ありません。君は?
JB

コードの組み合わせ:4 :'|-/(!&y*^&x)i.1x+y'/&.".;._2(1!:1)339文字。
エルベックス

エコーまたはアンダーなしでは、(複数行ではなく)1行のみで出力が得られます。
エルベックス

@Eelvexは確かですが、それは明示的に禁止されていません。
JB

3

GolfScript- 45 38 36文字

中程度のダーティな実装再帰関係(38 36文字):

n%{~{.2$*{\(.2$f\2$(f+*}{=}if}:f~p}/

私がピーター・テイラーのソリューションから盗んだ再帰関係は、次のようになります。

f(x, y) = y * ( f(x-1, y) + f(x-1, y-1) )

いずれかの変数が0の場合の特別な場合。

私の実装は以前の結果を再利用しないため、ゼロのケースの1つに到達しない限り、各関数呼び出しは2つの新しい呼び出しに分岐します。これは、私のマシンでは30秒かかる2 ^ 21-1関数呼び出しの最悪のケースになります。

Light-forceシリーズソリューション(45文字):

n%{~.),0\{.4$?3$,@[>.,,]{1\{)*}/}//*\-}/p;;}/

2

J、55文字

(wd@(4 :'(y^x)--/(!&y*^&x)|.i.y')/@".@,&'x');._2(1!:1)3
  • 現在のテストケースに合格します。私は数学を理解していると思う ...
  • j602、コンソールのみ(wd)。stdinの入力、stdoutの出力。

Bashテストスクリプト:

jconsole disballs.ijs <<END
12 4
6 3
END

そのj6xxは何をしwdますか?
JB

私は本当にj602を意味しました...私はそれがj601にもあると推測しています。として定義されecho、として定義され0 0&$@(1!:2&2)ます。私はそれが何を意味するのか分かりませんが、それは改行できれいに印刷されたランク1のアイテムのようなものをします。(今では4ではなく2を使用していることに気づきました。少なくともコンソールモードでは標準出力になると思います。)
ジェシーミリカン

このコードの実行に問題があります。コンソールに入力するだけですか?
mellamokb

@mellamokb上記のテストスクリプトのようなものを使用しました。プログラムはdisballs.ijsとして保存され、j602 / bin / jconsoleへの正しいパスが保存されています。
ジェシーミリカン

@ジェシー:私はこれをWindows上で実行しています。<< was unexpected at this time. J inputが初めてなので申し訳ありませんが、常にコンソールモードで使用していました。
mellamokb

2

Golfscript-26文字

警告:12 4の場合、多くのメモリが必要になります(ただし、以下の答えほどではありません)。実行にはかなり時間がかかります

~:)\?:x,{x+)base(;.&,)=},,

明らかにこの答えにはいくつかの問題がありますが、コメントはそれを参照しており、melamombの答えはそれに基づいているため、ここに残しておきます。

Golfscript-24文字

警告:12 4ケースは大量のメモリを必要とし、実行にはかなり時間がかかります

~:o)\?,{o)base[0]-,o=},,

2
このコードをどのように思いついたかはわかりませんが、このメソッドは大きな入力に対してメモリ不足になるだけでなく、インクリメント演算子が何に適しているのかもわかりません。あなたが実際に6 3で目標を達成したのは、運にほかならないようです。
aaaaaaaaaaaa

それは道化師ではなく、それは私の妻です!
ジェシーミリカン

2
Golfscriptを理解していませんが、あなたが言ったように、あなたのアプローチが遅すぎることに同意します。
キクソチック

3
@mellamokb、それがどのように機能するかを理解してくれてありがとう:)そのバグを修正するのに2つの余分な文字しか必要としませんでした。今、私たちは最も短いコードは正しいが実用的ではないかもしれない暗い領域にいます。Code-golfは非常に非効率的な答えに満ちていますが、通常、マイクロ秒と秒は関係ありません。これは極端なケースです(多くのメモリも)。Debanjanは回答をより速くする必要があることを示しましたが、このサイト SPOJではありません。この質問に code-golf
gnibbler

1
@gnibblerは、0 0生成する必要があり1ます。0 kその他のk場合は生成する必要があり0ます。n 1n > 0生成する必要があり1ます。
ピーターテイラー

2

Python 140文字

import sys
f=lambda n,k:(n and k and n>=k and k*(f(n-1,k-1)+f(n-1,k)))or(n+k==0 and 1)or 0
for l in sys.stdin:print f(*(map(int,l.split())))

2

dc、100文字

[0q]s5[1q]s6[l2l3>5l3 0>5l2 0=6l2 1-S2l3dS3 1-S3l1xL3s9l1xL2s9+L3*]s1[?z0=5S3S2l1xL3L2+s9fs9l4x]ds4x

残念ながら、dcはideoneによってサポートされていないようです。絞り出すキャラクターがまだ1人か2人いるかもしれませんが、それは就寝時間です。

注:これは複数行の入力をサポートし、20 19(呪い、Perl、私のソリューションをデバッグするのに無駄になった時間のために)正しい出力を提供するのに十分な精度を持ち、の正しい出力を提供します0 0

Nabbからの提案により、少なくともできるだけ短くすることができます。

[0q]sZ[1q]sI[?z0=ZSkSn[lnlk>Zlk0>Zln0=Iln1-SnlkdSk1-SklFxLks9lFxLns9+Lk*]dsFxfs9l4x]ds4x

ジャンクをレジスタスタックに残すというコストで(したがって、数十億の答えを計算するとメモリ不足になります)。


レジスタは常に単一の文字です(コードを読みやすくするために任意の文字を使用できます)l11として解析されl1 1ます(とにかく精度を変更しない場合のK単一文字トークンとして使用できます0)。入力ループをに変更できます?[...?z1=4]。registerでマクロをインライン化できます1。そして、おそらくより多くのキャラクターをヒープに保存することができますが、理解できるようにそれが短くなるのを待ちます。
ナブ

@Nabb、ああ、私はマニュアルページを十分に注意深く読みませんでした。私は8個または9個のレジスタのみを使用しているため、誤解の結果に遭遇することはありませんでした。ありがとう。
ピーターテイラー

1

Golfscript(28 31 37

~):$\.($\?:@;?,{@+}%{$base$,\-[0]=},,

gnibblerのGolfScriptソリューションの変更。これは実用的なソリューションだと思います-[3,2]、[4,2]、[6,3]、および[9,2]で正解をテストしました。(私は$@変数を使用して、baseキーワードの周りのスペースを絞りました)。

gnibbler現在のソリューションには2つの問題があります。

  1. [0]を削除した後に長さをチェックしても、4つのボールがすべて同じセル(1)にあるにもかかわらず、[1,1,1,1]が入力[4,2]に対して有効になるため、解を保証しません。そのため、すべての数字が使用されていることも確認するように変更しました。つまり、配列に1-2が含まれているため、各セルに少なくとも1つのボールが含まれています。
  2. 入力[4,2]の場合、0〜27の基数3の形式は4桁未満で、左端の0は含まれません。つまり、技術的には実際には[0,0,1,1]ですが、[1,1]は有効なソリューションとして含まれています。つまり、最初の2つのボールはどこにも配置されていません。すべてのエントリに3 ^ 3を追加して(通常はk ^ nエントリの配列にk ^ n-1を追加)、最初のエントリがベースk形式で少なくともn桁、最後にとにかくエントリは自動的に無効になり、ソリューションに影響しません(2桁目は常に0になるため)。

編集

~:@\?:$,{$+}%{@base(;@,\-,0=},,

`~:@\?:$,{$+@base(;@,\-,0=},,`

まだ良い解決策!インクリメントする必要はありません。すべての数字に加算して[1]で始まるようにします。最初の数字を削除すると、数字(0の左詰めを含む)が失われません。このソリューションは動作するはずであり、上記と同じエントリでテストされています。また、配列を生成するために指数を取得する前にインクリメントしないため、はるかに高速です(ただし、大きな入力に対して同じパフォーマンス/メモリの問題が発生します)。

編集:追加のステップとしてではなく、フィルター内部のgnibbler追加を移動するというアイデアを使用し$ます。(3文字保存)。


入力で中断します0 0
ピーターテイラー

入力の1行のみを処理するようにも見えます。
ピーターテイラー

そしてn 1、任意のnでブレークすると、ハングします。うーん
。– mellamokb

1
数値を基数1に変換すると、それが行われます:)
ニブラー

@gnibbler:何か提案はありますか?これらのケースをキャッチするために、最初にifステートメントをいくつか挿入するだけですか?私はそのように多くの地面を失うように思えます。
mellamokb

0

05AB1E、19 バイト

#D`ULX.Œʒ€gßĀ}gs_P+

注:それは非常に遅く、すでにタイムアウトし12 4ます。ただし、意図したとおりに機能しています。妥当な時間内にすべてのテストケースで機能する代替方法を思いつくことができるかどうかを確認します。1秒未満ですべてのテストケースを実行するはるかに高速なバージョンについては、以下を参照してください。

オンライン試してみようか、テストケース(小さい方の)いくつかのより多くのを確認

説明:

#               # Split the (implicit) input-string by spaces
 D              # Duplicate it
  `             # Push both values to the stack
   U            # Pop and store the second value in variable `X`
    L           # Create a list in the range [1,n] for the first value
     X        # Create a list of all possible ways to divide this list into `X` partitions
                # (including empty sublists, so we'll have to filter them out:)
        ʒ       # Filter this list of lists of partition-lists by:
         g     #  Get the length of each partition-list
           ß    #  Get the minimum length
            Ā   #  Truthify; 0 remains 0 (falsey); anything else becomes 1 (truthy)
             }g # After the filter, take the length to get the amount left
 s              # Swap so the duplicated input-list is at the top of the stack again
  _             # Check for each value if they're equal to 0 (1 if truthy; 0 if falsey)
   P            # Take the product of the two to check if both input-values are 0
    +           # And add it to the earlier calculated product (edge case for [0,0] = 1)
                # (After which the result is output implicitly)

05AB1E、29 バイト

ここでは、TIOで約0.5秒ですべてのテストケースで動作するはるかに高速なバージョンがあります。

Î#R`V©LRvyYmX*NÈ·<*+Xy*®y->÷U

@mellamokbのJavaScript回答のポートなので、必ず彼に賛成してください!

オンラインそれを試してみたり、すべてのテストケースを確認してください

説明:

Î                    # Push (result=) 0 and the input
 #                   # Split the input by spaces
  R`                 # Push the values to the stack reversed
    V                # Pop and store the first value in variable `Y`
     ©               # Store the second value in variable `®` (without popping)
      LRv            # Loop `y` in the range [`®`,1], with index `N` in the range [0,`®`):
         yYm         #  Calculate `y` to the power `Y`
            X*       #  Multiply it by `X`
                     #  (Note: `X` is 1 before setting it to another value initially)
              NÈ     #  Check if index `N` is even (1 if truthy; 0 if falsey)
                ·<   #  Double it; and decrease it by 1 (1 if truthy; -1 if falseY0
                  *  #  Multiply it to the earlier number
                   + #  And add it to the result
         Xy*         #  Push `X` multiplied by `y`
         ®y->        #  Push `®` - `y` + 1
             ÷       #  Integer divide them
              U      #  Pop and store it as new variable `X`
                     # (output the result at the top of the stack implicitly after the loop)

注:0 0このケースではエッジケースで動作します(このメソッドを移植したJavaScriptの回答とは異なります)。これは、Lビルトインがリストを作成するため[0,1]です。

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