Знайдіть максимально вигідну послідовність обмінів, задану таблицю обмінних курсів.
В якості прикладу розглянемо валюти riary (домашній валюти), Б АГТ, С EDI, і D ЕСПР де швидкість від одного до іншого (після будь-якої ставки угода була стягуються) задається (рядок, стовпець) записи в таблиця обмінних курсів нижче:
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 на будь-яку іншу валюту та повторний обмін назад - це збиток:
via B: 1.719828 × 0.579942 = 0.997400489976
via C: 4.509549 × 0.219978 = 0.992001569922
via D: 0.709929 × 1.39986 = 0.99380120994
Однак обмін A на D, потім D на B, потім B назад на A приносить прибуток (з урахуванням достатнього капіталу, щоб не піддатися округленню):
0.709929 × 2.429757 × 0.579942 = 1.0003738278192194
Можна було б неодноразово приймати цей "безкоштовний обід", поки є можливість.
Але тут існує ще більш привабливий ланцюг, а саме: A до D, потім D до C, потім C до B і, нарешті, B назад до A :
0.709929 × 6.409359 × 0.379962 × 0.579942 = 1.0026612752037345
Деталі виклику
З огляду на таблицю обмінних курсів у будь-якому розумному форматі, яка фіксує значення домашньої валюти (наприклад, 1- й рядок та 1- й стовпець завжди є домашньою валютою)
(або з урахуванням такої таблиці та індексу домашньої валюти)
знайдіть * максимальна арбітражна послідовність обмінів, що починається і закінчується домашньою валютою як індекси до списку валют, не повторюючи використання будь-якого обміну (тобто обмін Y-> X може слідувати X-> Y, але X-> Y не може дотримуйтесь X-> Y).
Якщо такої вигідної можливості немає, вийде порожній список або інший результат, який не можна переплутати з ідентифікованою можливістю.
- наприклад, для наведеного вище прикладу ( A-> D, D-> C, C-> B, B-> A ):
- за допомогою 0-індексації можна повернути
[[0,3],[3,2],[2,1],[1,0]]
або[0,3,2,1,0]
- за допомогою 1-індексації можна повернути
[[1,4],[4,3],[3,2],[2,1]]
або[1,4,3,2,1]
Інші формати прекрасні, доки немає двозначності.
- Одне, на що слід звернути увагу, це те, що найкращою можливістю є одна транзакція з дому-> додому (дурний стіл). Якщо ви вирішите скористатися виключенням індексу домашньої валюти з обох кінців плоскої опції вище (тобто [3,2,1]
або [4,3,2]
) та порожнього списку для "немає можливості", то переконайтесь, що home-> home також не є порожнім списком.
* Якщо трапляється кілька однаково вигідних дійсних можливостей, поверніть будь-яку з них, деякі з них або всі.
Алгоритм Беллмана-Форда - це один із способів наблизитись до цього, але, мабуть, не найкраще підходить для гольфу.
Випробування
Показані вхідні дані містяться в розташуванні, використаному в прикладі, а показані результати використовують 0-індексацію для перерахування індексів валюти (коли існує можливість, домашня валюта знаходиться лише в кінцевому кінці; немає можливості - порожній список).
[[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]
Це кодовий гольф, тому найкоротше рішення в байтах виграє, але конкуренція повинна бути також внутрішньомовною, так що не дозволяйте мовам кодового гольфу відкладати подання у вашому улюбленому!