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

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

Например:

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

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

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

person Adrien Aacha    schedule 29.10.2017    source источник
comment
Я предлагаю вам быть более гибкими в том, какие учебники вы просматриваете :-) Почти любой учебник, который объясняет, как написать простую рекурсивную функцию, будет применим к вашей проблеме. После того, как вы написали код, вы можете вернуться к StackOverflow с более конкретным вопросом.   -  person Jeffrey Scofield    schedule 30.10.2017


Ответы (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
person glennsl    schedule 30.10.2017

Я бы предложил попробовать с двумя списками, а затем перейти на 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"; "-"; "-"]                    
person keep_learning    schedule 30.10.2017