Как чередовать 3 списка в OCaml

Я пытаюсь взять три списка строк и заставить код возвращать список, чередующий три. Если списки имеют неравные размеры, тогда мы используем "-", чтобы указать, что значение отсутствует.

Например:

interleave3 ["1"; "2"; "3"] ["4"] ["5"; "6"]

должен вернуть:

["1"; "4"; "5"; "2"; "-"; "6"; "3"; "-"; "-"]

2 ответа

Решение

Если бы задача состояла в том, чтобы просто чередовать элементы, пока все списки не были бы пустыми, это было бы довольно просто; просто вращайте списки, добавляя по одному элементу за раз, пока все они не станут пустыми.

let rec interleave3 xs ys zs =
  match xs, ys, zs with
  | [], [], [] -> []
  | [], ys, zs -> "-" :: interleave3 ys zs []
  | x::xs, ys, zs -> x :: interleave3 ys zs xs

Однако, поскольку требуется, чтобы каждый список был эффективно дополнен до равной длины, нам нужно каким-то образом отслеживать, какой длины самый длинный список, и продолжать заполнять результирующий список до тех пор, пока сам список не будет дополнен. Один из способов сделать это состоит в том, чтобы сохранить общее количество и продолжать работу даже после того, как мы закончим, пока общее число не будет делиться на 3, и в этот момент мы знаем, что итоговый список имеет равное количество элементов:

let interleave3 xs ys zs =
  let rec aux xs ys zs n =
    match xs, ys, zs with
    | [], [], [] when n mod 3 = 0 -> []
    | [], [], []    -> "-" :: aux [] [] [] (n+1)
    | [], ys, zs    -> "-" :: aux ys zs [] (n+1)
    | x::xs, ys, zs ->   x :: aux ys zs xs (n+1)
  in aux xs ys zs 0

Я бы предложил попробовать с двумя списками, а затем вы идете на 3 или более списков. Как только вы поймете шаблон для двоих, вы сможете расширить ту же концепцию для большего количества списков. Я написал быстрое решение, но я не утверждаю, что это идиоматический OCaml. Также список в OCaml разделен точкой с запятой.

let rec patternMatching xs ys zs = 
        match xs, ys, zs with
        | [], [], [] -> []
        | x::xs, [], [] -> x :: "-" :: "-" :: patternMatching xs [] []
        | [], y::ys, [] -> "-" :: y :: "-" :: patternMatching [] ys []
        | [], [], z::zs -> "-" :: "-" :: z :: patternMatching [] [] zs
        | x::xs, y::ys, [] -> x :: y :: "-" :: patternMatching xs ys []
        | x::xs, [], z::zs -> x :: "-" :: z :: patternMatching xs [] zs
        | [], y::ys, z::zs -> "-" :: y :: z :: patternMatching [] ys zs
        | x::xs, y::ys, z::zs -> x :: y :: z :: patternMatching xs ys zs



       # patternMatching  ["1"; "2"; "3"] ["4"] ["5"; "6"];;
- : string list = ["1"; "4"; "5"; "2"; "-"; "6"; "3"; "-"; "-"]                    
Другие вопросы по тегам