2

えーと、

私は ocaml と CYK テーブルを通じて関数型プログラミングを学ぼうとしているので、 List.mem や命令型関数はありません。私の目的は、2 つのセルの製品を形成することです。

これが私が現在持っているものです:

let stringlister = function(mystring, newlist) ->
List.append newlist mystring;;

let rec append_func = function([listleft;listright], anslist, i, j) ->
if (j == (List.length listright)) then anslist
else begin
     append_func([listleft;listright], anslist, i, j + 1);
     List.append(anslist (stringlister((List.nth listright j), (stringlister( (List.nth listleft i), [])))))

   end;;

let rec prod_func = function([listleft;listright], anslist, i, j) ->
if (i == (List.length listleft)) then anslist
else begin
     prod_func([listleft;listright], anslist, i + 1, j);
     append_func([listleft;listright], anslist, i, j)
   end;;

let product = function[listleft;listright] ->
if (listleft == [] || listright == []) then []
else prod_func([listleft;listright], [], 0, 0);;

予想される出力は次のようになります。

#product[["A";"B"];["D","E","F","G"]];;
-: string list = ["AD"; "AE"; "AF"; "AG"; "BD"; "BE"; "BF"; "BG"]

#product[["A","B"];[]];;
-: string list = []

私の考えたプロセスは、基本的にリストをループして各文字列を別のリストの各文字列に配置する一連の再帰関数を作成することでした。

私のエラーは、特にappend_funcでの追加方法だと思います。より適切な質問は、文字列のリストを作成する方法かもしれないと思います。

4

3 に答える 3

1

私はOcamlを初めて使用するので、別の方法があるかもしれません

let rec flat_map f xs =
  match xs with
  | [] -> []
  | x :: xs -> List.append (f x) (flat_map f xs);;
val flat_map : ('a -> 'b list) -> 'a list -> 'b list = <fun>

let product lists =
  let rec loop acc lists =
    match lists with
    | [] -> [[]]
    | first :: [] -> first |> List.map (fun x -> x :: acc)
    | first :: rest -> first |> flat_map (fun x -> loop (x :: acc) rest)
  in
    loop [] lists;;
val product : 'a list list -> 'a list list = <fun>

product [["A"; "B"]; ["D"; "E"; "F"; "G"]]
- : string list list =
[["D"; "A"]; ["E"; "A"]; ["F"; "A"]; ["G"; "A"]; ["D"; "B"]; ["E"; "B"];
 ["F"; "B"]; ["G"; "B"]]

もちろん、どんな量の入力リストでも機能します

product [["1"; "2"; "3"]; ["A"; "B"; "C"; "D"]; ["+"; "-"]];;
- : string list list =
[["+"; "A"; "1"]; ["-"; "A"; "1"]; ["+"; "B"; "1"]; ["-"; "B"; "1"];
 ["+"; "C"; "1"]; ["-"; "C"; "1"]; ["+"; "D"; "1"]; ["-"; "D"; "1"];
 ["+"; "A"; "2"]; ["-"; "A"; "2"]; ["+"; "B"; "2"]; ["-"; "B"; "2"];
 ["+"; "C"; "2"]; ["-"; "C"; "2"]; ["+"; "D"; "2"]; ["-"; "D"; "2"];
 ["+"; "A"; "3"]; ["-"; "A"; "3"]; ["+"; "B"; "3"]; ["-"; "B"; "3"];
 ["+"; "C"; "3"]; ["-"; "C"; "3"]; ["+"; "D"; "3"]; ["-"; "D"; "3"]]

多分彼らは使用して少し良く読んでいますfunction

let rec flat_map f = function
  | [] -> []
  | x :: xs -> List.append (f x) (flat_map f xs)

let product lists =
  let rec loop acc = function
    | [] -> [[]]
    | first :: [] -> first |> List.map (fun x -> x :: acc)
    | first :: rest -> first |> flat_map (fun x -> loop (x :: acc) rest)
  in
    loop [] lists

別の角度から問題にアプローチすることもできます。出力の順序の違いに注意してください

let product lists =
  let rec loop acc = function
    | [] -> acc
    | first :: rest -> loop acc rest |> flat_map (fun c -> List.map (fun x -> x :: c) first)
  in
    loop [[]] lists;;
val product : 'a list list -> 'a list list = <fun>

product [["1"; "2"; "3"]; ["A"; "B"; "C"; "D"]; ["+"; "-"]];;
- : string list list =
[["1"; "A"; "+"]; ["2"; "A"; "+"]; ["3"; "A"; "+"]; ["1"; "B"; "+"];
 ["2"; "B"; "+"]; ["3"; "B"; "+"]; ["1"; "C"; "+"]; ["2"; "C"; "+"];
 ["3"; "C"; "+"]; ["1"; "D"; "+"]; ["2"; "D"; "+"]; ["3"; "D"; "+"];
 ["1"; "A"; "-"]; ["2"; "A"; "-"]; ["3"; "A"; "-"]; ["1"; "B"; "-"];
 ["2"; "B"; "-"]; ["3"; "B"; "-"]; ["1"; "C"; "-"]; ["2"; "C"; "-"];
 ["3"; "C"; "-"]; ["1"; "D"; "-"]; ["2"; "D"; "-"]; ["3"; "D"; "-"]]

上記は、リスト内の各要素に対してflat_map高価なを呼び出します。List.append以下のバリエーションでは、中間結果を収集してから、への 1 回の呼び出しで出力を構築します。List.concat

let flat_map f xs =
  let rec loop k = function
    | [] -> k []
    | x :: xs -> xs |> loop (fun r -> k (f x :: r))
  in
    loop List.concat xs;;
val flat_map : ('a -> 'b list) -> 'a list -> 'b list = <fun>
于 2018-04-07T23:54:00.647 に答える