ゴルフ無料ランチ


26

為替レート表を指定して、最大の利益をもたらす一連の交換を見つけます。


例として、通貨考えるriary(ホーム通貨)、Bの AHT、Cの EDI、およびDのいずれかから別の速度は(任意のトランザクションレートが課された後)に(行、列)エントリによって与えられるenarを以下の為替レート表:

                       TO
       A          B          C          D

   A   0.9999     1.719828   4.509549   0.709929

F  B   0.579942   0.9999     2.619738   0.409959
R
O  C   0.219978   0.379962   0.9999     0.149985
M
   D   1.39986    2.429757   6.409359   0.9999

明らかにAAに交換することは、このデスクが何もしないことで喜んで請求するので、素晴らしいアイデアではありません。

それほど明らかではありませんが、このテーブルでは、Aを他の通貨と交換してから再び交換することは損失メーカーです。

via B: 1.719828 × 0.579942 = 0.997400489976
via C: 4.509549 × 0.219978 = 0.992001569922
via D: 0.709929 × 1.39986  = 0.99380120994

しかし、交換AD次いでDをするBは、その後Bへ戻るAは ない利益(丸めないように屈するの十分な資金を与えられました)。

0.709929 × 2.429757 × 0.579942 = 1.0003738278192194

機会があれば、この「無料のランチ」を繰り返し取ることができます。

しかし、さらに魅力的なチェーン、つまりAからDDからCCからB、最後にBからAが存在します。

0.709929 × 6.409359 × 0.379962 × 0.579942 = 1.0026612752037345

チャレンジの詳細

ホーム通貨の意味を修正する任意の合理的な形式で為替レートテーブルを考えると(例えば、1 番目の行と1 番目の列は、常に家庭の通貨です)
(または、そのようなテーブルや家庭通貨インデックスを与えられる)
を見つけます*取引所の最大の裁定シーケンスの開始および自国通貨で終わる通貨リストにインデックスとして任意の交換の使用を繰り返すことなく(すなわち、A Y-> X交換はX-> Y 1に従うことができるが、X-> YはないかもしれませんX-> Yに従ってください)。

そのような有益な機会が存在しない場合、空のリストが生成されるか、特定された機会と混同しない他の結果が得られます。
-たとえば、上記の例(A-> D、D-> C、C-> B、B-> A):

  • 0インデックスを使用すると、1が返される[[0,3],[3,2],[2,1],[1,0]]か、[0,3,2,1,0]
  • 1インデックスを使用すると、1が返される[[1,4],[4,3],[3,2],[2,1]]か、[1,4,3,2,1]

あいまいさがない限り、他の形式でも問題ありません。
-気を付けなければならないことの1つは、home-> home(愚かな机)からの単一のトランザクションになる最良の機会が可能であるということです。上記のフラットオプションの両端から自国通貨インデックス(つまり[3,2,1]または[4,3,2])を除外し、「機会なし」の空のリストを除外する場合は、home-> homeも空のリストではないことを確認してください。

*複数の同等の利益のある有効な機会が存在する場合、それらのいずれか、一部、またはすべてを返します。

Bellman-Fordアルゴリズムはこれにアプローチする1つの方法ですが、おそらくゴルフには最適ではありません。

テストケース

示されている入力は、例で使用されている配置であり、示されている結果は、0インデックスを使用してto-currency-indiceをリストしています(機会が存在する場合、自国通貨はトレーリングエンドにのみあり、機会は空のリストではありません)。

[[0.999900, 1.719828, 4.509549, 0.709929],
 [0.579942, 0.999900, 2.619738, 0.409959],
 [0.219978, 0.379962, 0.999900, 0.149985],
 [1.399860, 2.429757, 6.409359, 0.999900]]  ->  [3, 2, 1, 0]

[[0.9999, 1.5645, 0.9048, 1.0929],
 [0.6382, 0.9999, 0.5790, 0.6998],
 [1.1051, 1.7269, 0.9999, 1.2087],
 [0.9131, 1.4288, 0.8262, 0.9999]]  ->  [1, 2, 0]

[[0.9999, 1.4288, 0.8262, 0.9131],
 [0.6998, 0.9999, 0.5790, 0.6382],
 [1.2087, 1.7269, 0.9999, 1.1051],
 [1.0929, 1.5645, 0.9048, 0.9999]]  ->  [1, 2, 3, 1, 0]

