Как я вычисляю декартово произведение последовательностей n в F#?

Я подарился загадка. Это состоит из 4 кубов, расположенных рядом. Поверхности каждого куба являются одним из четырех цветов.

Для решения загадки кубы должны ориентироваться так, чтобы вершины всех четырех кубов отличались, все их передние стороны отличаются, все их спины отличаются, и вся их нижняя часть отличаются. Левые и правые стороны не имеют значения.

Мое решение псевдокода было:

  1. Создайте представление каждого куба.
  2. Получите все возможные ориентации каждого куба (существует 24 для каждого).
  3. Получите все возможные комбинации ориентаций каждого куба.
  4. Найдите комбинацию ориентаций, которая удовлетворяет решение.

Я решил загадку с помощью реализации того псевдокода в F#, но не являюсь satisifed со способом, которым я сделал шаг 3:

let problemSpace =
    seq { for c1 in cube1Orientations do
              for c2 in cube2Orientations do
                  for c3 in cube3Orientations do
                      for c4 in cube4Orientations do
                          yield [c1; c2; c3; c4] }

Вышеупомянутый код очень конкретен, и только разрабатывает декартово произведение четырех последовательностей ориентаций. Я начал думать о способе записать это для n последовательностей ориентаций.

Я придумал (весь код с этого времени должен выполниться прекрасный в интерактивном F#):

// Used to just print the contents of a list.
let print = 
    Seq.fold (fun s i -> s + i.ToString()) "" >> printfn "%s"

// Computes the product of two sequences - kind of; the 2nd argument is weird.
let product (seq1:'a seq) (seq2:'a seq seq) =
    seq { for item1 in seq1 do
              for item2 in seq2 do
                  yield item1 |> Seq.singleton |> Seq.append item2 }

Функция продукта могла использоваться как так...

seq { yield Seq.empty }
|> product [ 'a'; 'b'; 'c' ]
|> product [ 'd'; 'e'; 'f' ]
|> product [ 'h'; 'i'; 'j' ]
|> Seq.iter print

... которые приводят к...

let productn (s:seq<#seq<'a>>) =
    s |> Seq.fold (fun r s -> r |> product s) (seq { yield Seq.empty })

[ [ 'a'; 'b'; 'c' ]
  [ 'd'; 'e'; 'f' ]
  [ 'h'; 'i'; 'j' ] ]
|> productn
|> Seq.iter print

Это - точно использование, которое я хочу. productn имеет точно подпись, которую я хочу, и работает.

Однако использование продукта включает противную строку seq {приводят к Seq.empty}, и это неинтуитивно берет:

  1. Последовательность значений (seq <'a>)
  2. Последовательность последовательностей значений (seq <seq <'a>>)

Второй аргумент не кажется корректным.

Тот странный интерфейс скрыт приятно productn, но все еще ворчит меня независимо.

Есть ли какие-либо более хорошие, более интуитивные способы в общем вычислить декартово произведение последовательностей n? Там кто-либо создается в функциях (или комбинация), которые делают это?

12
задан Alex Humphrey 26 July 2010 в 11:37
поделиться

2 ответа

Используйте рекурсию: декартово произведение n списков {L1..LN} - это совокупность списков, которые вы получаете, когда добавляете каждый элемент в L1 в каждый подсписок в декартовом произведении списков {L2..LN}.

let rec cart1 LL = 
    match LL with
    | [] -> Seq.singleton []
    | L::Ls -> seq {for x in L do for xs in cart1 Ls -> x::xs}

Пример:

> cart1 [[1;2];[3;4;5];[6;7]] |> Seq.toList;;
val it : int list list =
  [[1; 3; 6]; [1; 3; 7]; [1; 4; 6]; [1; 4; 7]; [1; 5; 6]; [1; 5; 7]; [2; 3; 6];
   [2; 3; 7]; [2; 4; 6]; [2; 4; 7]; [2; 5; 6]; [2; 5; 7]]

Декартово произведение [1; 2] [3; 4; 5] и [6; 7] является объединением {1, добавленного к каждому списку в корзине [[3; 4; 5] ; [6; 7]]} и {2 добавлены к каждому списку в корзине [[3; 4; 5]; [6; 7]]}. Это второе предложение в операторе соответствия.

10
ответ дан 2 December 2019 в 22:03
поделиться

Вот первая попытка версии со списком. Думаю, это можно было бы немного поправить.

let rec cart nll = 
  let f0 n nll =
    match nll with
    | [] -> [[n]]
    | _ -> List.map (fun nl->n::nl) nll
  match nll with
  | [] -> []
  | h::t -> List.collect (fun n->f0 n (cart t)) h
0
ответ дан 2 December 2019 в 22:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: