Golf Bedava Bir Öğle Yemeği


26

Bir döviz kuru tablosu verilen maksimum kârlı döviz sırası bulun.


Örnek olarak, para birimlerini göz önünde bulundurun Bir İran (ev para biriminiz), B a , C edi ve D enar oranları, birinden diğerine (herhangi bir işlem oranı uygulandıktan sonra) girişin (satır, sütun) girişinde verilmiştir. aşağıdaki döviz kuru tablosu:

                       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

Açıkçası A ile A arasında alışveriş yapmak harika bir fikir değil, çünkü bu masa sizi hiçbir şey yapmadan mutlu bir şekilde şarj edecektir.

Daha az açıkçası, ancak bu tablo için doğrudur, A'yı başka bir para birimi ile takas etmek ve tekrar geri takas etmek, bir kayıp üreticisidir:

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

Ancak alışverişi A için D sonra D için B sonra B geri A'ya yapar (yuvarlama yenik değil verilen yeterli sermaye) kâr:

0.709929 × 2.429757 × 0.579942 = 1.0003738278192194

Fırsat varken kişi bu "bedava öğle yemeğini" tekrar tekrar alabilir.

Ancak daha da cazip zinciri, burada var olan yani bir üzere D daha sonra D için C daha sonra C için B ve son olarak oda geri A :

0.709929 × 6.409359 × 0.379962 × 0.579942 = 1.0026612752037345

Mücadele Detayları

(Örneğin 1 ev para anlamını giderir herhangi bir makul biçimde kur tablosu Verilen st satır ve 1 st sütunu her zaman ev para birimidir)
(veya böyle bir tablo ve bir ev-kur endeksi verilen)
bir bulmak * herhangi bir değişimin kullanımını tekrar etmeden döviz listesine endeks olarak ev para birimi ile başlayan ve biten borsaların azami arbitraj dizisi (yani, bir Y-> X değişimi bir X-> Y birini izleyebilir, ancak bir X-> Y olmayabilir bir X-> Y) izleyin.

Bu kadar karlı bir fırsat yoksa, boş bir liste veya belirlenmiş bir fırsatla karıştırılamayan başka bir sonuç verir.
- örneğin yukarıdaki örnek için ( A-> D, D-> C, C-> B, B-> A ):

  • 0 indeksleme birini kullanarak döndürebilir [[0,3],[3,2],[2,1],[1,0]]veya[0,3,2,1,0]
  • 1-indeksleme birini kullanarak döndürebilir [[1,4],[4,3],[3,2],[2,1]]veya[1,4,3,2,1]

Belirsizliğin olmadığı sürece diğer formatlar gayet iyi.
- Dikkat edilmesi gereken bir şey, evden tek bir işlem yapabilmek için en iyi fırsatın mümkün olduğudur. Ana para birimi endeksini yukarıdaki düz seçeneğin (yani [3,2,1]veya [4,3,2]) her iki ucundan ve "fırsat yok" için boş bir listeden hariç tutmaya karar verirseniz , ev-> evin de boş bir liste olmadığından emin olun.

* Birden fazla eşit derecede kârlı geçerli fırsat mevcutsa, bunlardan herhangi birini, bazılarını veya hepsini iade edin.

Bellman-Ford algoritması buna yaklaşmanın bir yoludur, ancak muhtemelen golf için en uygun yöntem değildir.

Test Kılıfları

Gösterilen girdiler, örnekte kullanılan düzenlemededir ve gösterilen sonuçlar, döviz endekslerini listelemek için 0 indekslemeyi kullanır (bir fırsat varsa, ev para birimi sadece sonda bulunur; hiçbir fırsat boş bir liste değildir).

[[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]

Bu bu nedenle baytlardaki en kısa çözüm kazanır, ancak rekabet dil içinde de yapılmalıdır, bu nedenle kod-golf dillerinin sizi en sevdiğiniz dilde göndermenize izin vermeyin!

Yanıtlar:


8

JavaScript (ES6), 122 113 103 bayt

Mücadelede açıklanan formata göre translasyon matrisi olarak girdi alır Değişimleri (from,to)biçiminde açıklayan bir dize döndürür .

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

İlk test durumu: Çevrimiçi deneyin!

Daha fazla test vakası: Çevrimiçi deneyin!

Yorumlananlar

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

Python 2 , 143 125 124 bayt

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])

Çevrimiçi deneyin!

0-tabanlı indeksleme kullanır (0, ev para birimidir); Maksimum ödemeyi sağlayan borsaların listesini gösterir.

Yaklaşım kaba kuvvet yineleme ile, en başlayan her olmayan kenar tekrar yolu ziyaret sonuna kadar 0(için npara sayısı olmak, bu maksimum verir derinliği arasında n^2). Bu yolların alt kümesi için '0' ile de biter, kazancı maksimize ederiz.


1

Haskell, 175 bayt

e?l|e`elem`l=0|2>1=1
w[]=[]
w l=[maximum l];0!q=[q]
n!c@(v,i,(h,l))=do{j<-[0..3];c:((n-1)!(v*l!!i!!j*(i,j)?h,j,((i,j):h,l)))}
z l=w$filter(\(v,e,_)->v>1&&e==0)$12!(1,0,([],l))

Burada dene

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.