Reputation: 13
I'm tasked with creating a list of m word portmanteaus with n letter overlap from a given list of words.
For example, a 2 word 2 letter overlap portmanteau would be: "collegenetics" made from "college" and "genetics". A 3 word 2 letter overlap could be "firegaluminum" made of "fire", "regal" and "aluminum".
I have written a function singleport with this syntax:
let singleport word1 word2 n =
match suffix word1 n = prefix word2 n with
| false -> "No Port"
| true -> word1 ^ (prefixless word2 n)
which identifies whether or not two words could be portmanteaus. However, I'm struggling to identify a way to run this recursively in order to compare two elements of a list, all while constructing a new list that records all the possible portmantaus.
I figured List.fold_left could be used because of the use of the accumulator, but I don't know how to implement it and I would greatly appreciate any advice. Thank you very much!
Upvotes: 0
Views: 1400
Reputation: 35210
One of the approaches to attack this task is to split it into small understandable subtasks, and then try to merge them. This is the deductive approach.
Applying the deductive method to your task, we can split it in the following way:
To create a list of pairs, you need to write the following function:
(** [pair_list xs] given the list [xs], produces a list of consecutive pairs.
Fails with an invalid argument, if the list has odd length. *)
val pair_list : 'a list -> ('a * 'a) list
With such a function, you can use map
to transform each pair to a list of portmanteau, mapping a pair to an empty list, if it is impossible. E.g., given this function:
val portmanteau : (string * string) -> string list
And now we can join everything with List.concat
:
let portmanteau_of_list xs =
List.map portmanteau (pair_list xs) |> List.concat
Another approach is to move from the opposite direction, i.e., not from top to down, but from the bottom. So inductive reasoning about this task would be the following:
The same in OCaml (untested):
let rec portmanteau_of_list = function
| [] -> []
| [_] -> failwith "odd list"
| x :: y :: xs -> match portmanteau x y with
| None -> portmanteau_of_list xs
| Some p -> p :: portmanteau_of_list xs
Upvotes: 2