Winnable Solitaire Mancalaボード


10

マンカラは、通常、プレーヤーが操作するビーズで満たされた一連のカップを含むボードゲームのファミリーの名前です。このチャレンジでは、ゲームのソリティアバリアントに特定のルールセットを使用します。

ボードは、1つの端にある「バスケット」と、それに続く1から始まる無数のカップで構成されています。一部のカップには、いくつかのビーズが含まれています。場合n番目のカップを正確に持っているnことでビーズを、あなたはそれからビーズ「種をまく」ことがあります。播種とは、すべてのnビーズをカップから取り出し、各カップに1つずつバスケットに向かって堆積させることを意味します。最後のビーズがバスケットに入ります。ボード上のすべてのビーズがバスケットに入ったときにプレーヤーが勝利します。

明らかに、2番目のカップにビードが1つしかない場合など、勝てないボードがたくさんあります。ビーズが0個のカップはすべて播種できず、2番目のカップには播種するのに十分なビーズがないため、合法的なプレーはありません。これは明らかに面白くないので、あなたの仕事は勝てるボードを作ることです。

仕事

ビーズの数を表す正の整数が出力されると、上記のように勝てるボードを作るために各カップに入れる必要のあるビーズの数を表す非負の整数のリストが出力されます。このリストには、末尾にゼロを含めないでください。

任意の数のビーズに対して、常に1つの勝利可能なボード構成があります。

デモンストレーション

これは、4の入力と勝者のボードをプレイする方法のデモです[0, 1, 3]。勝者のボードはです。利用可能な唯一の動きから始めて、3番目のカップからビーズを播種します[1, 2, 0]。今、私たちは実際に選択肢を持っていますが、唯一正しいのは最初のカップを播種して、を取得することです[0, 2, 0]。次に、2番目のカップを降伏させ[1, 0, 0]、最後に最初のカップを再び播種して、すべての空のカップを取得します。

テストケース:

1 => [1]
2 => [0, 2]
3 => [1, 2]
4 => [0, 1, 3]
5 => [1, 1, 3]
6 => [0, 0, 2, 4]
7 => [1, 0, 2, 4]
8 => [0, 2, 2, 4]
9 => [1, 2, 2, 4]
10 => [0, 1, 1, 3, 5]
11 => [1, 1, 1, 3, 5]
12 => [0, 0, 0, 2, 4, 6]
13 => [1, 0, 0, 2, 4, 6]
14 => [0, 2, 0, 2, 4, 6]
15 => [1, 2, 0, 2, 4, 6]
16 => [0, 1, 3, 2, 4, 6]
17 => [1, 1, 3, 2, 4, 6]
18 => [0, 0, 2, 1, 3, 5, 7]
19 => [1, 0, 2, 1, 3, 5, 7]
20 => [0, 2, 2, 1, 3, 5, 7]

テストケースを生成するプログラムを作成してくれたPeterTaylorに感謝します。


回答:


5

CJam(21バイト)

M{_0+0#_Wa*\)+.+}ri*`

オンラインデモ

説明

私はこの論文で言及されている「アンプレイ」テクニックを独自に導きました。誘導によって、与えられた数のビーズに対してちょうど1つの勝利ボードがあることを証明します。

基本ケース:ビーズが0の場合、勝つボードは空のボードのみです。

誘導ステップ:カップから播種するkと、次の移動時にカップkは空になり、バスケットに近いすべてのカップには少なくとも1つのビーズが含まれます。したがって、最も番号の小さい空のカップを探し、バスケットから1つのビーズとその空のカップの下にある各カップから1つのビーズを取り、それらをすべて空のカップに入れることによりnn-1ビーズ付きの勝利ボードからユニークなビーズ付き勝利ボードを見つけることができます。

解剖

M           e# Start with an empty board
{           e# Loop
  _0+0#     e#   Find position of first 0 (appending to ensure that there is one)
  _Wa*      e#   Make array of that many [-1]s
  \)+       e#   Append the index plus 1 (since board is 1-indexed)
  .+        e#   Pointwise addition
}
ri*         e# Read integer from stdin and execute loop that many times
`           e# Format for display

9

Python、42 41バイト

m=lambda n,i=2:n*[1]and[n%i]+m(n-n%i,i+1)

4

JavaScript(ES6)、63 37バイト

f=(n,d=2)=>n?[n%d,...f(n-n%d,d+1)]:[]

@orlpのPython回答のポート。説明:i番目のカップ以上のビーズの総数を考慮してください。これらのカップの1つからプレイするたびにi、その合計からビーズが削除されます。(たとえば、iが3で、5番目のカップからプレイする場合、そのカップのビーズの数を5つ減らしますが、4番目と3番目のカップの両方に1を追加します。)したがって、合計は倍数でなければなりません。のi。これで、i-1th番目のカップには1 iつ以上のビーズを含めることができないため、複数のビーズを残すためにiは、残りのビーズをモジュロで含める必要がありますi

以前の説明(@xnorのリンクから):素朴なアプローチは「逆再生」手法です。これは、プレーを行うとカップが空になるという観察を使用しているため、逆再生では各カップからビーズが収集され、最初の空のカップに入れられます(63バイト)。

f=n=>n?[...a=f(n-1),0].some((m,i)=>(m?a[i]--:a[i]=i+1)>m)&&a:[]

では、最初のiカップについて考えてみましょう。それらの1つが空の場合、逆再生は1それらのカップのビーズの総数に追加されますが、それらのいずれも空でない場合、逆再生はi合計から差し引かれますが、これは1モジュロを追加することと同等ですi+1。したがってn、逆再生後、最初のiカップのビーズの合計はnmodulo i+1に等しくなるか、言い換えると、ithカップのビーズの数はn、前のカップのビーズの合計からmodulo を差し引いたものに等しくなりますi+1。これで、ithカップが再生可能になるため、ビーズの数はを超えることはできませんi。そのため、実際には、残りのビーズのモジュロ数と等しくなります。i+1。(使用するd=i+1バイト数が少ないため、使用することに注意してください。)


@orlpのソリューションを使用してバージョンに関数を割り当てるのを忘れて、再帰が機能しないようにしました。その解決策についても、配列の連結+はES6のものではありませんか?
Value Ink

@KevinLauおっと、それもバイト数に含める問題に行った後!ただし、両方のパラメーターが数値またはブール値である場合を除き、+は文字列連結です。幸いなことに、配列内包は任意の連結を容易にします。
Neilは

2

Ruby、36バイト

@orlpの答えのポート。なぜなら、私が何か良いことを考えるのはあまりにも天才だからです。

m=->n,i=2{n>0?[n%i]+m[n-n%i,i+1]:[]}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.