Предположим, вы работаете на языке с массивами переменной длины (например, с A[i]
для всех i
в 1..A.length
) и должны написать процедуру, которая принимает n
(n : 1..8
) массивов элементов переменной длины в массиве переменной длины длиной n
и требует для вызова процедуры со всеми возможными длинами n
массивов элементов, где первый выбирается из первого массива, второй выбирается из второго массива и так далее.
Если вы хотите визуализировать что-то конкретное, представьте, что ваша процедура должна принимать такие данные, как:
[ [ 'top hat', 'bowler', 'derby' ], [ 'bow tie', 'cravat', 'ascot', 'bolo'] ... ['jackboots','galoshes','sneakers','slippers']]
и сделайте следующие вызовы процедур (в любом порядке):
try_on ['top hat', 'bow tie', ... 'jackboots']
try_on ['top hat', 'bow tie', ... 'galoshes']
:
try_on ['derby','bolo',...'slippers']
Это иногда называют проблемой китайского меню, и для фиксированного n
можно довольно просто закодировать (например, для n
= 3 в псевдокоде)
procedure register_combination( items : array [1..3] of vararray of An_item)
for each i1 from items[1]
for each i2 from items[2]
for each i3 from items[3]
register( [ii,i2,i3] )
Но что, если n
может варьироваться, давая подпись типа:
procedure register_combination( items : vararray of vararray of An_item)
Написанный код содержал уродливый оператор case, который я заменил гораздо более простым решением. Но я не уверен, что это лучший (и, конечно, не единственный) способ реорганизовать это.
Как бы вы это сделали? Умный и неожиданный — это хорошо, но понятный и удобный в сопровождении — еще лучше — я просто просматриваю этот код и не хочу, чтобы мне перезвонили. Краткий, ясный и умный текст был бы идеален.
Изменить: сегодня я опубликую свое решение позже, после того как другие смогут ответить.
Тизер: я пытался продать рекурсивное решение, но они не пошли на это, поэтому мне пришлось придерживаться написания фортрана на HLL.
Ответ, с которым я пошел, размещен ниже.