Я пытаюсь перечислить набор всех пар из элементов из двух ленивых списков (первый элемент из первого списка, второй элемент из второго списка) в OCaml, используя обычный идея диагонализации. Идея заключается в том, что в строгих оценочных терминах что-то вродеПеречисление всех пар из двух ленивых списков в OCaml
enum [0;1;2;...] [0;1;2;...] = [(0,0);(0,1);(1;0);(0;2);(1;1);(2;2);...]
Мой вопрос: как вы это определяете?
Я объясню, что я думал до сих пор, возможно, это будет полезно для тех, кто пытается ответить на это. Но если вы уже знаете ответ, вам не нужно читать дальше. Возможно, я ошибаюсь.
Я определил ленивые списки, как
type 'a node_t =
| Nil
| Cons of 'a *'a t
and 'a t = ('a node_t) Lazy.t
Тогда я определил функцию «Последовательность»
let seq m =
let rec seq_ n m max acc =
if n=max+1
then acc
else (seq_ (n+1) (m-1) max (lazy (Cons((n,m),acc))))
in seq_ 0 m m (lazy Nil)
, который дает мне ленивым список пар (х, у) такой, что х + у = т. Это и есть диагональная идея. Начнем с перечисления всех пар, сумма которых 0, то все те, сумма которых 1, то те, сумма которых 2 и т.д.
Тогда я определил функцию «» enum_pair
let enum_pair() =
let rec enum_pair_ n = lazy (Cons(seq n,enum_pair_ (n+1)))
in enum_pair_ 0
, который генерирует бесконечное ленивым Список состоит из: ленивого списка пар, которые суммируют 0, объединяются с ленивыми списками пар, которые суммируют 1 и т. д.
Теперь мне кажется, что я почти там. Проблема в следующем: Как я могу получить фактические пары по одному?
Мне кажется, что мне придется использовать некоторую форму конкатенации списка (ленивый эквивалент @). Но это не эффективно, потому что в моем представлении ленивых списков объединение двух списков имеет сложность O (n^2), где n - размер первого списка. Должен ли я пойти на разные представления ленивых списков? Или есть другой способ (не используя «seq» и «enum_pair» выше), который не требует конкатенации списка?
Любая помощь была бы действительно оценена.
Большое спасибо, Сурикатор.
Спасибо, Дэниэл, это очень полезно. Можете ли вы обобщить это, чтобы заставить его работать с n ленивыми списками (т. Е. Выбрать все n-кортежи, которые можно выбрать из n списков)? Благодаря! – Surikator
Создание k-кортежей для k> 2 не так просто. Я думаю, что это сводится к созданию комбинаций с повторением k элементов из n возможных, когда вы хотите k-мерную диагональ с элементами, которые суммируются с n. –