Ăn trưa miễn phí


26

Tìm một chuỗi các lợi nhuận tối đa của các sàn giao dịch được đưa ra một bảng tỷ giá hối đoái.


Ví dụ, hãy xem xét các loại tiền A riary (tiền tệ tại nhà của bạn), B aht, C edi và D enar trong đó tỷ lệ từ loại này sang loại khác (sau khi bất kỳ tỷ lệ giao dịch nào được áp dụng) được đưa ra bởi mục (hàng, cột) bảng tỷ giá dưới đây:

                       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

Rõ ràng trao đổi A cho A không phải là một ý tưởng tuyệt vời vì bàn này sẽ vui vẻ tính phí cho bạn vì không làm gì cả.

Ít rõ ràng hơn, nhưng đúng với bảng này, đổi A lấy bất kỳ loại tiền nào khác và sau đó trao đổi lại là một công cụ thua lỗ:

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

Tuy nhiên, trao đổi A thành D rồi D sang B rồi B quay lại A lãi (được cung cấp đủ vốn để không chịu khuất phục):

0.709929 × 2.429757 × 0.579942 = 1.0003738278192194

Người ta có thể liên tục lấy "bữa trưa miễn phí" này trong khi cơ hội tồn tại.

Nhưng một chuỗi thậm chí còn hấp dẫn hơn tồn tại ở đây, cụ thể là A đến D rồi D đến C rồi C đến B và cuối cùng B trở lại A :

0.709929 × 6.409359 × 0.379962 × 0.579942 = 1.0026612752037345

Chi tiết thử thách

Với một bảng tỷ giá hối đoái trong bất kỳ định dạng hợp lý mà ấn định nghĩa của nhà tệ (ví dụ 1 st hàng và 1 st cột luôn là nhà tệ)
(hoặc cho như vậy một cái bàn và một số nhà tệ)
tìm thấy một * chuỗi chênh lệch tối đa của các trao đổi bắt đầu và kết thúc với tiền tệ gia đình khi các chỉ mục vào danh sách tiền tệ mà không lặp lại việc sử dụng bất kỳ trao đổi nào (ví dụ: trao đổi Y-> X có thể theo một X-> Y, nhưng X-> Y có thể không theo một X-> Y).

Nếu không có cơ hội sinh lời như vậy, sẽ mang lại một danh sách trống hoặc một số kết quả khác không thể nhầm lẫn với một cơ hội được xác định.
- ví dụ: ví dụ trên ( A-> D, D-> C, C-> B, B-> A ):

  • sử dụng chỉ mục 0 có thể trả về [[0,3],[3,2],[2,1],[1,0]]hoặc[0,3,2,1,0]
  • sử dụng chỉ mục 1 có thể trả về [[1,4],[4,3],[3,2],[2,1]]hoặc[1,4,3,2,1]

Các định dạng khác là tốt miễn là không có sự mơ hồ.
- Một điều cần chú ý là có thể có cơ hội tốt nhất để thực hiện một giao dịch duy nhất từ ​​nhà-> nhà (một bàn ngu ngốc). Nếu bạn quyết định loại trừ chỉ số tiền tệ gia đình từ cả hai đầu của tùy chọn căn hộ ở trên (tức là [3,2,1]hoặc [4,3,2]) và một danh sách trống cho "không có cơ hội" thì hãy đảm bảo rằng nhà-> nhà cũng không phải là một danh sách trống.

* Nếu nhiều cơ hội hợp lệ có lợi nhuận tương đương xảy ra, hãy trả lại bất kỳ trong số chúng, một số trong số chúng hoặc tất cả chúng.

Thuật toán Bellman-Ford là một cách để tiếp cận điều này, nhưng có lẽ không phải là cách phù hợp nhất cho golf.

Các trường hợp thử nghiệm

Các đầu vào được hiển thị theo cách sắp xếp được sử dụng trong ví dụ và kết quả được hiển thị sử dụng lập chỉ mục 0 để liệt kê các chỉ số tiền tệ (khi có cơ hội, tiền tệ chỉ ở cuối cuối; không có cơ hội nào là danh sách trống).

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

Đây là vì vậy giải pháp ngắn nhất về byte sẽ thắng, nhưng cạnh tranh cũng nên được thực hiện bằng ngôn ngữ nội bộ, vì vậy đừng để ngôn ngữ chơi gôn mã khiến bạn không thể gửi bài yêu thích!

Câu trả lời:


8

JavaScript (ES6), 122 113 103 byte

Đưa đầu vào dưới dạng ma trận chuyển vị đối với định dạng được mô tả trong thử thách. Trả về một chuỗi mô tả các trao đổi trong (from,to)định dạng.

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

Trường hợp thử nghiệm đầu tiên: Hãy thử trực tuyến!

Thêm trường hợp thử nghiệm: Hãy thử trực tuyến!

Đã bình luận

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 byte

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

Hãy thử trực tuyến!

Sử dụng lập chỉ mục dựa trên 0 (0 là tiền tệ gia đình); trả về một danh sách các bộ dữ liệu của các sàn giao dịch mang lại khoản thanh toán tối đa.

Cách tiếp cận là brute force: thông qua đệ quy, chúng tôi kết thúc quý khách đến thăm mỗi con đường phi cạnh lặp lại bắt đầu từ 0(ví nlà số tiền tệ, điều này mang lại tối đa chiều sâu của n^2). Đối với tập hợp con của những đường dẫn này cũng kết thúc bằng '0', chúng tôi tối đa hóa mức chi trả.


1

Haskell, 175 byte

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

Hãy thử nó ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.