0

I have the following functions to calculate the LCM of all elements from a list. Are there any hints for calculating every LCM of each (n-1) subsets and store them in a list instead?

fun modulo (_,0) = 0
  | modulo (0,_) = 0
  | modulo (x,y) = if y > x then x else
    let
      fun getMod(z) = if z >= y then getMod(z-y) else z
    in
      getMod(x)
    end

fun lcm (0,_) = 0
  | lcm (_,0) = 0
  | lcm (x,y) = 
    let
      fun findLcm (base,mult,v) =
          if modulo(mult,v) = 0
          then mult
          else findLcm(base,mult+base,v)
    in
      if x > y then findLcm(x,x,y) else findLcm(y,y,x)
    end

fun ekp(xs) =
    case xs of
         []       => 1
       | (x::xs') => lcm(x,ekp(xs'))
sshine
  • 15,635
  • 1
  • 41
  • 66

1 Answers1

1

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.

sshine
  • 15,635
  • 1
  • 41
  • 66