Computing a set of all subsets (power set)

前端 未结 2 1720
無奈伤痛
無奈伤痛 2021-01-24 17:11

I am trying to get a function (given as a parameter a set) to return a set whose elements are all the subset formed from the main set. Ex: {1;2;3} -> { {1}, {2}, {3}, {1,2}, {1,

相关标签:
2条回答
  • A set of all subsets is called a power set. To implement an algorithm you don't really need a special data structure, as you can represent a set with a list. Correspondingly a set of sets would be a list of lists. E.g.,

    let rec superset = function | [] -> [[]] | x :: xs -> let ps = superset xs in ps @ List.map (fun ss -> x :: ss) ps

    And here is an example of usage:

    superset [1;2;3];;
    - : int list list = [[]; [1]; [2]; [2; 1]; [3]; [3; 1]; [3; 2]; [3; 2; 1]
    

    If you want to use real sets, like Jeffrey suggested. Then we will need to adapt the algorithm a little bit, since Set module provides a little bit different interface.

    module S = Set.Make(String)
    module SS = Set.Make(S) let superset xs = S.fold (fun x ps -> SS.fold (fun ss -> SS.add (S.add x ss)) ps ps) xs (SS.singleton S.empty)

    To run the algorithm and to print the result we need to transform it back to a list, since OCaml toplevel doesn't know how to print sets:

    # superset (S.of_list ["1"; "2"; "3"]) |> SS.elements |> List.map S.elements;;
    - : S.elt list list =
    [[]; ["1"]; ["1"; "2"]; ["1"; "2"; "3"]; ["1"; "3"]; ["2"]; ["2"; "3"];
     ["3"]]
    

    Now, we can generalize algorithm, so that it will work on any ordered type.

    module Superset(T : Set.OrderedType) = struct module S = Set.Make(T)
    module SS = Set.Make(S) let of_set xs = S.fold (fun x ps -> SS.fold (fun ss -> SS.add (S.add x ss)) ps ps) xs (SS.singleton S.empty) end

    Now we can run it:

    # module Superset_of_strings = Superset(String);;
    # open Superset_of_string;;  
    # of_set (S.of_list ["1"; "2"; "3"]) |> SS.elements |> List.map S.elements;;
    - : S.elt list list =
    [[]; ["1"]; ["1"; "2"]; ["1"; "2"; "3"]; ["1"; "3"]; ["2"]; ["2"; "3"];
     ["3"]]
    
    0 讨论(0)
  • 2021-01-24 17:49

    If you want to use the standard Set module, you can work with sets of strings (say) and sets of sets of strings like this:

    # module S = Set.Make(String);;
    . . .
    # module SS = Set.Make(S);;
    . . .
    
    # let s1 = S.singleton "abc";;
    val s1 : S.t = <abstr>
    # let ss1 = SS.singleton s1;;
    val ss1 : SS.t = <abstr>
    # List.map S.elements (SS.elements ss1);;
    - : S.elt list list = [["abc"]]
    
    0 讨论(0)
提交回复
热议问题