Assuming that "the (n-1) subsets of S" means { S\{x} | x ∈ S }, the set of subsets of S where one element has been removed for each element of S, you can trivially generate the least common multiple of each of those by first generating the sets and then applying the least common multiple algorithm to each subset.
Here's a shorter way to generate the least common multiple:
fun gcd (a, 0) = a
| gcd (a, b) = gcd (b, a mod b)
fun lcm (a, b) = (a * b) div (gcd (a, b))
val lcm_list = foldl lcm 1
The function lcm_list
corresponds to your function ekp
.
To get a list of subsets where one element is removed from each (assuming no duplicates):
fun curry f x y = f (x, y)
fun subsets1 [] = []
| subsets1 (x::xs) = xs :: map (curry op:: x) (subsets1 xs)
And to generate the least common multiple of each of those subsets,
- subsets1 [3,4,5];
> val it = [[4, 5], [3, 5], [3, 4]] : int list list
- map lcm_list (subsets1 [3,4,5]);
> val it = [20, 15, 12] : int list
That is, the (n-1) subsets of {3,4,5} is found to be { {4,5}, {3,5}, {3,4} }, and the least common multiple of each of those (n-1) subsets is { lcm(4, 5), lcm(3, 5), lcm(3, 4) } = { 20, 15, 12 }. At this point, some redundant work may have been carried out. For any larger list, the set of subsets will have a large amount of overlap. For example,
- subsets1 [3,4,5,6,7,8];
> val it =
[ [4, 5, 6, 7, 8],
[3, 5, 6, 7, 8],
[3, 4, 6, 7, 8],
[3, 4, 5, 7, 8],
[3, 4, 5, 6, 8],
[3, 4, 5, 6, 7] ] : int list list
Using the method above, we would calculate lcm (3, 4)
= 12 four times, lcm (12, 5)
= 60 three times, etc. You may benefit from a speed-up by applying memoization to the lcm
function, although it isn't terribly expensive.