Как чередовать 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"; "-"; "-"]