[[1.002662, 1.719828, 4.509549, 0.709929],
 [0.579942, 0.999900, 2.619738, 0.409959],
 [0.219978, 0.379962, 0.999900, 0.149985],
 [1.399860, 2.429757, 6.409359, 0.999900]]  ->  [3, 2, 1, 0, 0]

[[1.002662, 1.719828, 4.509549, 0.709929],
 [0.579942, 1.002604, 2.619738, 0.409959],
 [0.219978, 0.379962, 1.003000, 0.149985],
 [1.399860, 2.429757, 6.409359, 1.002244]]  ->  [3, 3, 2, 2, 1, 1, 0, 0]

[[0.9999, 1.4288, 0.8262, 0.9131],
 [0.6998, 0.9999, 0.5790, 0.6382],
 [1.2087, 1.7269, 1.0001, 1.1051],
 [1.0929, 1.4974, 0.9048, 0.9999]]  ->  [1, 2, 2, 0]

[[0.9999, 1.3262, 0.7262, 0.9131],
 [0.6998, 0.9999, 0.5490, 0.6382],
 [1.2087, 1.7269, 0.9999, 1.2051],
 [1.0929, 1.5645, 0.9048, 0.9999]]  ->  [3, 2, 3, 1, 0]

[[0.9999, 1.5645, 0.9048, 0.5790],
 [0.6382, 0.9999, 0.5790, 0.3585],
 [1.1051, 1.7269, 0.9999, 0.6391],
 [1.7271, 2.6992, 1.5645, 0.9999]]  ->  [1, 2, 0]  and/or  [3, 2, 0]

[[0.9999, 1.2645, 0.7048, 0.3790],
 [0.4382, 0.9999, 0.3790, 0.1585],
 [1.0001, 1.5269, 1.0001, 0.4391],
 [1.5271, 2.4992, 1.3645, 0.9999]]  ->  []

[[0.9999, 1.2645, 0.7048, 0.3790],
 [0.4382, 0.9999, 0.3790, 0.1585],
 [0.9999, 1.5269, 1.4190, 0.4391],
 [1.5271, 2.4992, 1.3645, 0.9999]]  ->  [2, 2, 0]

これはので、バイト単位の最短のソリューションが勝ちますが、競争も言語内で行う必要があります。そのため、コードゴルフ言語でお気に入りの投稿を遅らせないでください。

回答:


8

JavaScript(ES6)、122 113 103バイト

チャレンジで説明されている形式に関して、転置行列として入力を受け取ります。(from,to)形式で交換を説明する文字列を返します。

a=>(g=(s,x=b=0,h='')=>a.map((r,y)=>~h.search(k=`(${x},${y})`)||g(s*r[x],y,h+k),x|s<b||(b=s,p=h)))(1)&&p

最初のテストケース:オンラインで試してみてください!

その他のテストケース:オンラインでお試しください!

コメント済み

a => (                  // given the exchange rate matrix a[][]
  g = (                 // g = recursive function taking:
    s,                  //   s = current amount of money
    x = b = 0,          //   x = ID of current currency, b = best result so far
    h = ''              //   h = exchange history, as a string
  ) =>                  //  
  a.map((r, y) =>       // for each row at position y in a[]:
    ~h.search(          //   if we can't find in h ...
      k = `(${x},${y})` //     ... the exchange key k from currency x to currency y
    ) ||                //   then:
    g(                  //   do a recursive call to g() with:
      s * r[x],         //     s = new amount obtained by applying the exchange rate
      y,                //     x = y
      h + k             //     h = h + k
    ),                  //   end of recursive call
    x | s < b ||        //   if x is our home currency and s is greater than or equal to b
    (b = s, p = h)      //   then set b to s and set p to h
  )                     // end of map()
)(1)                    // initial call to g() with s = 1
&& p                    // return p

4

パイソン2143の 125 124バイト

lambda M:g(M)[1]
g=lambda M,s=[],p=1,x=0:max([(p,s)]*-~-x+[g(M,s+[(x,y)],p*M[x][y],y)for y in range(len(M))if(x,y)not in s])

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

0から始まるインデックスを使用します(0は自国通貨です)。最大ペイアウトをもたらす取引所のタプルのリストを返します。

アプローチはブルートフォースです。再帰を介して、0n通貨の数であるため、最大の深さを与えるn^2)で始まるすべての非エッジ繰り返しパスを訪問することになります。「0」で終わるこれらのパスのサブセットについては、ペイオフを最大化します。


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