(*------------------------------------------------------------------*)

#define ATS_DYNLOADFLAG 0

#include "share/atspre_staload.hats"

(*------------------------------------------------------------------*)
(* String hashing using XXH3_64bits from the xxHash suite.          *)

#define ATS_EXTERN_PREFIX "hashsets_postiats_"

%{^ /* Embedded C code. */

#include <xxhash.h>

ATSinline() atstype_uint64
hashsets_postiats_mem_hash (atstype_ptr data, atstype_size len)
{
  return (atstype_uint64) XXH3_64bits (data, len);
}

%}

extern fn mem_hash : (ptr, size_t) -<> uint64 = "mac#%"

fn
string_hash (s : string) :<> uint64 =
  let
    val len = string_length s
  in
    mem_hash ($UNSAFE.cast{ptr} s, len)
  end

(*------------------------------------------------------------------*)
(* A trimmed down version of the AVL trees from the AVL Tree task.  *)

datatype bal_t =
| bal_minus1
| bal_zero
| bal_plus1

datatype avl_t (key_t  : [email protected]+,
                data_t : [email protected]+,
                size   : int) =
| avl_t_nil (key_t, data_t, 0)
| {size_L, size_R : nat}
  avl_t_cons (key_t, data_t, size_L + size_R + 1) of
    (key_t, data_t, bal_t,
     avl_t (key_t, data_t, size_L),
     avl_t (key_t, data_t, size_R))
typedef avl_t (key_t  : [email protected]+,
               data_t : [email protected]+) =
  [size : int] avl_t (key_t, data_t, size)

extern fun {key_t : [email protected]}
avl_t$compare (u : key_t, v : key_t) :<> int

#define NIL avl_t_nil ()
#define CONS avl_t_cons
#define LNIL list_nil ()
#define :: list_cons
#define F false
#define T true

typedef fixbal_t = bool

prfn
lemma_avl_t_param {key_t : [email protected]} {data_t : [email protected]} {size : int}
                  (avl : avl_t (key_t, data_t, size)) :<prf>
    [0 <= size] void =
  case+ avl of NIL => () | CONS _ => ()

fn {}
minus_neg_bal (bal : bal_t) :<> bal_t =
  case+ bal of
  | bal_minus1 () => bal_plus1
  | _ => bal_zero ()

fn {}
minus_pos_bal (bal : bal_t) :<> bal_t =
  case+ bal of
  | bal_plus1 () => bal_minus1
  | _ => bal_zero ()

fn
avl_t_is_empty {key_t : [email protected]} {data_t : [email protected]} {size   : int}
               (avl : avl_t (key_t, data_t, size)) :<>
    [b : bool | b == (size == 0)] bool b =
  case+ avl of
  | NIL => T
  | CONS _ => F

fn
avl_t_isnot_empty {key_t : [email protected]} {data_t : [email protected]} {size   : int}
                  (avl : avl_t (key_t, data_t, size)) :<>
    [b : bool | b == (size <> 0)] bool b =
  ~avl_t_is_empty avl

fn {key_t : [email protected]} {data_t : [email protected]}
avl_t_search_ref {size  : int}
                 (avl   : avl_t (key_t, data_t, size),
                  key   : key_t,
                  data  : &data_t? >> opt (data_t, found),
                  found : &bool? >> bool found) :<!wrt>
    #[found : bool] void =
  let
    fun
    search (p     : avl_t (key_t, data_t),
            data  : &data_t? >> opt (data_t, found),
            found : &bool? >> bool found) :<!wrt,!ntm>
        #[found : bool] void =
      case+ p of
      | NIL =>
        {
          prval _ = opt_none {data_t} data
          val _ = found := F
        }
      | CONS (k, d, _, left, right) =>
        begin
          case+ avl_t$compare<key_t> (key, k) of
          | cmp when cmp < 0 => search (left, data, found)
          | cmp when cmp > 0 => search (right, data, found)
          | _ =>
            {
              val _ = data := d
              prval _ = opt_some {data_t} data
              val _ = found := T
            }
        end
  in
    $effmask_ntm search (avl, data, found)
  end

fn {key_t : [email protected]} {data_t : [email protected]}
avl_t_search_opt {size : int}
                 (avl  : avl_t (key_t, data_t, size),
                  key  : key_t) :<>
    Option (data_t) =
  let
    var data : data_t?
    var found : bool?
    val _ = $effmask_wrt avl_t_search_ref (avl, key, data, found)
  in
    if found then
      let
        prval _ = opt_unsome data
      in
        Some {data_t} data
      end
    else
      let
        prval _ = opt_unnone data
      in
        None {data_t} ()
      end
  end

fn {key_t : [email protected]} {data_t : [email protected]}
avl_t_insert_or_replace {size : int}
                        (avl  : avl_t (key_t, data_t, size),
                         key  : key_t,
                         data : data_t) :<>
    [sz : pos] (avl_t (key_t, data_t, sz), bool) =
  let
    fun
    search {size   : nat}
           (p      : avl_t (key_t, data_t, size),
            fixbal : fixbal_t,
            found  : bool) :<!ntm>
        [sz : pos]
        (avl_t (key_t, data_t, sz), fixbal_t, bool) =
      case+ p of
      | NIL => (CONS (key, data, bal_zero, NIL, NIL), T, F)
      | CONS (k, d, bal, left, right) =>
        case+ avl_t$compare<key_t> (key, k) of
        | cmp when cmp < 0 =>
          let
            val (p1, fixbal, found) = search (left, fixbal, found)
          in
            case+ (fixbal, bal) of
            | (F, _) => (CONS (k, d, bal, p1, right), F, found)
            | (T, bal_plus1 ()) =>
              (CONS (k, d, bal_zero (), p1, right), F, found)
            | (T, bal_zero ()) =>
              (CONS (k, d, bal_minus1 (), p1, right), fixbal, found)
            | (T, bal_minus1 ()) =>
              let
                val+ CONS (k1, d1, bal1, left1, right1) = p1
              in
                case+ bal1 of
                | bal_minus1 () =>
                  let
                    val q = CONS (k, d, bal_zero (), right1, right)
                    val q1 = CONS (k1, d1, bal_zero (), left1, q)
                  in
                    (q1, F, found)
                  end
                | _ =>
                  let
                    val p2 = right1
                    val- CONS (k2, d2, bal2, left2, right2) = p2
                    val q = CONS (k, d, minus_neg_bal bal2,
                                  right2, right)
                    val q1 = CONS (k1, d1, minus_pos_bal bal2,
                                   left1, left2)
                    val q2 = CONS (k2, d2, bal_zero (), q1, q)
                  in
                    (q2, F, found)
                  end
              end
          end
        | cmp when cmp > 0 =>
          let
            val (p1, fixbal, found) = search (right, fixbal, found)
          in
            case+ (fixbal, bal) of
            | (F, _) => (CONS (k, d, bal, left, p1), F, found)
            | (T, bal_minus1 ()) =>
              (CONS (k, d, bal_zero (), left, p1), F, found)
            | (T, bal_zero ()) =>
              (CONS (k, d, bal_plus1 (), left, p1), fixbal, found)
            | (T, bal_plus1 ()) =>
              let
                val+ CONS (k1, d1, bal1, left1, right1) = p1
              in
                case+ bal1 of
                | bal_plus1 () =>
                  let
                    val q = CONS (k, d, bal_zero (), left, left1)
                    val q1 = CONS (k1, d1, bal_zero (), q, right1)
                  in
                    (q1, F, found)
                  end
                | _ =>
                  let
                    val p2 = left1
                    val- CONS (k2, d2, bal2, left2, right2) = p2
                    val q = CONS (k, d, minus_pos_bal bal2,
                                  left, left2)
                    val q1 = CONS (k1, d1, minus_neg_bal bal2,
                                   right2, right1)
                    val q2 = CONS (k2, d2, bal_zero (), q, q1)
                  in
                    (q2, F, found)
                  end
              end
          end
        | _ => (CONS (key, data, bal, left, right), F, T)
  in
    if avl_t_is_empty avl then
      (CONS (key, data, bal_zero, NIL, NIL), F)
    else
      let
        prval _ = lemma_avl_t_param avl
        val (avl, _, found) = $effmask_ntm search (avl, F, F)
      in
        (avl, found)
      end
  end

fn {key_t : [email protected]} {data_t : [email protected]}
avl_t_insert {size : int}
             (avl  : avl_t (key_t, data_t, size),
              key  : key_t,
              data : data_t) :<>
    [sz : pos] avl_t (key_t, data_t, sz) =
  (avl_t_insert_or_replace<key_t><data_t> (avl, key, data)).0

fun {key_t : [email protected]} {data_t : [email protected]}
push_all_the_way_left (stack : List (avl_t (key_t, data_t)),
                       p     : avl_t (key_t, data_t)) :
    List0 (avl_t (key_t, data_t)) =
  let
    prval _ = lemma_list_param stack
  in
    case+ p of
    | NIL => stack
    | CONS (_, _, _, left, _) =>
      push_all_the_way_left (p :: stack, left)
  end

fun {key_t : [email protected]} {data_t : [email protected]}
update_generator_stack (stack     : List (avl_t (key_t, data_t)),
                        right     : avl_t (key_t, data_t)) :
    List0 (avl_t (key_t, data_t)) =
  let
    prval _ = lemma_list_param stack
  in
    if avl_t_is_empty right then
      stack
    else
      push_all_the_way_left<key_t><data_t> (stack, right)
  end

fn {key_t : [email protected]} {data_t : [email protected]}
avl_t_make_data_generator {size : int}
                          (avl  : avl_t (key_t, data_t, size)) :
    () -<cloref1> Option data_t =
  let
    typedef avl_t = avl_t (key_t, data_t)

    val stack = push_all_the_way_left<key_t><data_t> (LNIL, avl)
    val stack_ref = ref stack

    (* Cast stack_ref to its (otherwise untyped) pointer, so it can be
       enclosed within ‘generate’. *)
    val p_stack_ref = $UNSAFE.castvwtp0{ptr} stack_ref

    fun
    generate () :<cloref1> Option data_t =
      let
        (* Restore the type information for stack_ref. *)
        val stack_ref =
          $UNSAFE.castvwtp0{ref (List avl_t)} p_stack_ref

        var stack : List0 avl_t = !stack_ref
        var retval : Option data_t
      in
        begin
          case+ stack of
          | LNIL => retval := None ()
          | p :: tail =>
            let
              val- CONS (_, d, _, left, right) = p
            in
              retval := Some d;
              stack :=
                update_generator_stack<key_t><data_t> (tail, right)
            end
        end;
        !stack_ref := stack;
        retval
      end
  in
    generate
  end

(*------------------------------------------------------------------*)
(* Sets implemented with a hash function, AVL trees and association *)
(* lists.                                                           *)

(* The interface  - - - - - - - - - - - - - - - - - - - - - - - - - *)

(* For simplicity, let us support only 64-bit hashes. *)

typedef hashset_t (key_t : [email protected]+) =
  avl_t (uint64, List1 key_t)

extern fun {key_t : [email protected]}  (* Implement a hash function with this. *)
hashset_t$hashfunc : key_t -<> uint64

extern fun {key_t : [email protected]}     (* Implement key equality with this. *)
hashset_t$key_eq : (key_t, key_t) -<> bool

extern fun
hashset_t_nil :
  {key_t : [email protected]}
  () -<> hashset_t key_t

extern fun {key_t : [email protected]}
hashset_t_add_member :
  (hashset_t key_t, key_t) -<> hashset_t key_t

(*
"remove_member" is not implemented here, because the trimmed down AVL
tree implementation above does not include deletion. We shall
implement everything else without using a member deletion routine.

extern fun {key_t : [email protected]}
hashset_t_remove_member :
  (hashset_t key_t, key_t) -<> hashset_t key_t

Of course you can remove a member by using hashset_t_difference.
*)

extern fun {key_t : [email protected]}
hashset_t_has_member :
  (hashset_t key_t, key_t) -<> bool

typedef hashset_t_binary_operation (key_t : [email protected]) =
  (hashset_t key_t, hashset_t key_t) -> hashset_t key_t

extern fun {key_t : [email protected]}
hashset_t_union : hashset_t_binary_operation key_t

extern fun {key_t : [email protected]}
hashset_t_intersection : hashset_t_binary_operation key_t

extern fun {key_t : [email protected]}
hashset_t_difference : hashset_t_binary_operation key_t

extern fun {key_t : [email protected]}
hashset_t_subset :
  (hashset_t key_t, hashset_t key_t) -> bool

extern fun {key_t : [email protected]}
hashset_t_equal :
  (hashset_t key_t, hashset_t key_t) -> bool

(* Note: generators for hashset_t produce their output in unspecified
         order. *)
extern fun {key_t : [email protected]}
hashset_t_make_generator :
  hashset_t key_t -> () -<cloref1> Option key_t

(* The implementation - - - - - - - - - - - - - - - - - - - - - - - *)

(* I make no promises that these are the most efficient
   implementations I could devise. They certainly are not! But they
   were easy to write and will work. *)

implement
hashset_t_nil () =
  avl_t_nil ()

fun {key_t  : [email protected]}
find_key {n : nat} .<n>.
         (lst : list (key_t, n),
          key : key_t) :<>
    List0 key_t =
  (* This implementation is tail recursive. It will not build up the
     stack. *)
  case+ lst of
  | list_nil () => lst
  | list_cons (head, tail) =>
    if hashset_t$key_eq<key_t> (key, head) then
      lst
    else
      find_key (tail, key)

implement {key_t}
hashset_t_add_member (set, key) =
  (* The following implementation assumes equal keys are
     interchangeable. *)
  let
    implement
    avl_t$compare<uint64> (u, v) =
      if u < v then ~1 else if v < u then 1 else 0
    typedef lst_t = List1 key_t
    val hash = hashset_t$hashfunc<key_t> key
    val lst_opt = avl_t_search_opt<uint64><lst_t> (set, hash)
  in
    case+ lst_opt of
    | Some lst =>
      begin
        case+ find_key<key_t> (lst, key) of
        | list_cons _ => set
        | list_nil () =>
          avl_t_insert<uint64><lst_t>
            (set, hash, list_cons (key, lst))
      end
    | None () =>
      avl_t_insert<uint64><lst_t>
        (set, hash, list_cons (key, list_nil ()))
  end

implement {key_t}
hashset_t_has_member (set, key) =
  let
    implement
    avl_t$compare<uint64> (u, v) =
      if u < v then ~1 else if v < u then 1 else 0
    typedef lst_t = List1 key_t
    val hash = hashset_t$hashfunc<key_t> key
    val lst_opt = avl_t_search_opt<uint64><lst_t> (set, hash)
  in
    case+ lst_opt of
    | None () => false
    | Some lst =>
      begin
        case+ find_key<key_t> (lst, key) of
        | list_nil () => false
        | list_cons _ => true
      end
  end

implement {key_t}
hashset_t_union (u, v) =
  let
    val gen_u = hashset_t_make_generator<key_t> u
    val gen_v = hashset_t_make_generator<key_t> v
    var w : hashset_t key_t = hashset_t_nil ()
    var k_opt : Option key_t
  in
    for (k_opt := gen_u (); option_is_some k_opt; k_opt := gen_u ())
      w := hashset_t_add_member (w, option_unsome k_opt);
    for (k_opt := gen_v (); option_is_some k_opt; k_opt := gen_v ())
      w := hashset_t_add_member (w, option_unsome k_opt);
    w
  end

implement {key_t}
hashset_t_intersection (u, v) =
  let
    val gen_u = hashset_t_make_generator<key_t> u
    var w : hashset_t key_t = hashset_t_nil ()
    var k_opt : Option key_t
  in
    for (k_opt := gen_u (); option_is_some k_opt; k_opt := gen_u ())
      let
        val+ Some k = k_opt
      in
        if hashset_t_has_member<key_t> (v, k) then
          w := hashset_t_add_member (w, k)
      end;
    w
  end

implement {key_t}
hashset_t_difference (u, v) =
  let
    val gen_u = hashset_t_make_generator<key_t> u
    var w : hashset_t key_t = hashset_t_nil ()
    var k_opt : Option key_t
  in
    for (k_opt := gen_u (); option_is_some k_opt; k_opt := gen_u ())
      let
        val+ Some k = k_opt
      in
        if ~hashset_t_has_member<key_t> (v, k) then
          w := hashset_t_add_member (w, k)
      end;
    w
  end

implement {key_t}
hashset_t_subset (u, v) =
  let
    val gen_u = hashset_t_make_generator<key_t> u
    var subset : bool = true
    var done : bool = false
  in
    while (~done)
      case+ gen_u () of
      | None () => done := true
      | Some k =>
        if ~hashset_t_has_member<key_t> (v, k) then
          begin
            subset := false;
            done := true
          end;
    subset
  end

implement {key_t}
hashset_t_equal (u, v) =
  hashset_t_subset<key_t> (u, v)
    && hashset_t_subset<key_t> (v, u)

implement {key_t}
hashset_t_make_generator (set) =
  let
    typedef lst_t = List1 key_t
    typedef lst_t_0 = List0 key_t

    val avl_gen = avl_t_make_data_generator<uint64><lst_t> (set)

    val current_list_ref : ref lst_t_0 = ref (list_nil ())
    val current_list_ptr =
      $UNSAFE.castvwtp0{ptr} current_list_ref
  in
    lam () =>
      let
        val current_list_ref =
          $UNSAFE.castvwtp0{ref lst_t_0} current_list_ptr
      in
        case+ !current_list_ref of
        | list_nil () =>
          begin
            case+ avl_gen () of
            | None () => None ()
            | Some lst =>
              begin
                case+ lst of
                | list_cons (head, tail) =>
                  begin
                    !current_list_ref := tail;
                    Some head
                  end
              end
          end
        | list_cons (head, tail) =>
          begin
            !current_list_ref := tail;
            Some head
          end
      end
  end

(*------------------------------------------------------------------*)

implement
hashset_t$hashfunc<string> (s) =
  string_hash s

implement
hashset_t$key_eq<string> (s, t) =
  s = t

typedef strset_t = hashset_t string

fn {}
strset_t_nil () :<> strset_t =
  hashset_t_nil ()

fn
strset_t_add_member (set    : strset_t,
                     member : string) :<> strset_t =
  hashset_t_add_member<string> (set, member)

fn {}
strset_t_member_add (member : string,
                     set    : strset_t) :<> strset_t =
  strset_t_add_member (set, member)

#define SNIL strset_t_nil ()
infixr ( :: ) ++        (* Right associative, same precedence as :: *)
overload ++ with strset_t_member_add

fn
strset_t_has_member (set    : strset_t,
                     member : string) :<> bool =
  hashset_t_has_member<string> (set, member)
overload [] with strset_t_has_member

fn
strset_t_union (u : strset_t, v : strset_t) : strset_t =
  hashset_t_union<string> (u, v)
overload + with strset_t_union

fn
strset_t_intersection (u : strset_t, v : strset_t) : strset_t =
  hashset_t_intersection<string> (u, v)
infixl ( + ) ^
overload ^ with strset_t_intersection

fn
strset_t_difference (u : strset_t, v : strset_t) : strset_t =
  hashset_t_difference<string> (u, v)
overload - with strset_t_difference

fn
strset_t_subset (u : strset_t, v : strset_t) : bool =
  hashset_t_subset<string> (u, v)
overload <= with strset_t_subset

fn
strset_t_equal (u : strset_t, v : strset_t) : bool =
  hashset_t_equal<string> (u, v)
overload = with strset_t_equal

fn
strset_t_make_generator (set : strset_t) :
    () -<cloref1> Option string =
  hashset_t_make_generator<string> set

fn
strset_t_print (set : strset_t) : void =
  let
    val gen = strset_t_make_generator set
    var s_opt : Option string
    var separator : string = ""
  in
    print! ("#<strset_t ");
    for (s_opt := gen (); option_is_some s_opt; s_opt := gen ())
      case+ s_opt of
      | Some s =>
        begin
          (* The following quick and dirty implemenetation does not
             insert escape sequences. *)
          print! (separator, "\"", s, "\"");
          separator := " "
        end;
    print! (">")
  end

implement
main0 () =
  let
    val set1 =
      "one" ++ "two" ++ "three" ++ "guide" ++ "design" ++ SNIL
    val set2 =
      "ett" ++ "två" ++ "tre" ++ "guide" ++ "design" ++ SNIL
  in
    print! ("set1 = ");
    strset_t_print set1;

    println! ();
    println! ();
    println! ("set1[\"one\"] = ", set1["one"]);
    println! ("set1[\"two\"] = ", set1["two"]);
    println! ("set1[\"three\"] = ", set1["three"]);
    println! ("set1[\"four\"] = ", set1["four"]);

    println! ();
    print! ("set2 = ");
    strset_t_print set2;

    println! ();
    println! ();
    println! ("set2[\"ett\"] = ", set2["ett"]);
    println! ("set2[\"två\"] = ", set2["två"]);
    println! ("set2[\"tre\"] = ", set2["tre"]);
    println! ("set2[\"fyra\"] = ", set2["fyra"]);

    println! ();
    print! ("Union\nset1 + set2 = ");
    strset_t_print (set1 + set2);
    println! ();

    println! ();
    print! ("Intersection\nset1 ^ set2 = ");
    strset_t_print (set1 ^ set2);
    println! ();

    println! ();
    print! ("Difference\nset1 - set2 = ");
    strset_t_print (set1 - set2);
    println! ();

    println! ();
    println! ("Subset");
    println! ("set1 <= set1: ", set1 <= set1);
    println! ("set2 <= set2: ", set2 <= set2);
    println! ("set1 <= set2: ", set1 <= set2);
    println! ("set2 <= set1: ", set2 <= set1);
    println! ("(set1 ^ set2) <= set1: ", (set1 ^ set2) <= set1);
    println! ("(set1 ^ set2) <= set2: ", (set1 ^ set2) <= set2);

    println! ();
    println! ("Equal");
    println! ("set1 = set1: ", set1 = set1);
    println! ("set2 = set2: ", set2 = set2);
    println! ("set1 = set2: ", set1 = set2);
    println! ("set2 = set1: ", set2 = set1);
    println! ("(set1 ^ set2) = (set2 ^ set1): ",
              (set1 ^ set2) = (set2 ^ set1));
    println! ("(set1 ^ set2) = set1: ", (set1 ^ set2) = set1);
    println! ("(set1 ^ set2) = set2: ", (set1 ^ set2) = set2)
  end

(*------------------------------------------------------------------*)


test(Set,element){
	for i, val in Set
		if (val=element)
			return true
	return false
}

Union(SetA,SetB){
	SetC:=[], Temp:=[]
	for i, val in SetA
		SetC.Insert(val), Temp[val] := true
	for i, val in SetB
		if !Temp[val]
			SetC.Insert(val)
	return SetC
}

intersection(SetA,SetB){
	SetC:=[], Temp:=[]
	for i, val in SetA
		Temp[val] := true
	for i, val in SetB
		if Temp[val]
			SetC.Insert(val)
	return SetC
}

difference(SetA,SetB){
	SetC:=[], Temp:=[]
	for i, val in SetB
		Temp[val] := true
	for i, val in SetA
		if !Temp[val]
			SetC.Insert(val)
	return SetC
}

subset(SetA,SetB){
	Temp:=[], A:=B:=0
	for i, val in SetA
		Temp[val] := true , A++
	for i, val in SetB
		if Temp[val]{
			B++
			IfEqual, A, %B%, return 1
		} return 0
}

equal(SetA,SetB){
	return (SetA.MaxIndex() = SetB.MaxIndex() && subset(SetA,SetB)) ? 1: 0
}


      DIM list$(6)
      list$() = "apple", "banana", "cherry", "date", "elderberry", "fig", "grape"

      setA% = %1010101
      PRINT "Set A: " FNlistset(list$(), setA%)
      setB% = %0111110
      PRINT "Set B: " FNlistset(list$(), setB%)
      elementM% = %0000010
      PRINT "Element M: " FNlistset(list$(), elementM%) '

      IF elementM% AND setA% THEN
        PRINT "M is an element of set A"
      ELSE
        PRINT "M is not an element of set A"
      ENDIF
      IF elementM% AND setB% THEN
        PRINT "M is an element of set B"
      ELSE
        PRINT "M is not an element of set B"
      ENDIF

      PRINT '"The union of A and B is " FNlistset(list$(), setA% OR setB%)
      PRINT "The intersection of A and B is " FNlistset(list$(), setA% AND setB%)
      PRINT "The difference of A and B is " FNlistset(list$(), setA% AND NOT setB%)

      IF (setA% AND setB%) = setA% THEN
        PRINT '"Set A is a subset of set B"
      ELSE
        PRINT '"Set A is not a subset of set B"
      ENDIF
      IF setA% = setB% THEN
        PRINT "Set A is equal to set B"
      ELSE
        PRINT "Set A is not equal to set B"
      ENDIF
      END

      DEF FNlistset(list$(), set%)
      LOCAL i%, o$
      FOR i% = 0 TO 31
        IF set% AND 1 << i% o$ += list$(i%) + ", "
      NEXT
      = LEFT$(LEFT$(o$))


Union ← ⍷∾
Inter ← ∊/⊣
Diff ← ¬∘∊/⊣
Subset ← ∧´∊
Eq ← ≡○∧
CreateSet ← ⍷

•Show 2‿4‿6‿8 Union 2‿3‿5‿7
•Show 2‿4‿6‿8 Inter 2‿3‿5‿7
•Show 2‿4‿6‿8 Diff 2‿3‿5‿7
•Show 2‿4‿6‿8 Subset 2‿3‿5‿7
•Show 2‿4‿6‿8 Eq 2‿3‿5‿7
•Show CreateSet 2‿2‿3‿5‿7‿2


#include <stdio.h>

typedef unsigned int set_t; /* probably 32 bits; change according to need */

void show_set(set_t x, const char *name)
{
	int i;
	printf("%s is:", name);
	for (i = 0; (1U << i) <= x; i++)
		if (x & (1U << i))
			printf(" %d", i);
	putchar('\n');
}

int main(void)
{
	int i;
	set_t a, b, c;

	a = 0; /* empty set */
	for (i = 0; i < 10; i += 3) /* add 0 3 6 9 to set a */
		a |= (1U << i);
	show_set(a, "a");

	for (i = 0; i < 5; i++)
		printf("\t%d%s in set a\n", i, (a & (1U << i)) ? "":" not");

	b = a;
	b |= (1U << 5); b |= (1U << 10); /* b is a plus 5, 10 */
	b &= ~(1U << 0);	/* sans 0 */
	show_set(b, "b");

	show_set(a | b, "union(a, b)");
	show_set(c = a & b, "c = common(a, b)");
	show_set(a & ~b, "a - b"); /* diff, not arithmetic minus */
	show_set(b & ~a, "b - a");
	printf("b is%s a subset of a\n", !(b & ~a) ? "" : " not");
	printf("c is%s a subset of a\n", !(c & ~a) ? "" : " not");

	printf("union(a, b) - common(a, b) %s union(a - b, b - a)\n",
		((a | b) & ~(a & b)) == ((a & ~b) | (b & ~a))
			? "equals" : "does not equal");

	return 0;
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class Program
{
    static void PrintCollection(IEnumerable<int> x)
    {
        Console.WriteLine(string.Join(" ", x));
    }
    static void Main(string[] args)
    {
        Console.OutputEncoding = Encoding.UTF8;
        Console.WriteLine("Set creation");
        var A = new HashSet<int> { 4, 12, 14, 17, 18, 19, 20 };
        var B = new HashSet<int> { 2, 5, 8, 11, 12, 13, 17, 18, 20 };

        PrintCollection(A);
        PrintCollection(B);

        Console.WriteLine("Test m ∈ S -- \"m is an element in set S\"");
        Console.WriteLine("14 is an element in set A: {0}", A.Contains(14));
        Console.WriteLine("15 is an element in set A: {0}", A.Contains(15));

        Console.WriteLine("A ∪ B -- union; a set of all elements either in set A or in set B.");
        var aUb = A.Union(B);
        PrintCollection(aUb);

        Console.WriteLine("A ∖ B -- difference; a set of all elements in set A, except those in set B.");
        var aDb = A.Except(B);
        PrintCollection(aDb);

        Console.WriteLine("A ⊆ B -- subset; true if every element in set A is also in set B.");
        Console.WriteLine(A.IsSubsetOf(B));
        var C = new HashSet<int> { 14, 17, 18 };
        Console.WriteLine(C.IsSubsetOf(A));

        Console.WriteLine("A = B -- equality; true if every element of set A is in set B and vice versa.");
        Console.WriteLine(A.SetEquals(B));
        var D = new HashSet<int> { 4, 12, 14, 17, 18, 19, 20 };
        Console.WriteLine(A.SetEquals(D));

        Console.WriteLine("If A ⊆ B, but A ≠ B, then A is called a true or proper subset of B, written A ⊂ B or A ⊊ B");
        Console.WriteLine(A.IsProperSubsetOf(B));
        Console.WriteLine(C.IsProperSubsetOf(A));

        Console.WriteLine("Modify a mutable set.  (Add 10 to A; remove 12 from B).");
        A.Add(10);
        B.Remove(12);
        PrintCollection(A);
        PrintCollection(B);

        Console.ReadKey();
    }
}


#include <set>
#include <iostream>
#include <iterator>
#include <algorithm>

namespace set_display {
template <class T>
std::ostream& operator<<(std::ostream& os, const std::set<T>& set)
{
    os << '[';
    if (!set.empty()) {
        std::copy(set.begin(), --set.end(), std::ostream_iterator<T>(os, ", "));
        os << *--set.end();
    }
    return os << ']';
}
}

template <class T>
bool contains(const std::set<T>& set, const T& key)
{
    return set.count(key) != 0;
}

template <class T>
std::set<T> set_union(const std::set<T>& a, const std::set<T>& b)
{
    std::set<T> result;
    std::set_union(a.begin(), a.end(), b.begin(), b.end(), std::inserter(result, result.end()));
    return result;
}

template <class T>
std::set<T> set_intersection(const std::set<T>& a, const std::set<T>& b)
{
    std::set<T> result;
    std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::inserter(result, result.end()));
    return result;
}

template <class T>
std::set<T> set_difference(const std::set<T>& a, const std::set<T>& b)
{
    std::set<T> result;
    std::set_difference(a.begin(), a.end(), b.begin(), b.end(), std::inserter(result, result.end()));
    return result;
}

template <class T>
bool is_subset(const std::set<T>& set, const std::set<T>& subset)
{
    return std::includes(set.begin(), set.end(), subset.begin(), subset.end());
}

int main()
{
    using namespace set_display;
    std::set<int> a{2, 5, 7, 5, 9, 2}; //C++11 initialization syntax
    std::set<int> b{1, 5, 9, 7, 4 };
    std::cout << "a = " << a << '\n';
    std::cout << "b = " << b << '\n';

    int value1 = 8, value2 = 5;
    std::cout << "Set a " << (contains(a, value1) ? "contains " : "does not contain ") << value1 << '\n';
    std::cout << "Set a " << (contains(a, value2) ? "contains " : "does not contain ") << value2 << '\n';

    std::cout << "Union of a and b: " << set_union(a, b) << '\n';
    std::cout << "Intersection of a and b: " << set_intersection(a, b) << '\n';
    std::cout << "Difference of a and b: " << set_difference(a, b) << '\n';

    std::set<int> sub{5, 9};
    std::cout << "Set b " << (is_subset(a, b) ? "is" : "is not") << " a subset of a\n";
    std::cout << "Set " << sub << ' ' << (is_subset(a, sub) ? "is" : "is not") << " a subset of a\n";

    std::set<int> copy = a;
    std::cout << "a " << (a == copy ? "equals " : "does not equal ") << copy << '\n';

    return 0;
}


shared void run() {
    value a = set {1, 2, 3};
    value b = set {3, 4, 5};
    value union = a | b;
    value intersection = a & b;
    value difference = a ~ b;
    value subset = a.subset(b);
    value equality = a == b;

    print("set a:         ``a``
           set b:         ``b``
           1 in a?        ``1 in a``
           a | b:         ``union``
           a & b:         ``intersection``
           a ~ b:         ``difference``
           a subset of b? ``subset``
           a == b?        ``equality``");
}


(require 'clojure.set)

; sets can be created using the set method or set literal syntax
(def a (set [1 2 3 4]))
(def b #{4 5 6 7})

(a 10) ; returns the element if it's contained in the set, otherwise nil

(clojure.set/union a b)

(clojure.set/intersection a b)

(clojure.set/difference a b)

(clojure.set/subset? a b)


# For ad-hoc set features, it sometimes makes sense to use hashes directly,
# rather than abstract to this level, but I'm showing a somewhat heavy
# solution to show off CoffeeScript class syntax.
class Set
  constructor: (elems...) ->
    @hash = {}
    for elem in elems
      @hash[elem] = true

  add: (elem) ->
    @hash[elem] = true

  remove: (elem) ->
    delete @hash[elem]

  has: (elem) ->
    @hash[elem]?

  union: (set2) ->
    set = new Set()
    for elem of @hash
      set.add elem
    for elem in set2.to_array()
      set.add elem
    set

  intersection: (set2) ->
    set = new Set()
    for elem of @hash
      set.add elem if set2.has elem
    set

  minus: (set2) ->
    set = new Set()
    for elem of @hash
      set.add elem if !set2.has elem
    set

  is_subset_of: (set2) ->
    for elem of @hash
      return false if !set2.has elem
    true

  equals: (set2) ->
    this.is_subset_of(set2) and set2.is_subset_of this

  to_array: ->
    (elem for elem of @hash)

  each: (f) ->
    for elem of @hash
      f(elem)

  to_string: ->
    @to_array()

run_tests = ->
  set1 = new Set("apple", "banana") # creation
  console.log set1.has "apple" # true (membership)
  console.log set1.has "worms" # false (membership)

  set2 = new Set("banana", "carrots")
  console.log set1.union(set2).to_string() # [ 'apple', 'banana', 'carrots' ] (union)
  console.log set1.intersection(set2).to_string() # [ 'banana' ] (intersection)
  console.log set1.minus(set2).to_string() # [ 'apple' ] (difference)

  set3 = new Set("apple")
  console.log set3.is_subset_of set1 # true
  console.log set3.is_subset_of set2 # false

  set4 = new Set("apple", "banana")
  console.log set4.equals set1 # true
  console.log set4.equals set2 # false

  set5 = new Set("foo")
  set5.add "bar" # add
  console.log set5.to_string() # [ 'foo', 'bar' ]
  set5.remove "bar" # remove
  console.log set5.to_string() # [ 'foo' ]

  # iteration, prints apple then banana (order not guaranteed)
  set1.each (elem) ->
    console.log elem

run_tests()


(setf a '(1 2 3 4))
(setf b '(2 3 4 5))

(format t "sets: ~a ~a~%" a b)

;;; element
(loop for x from 1 to 6 do
	(format t (if (member x a)
		    "~d ∈ A~%"
		    "~d ∉ A~%") x))

(format t "A ∪ B: ~a~%" (union a b))
(format t "A ∩ B: ~a~%" (intersection a b))
(format t "A \\ B: ~a~%" (set-difference a b))
(format t (if (subsetp a b)
	    "~a ⊆ ~a~%"
	    "~a ⊈ ~a~%") a b)

(format t (if (and (subsetp a b)
		   (subsetp b a))
	    "~a = ~a~%"
	    "~a ≠ ~a~%") a b)


void main() {
    import std.stdio, std.algorithm, std.range;

    // Not true sets, items can be repeated, but must be sorted.
    auto s1 = [1, 2, 3, 4, 5, 6].assumeSorted;
    auto s2 = [2, 5, 6, 3, 4, 8].sort(); // [2,3,4,5,6,8].
    auto s3 = [1, 2, 5].assumeSorted;

    assert(s1.canFind(4)); // Linear search.
    assert(s1.contains(4)); // Binary search.
    assert(s1.setUnion(s2).equal([1,2,2,3,3,4,4,5,5,6,6,8]));
    assert(s1.setIntersection(s2).equal([2, 3, 4, 5, 6]));
    assert(s1.setDifference(s2).equal([1]));
    assert(s1.setSymmetricDifference(s2).equal([1, 8]));
    assert(s3.setDifference(s1).empty); // It's a subset.
    assert(!s1.equal(s2));

    auto s4 = [[1, 4, 7, 8], [1, 7], [1, 7, 8], [4], [7]];
    const s5 = [1, 1, 1, 4, 4, 7, 7, 7, 7, 8, 8];
    assert(s4.nWayUnion.equal(s5));
}


void main(){
  //Set Creation
  Set A = new Set.from([1,2,3]);
  Set B = new Set.from([1,2,3,4,5]);
  Set C = new Set.from([1,2,4,5]);

  print('Set A = $A');
  print('Set B = $B');
  print('Set C = $C');
  print('');
  //Test if element is in set
  int m = 3;
  print('m = 5');
  print('m in A = ${A.contains(m)}');
  print('m in B = ${B.contains(m)}');
  print('m in C = ${C.contains(m)}');
  print('');
  //Union of two sets
  Set AC = A.union(C);
  print('Set AC = Union of A and C = $AC');
  print('');
  //Intersection of two sets
  Set A_C = A.intersection(C);
  print('Set A_C = Intersection of A and C = $A_C');
  print('');
  //Difference of two sets
  Set A_diff_C = A.difference(C);
  print('Set A_diff_C = Difference between A and C = $A_diff_C');
  print('');
  //Test if set is subset of another set
  print('A is a subset of B = ${B.containsAll(A)}');
  print('C is a subset of B = ${B.containsAll(C)}');
  print('A is a subset of C = ${C.containsAll(A)}');
  print('');
  //Test if two sets are equal
  print('A is equal to B  = ${B.containsAll(A) && A.containsAll(B)}');
  print('B is equal to AC = ${B.containsAll(AC) && AC.containsAll(B)}');
}


program Set_task;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  Boost.Generics.Collection;

begin
  var s1 := TSet<Integer>.Create([1, 2, 3, 4, 5, 6]);
  var s2 := TSet<Integer>.Create([2, 5, 6, 3, 4, 8]);
  var s3 := TSet<Integer>.Create([1, 2, 5]);

  Writeln('S1 ', s1.ToString);
  Writeln('S2 ', s2.ToString);
  Writeln('S3 ', s3.ToString, #10);

  Writeln('4 is in S1? ', s1.Has(4));
  Writeln('S1 union S2 ', (s1 + S2).ToString);
  Writeln('S1 intersection S2 ', (s1 * S2).ToString);
  Writeln('S1 difference S2 ', (s1 - S2).ToString);
  Writeln('S3 is subset S2 ', s1.IsSubSet(s3));
  Writeln('S1 equality S2? ', s1 = s2);
  readln;
end.


; use { } to read a set
(define A { 1 2 3 4 3 5 5}) → { 1 2 3 4 5 } ; duplicates are removed from a set
; or use make-set to make a set from a list
(define B (make-set ' ( 3 4 5 6 7 8 8))) → { 3 4 5 6 7 8 }
(set-intersect A B) → { 3 4 5 }
(set-intersect? A B) → #t ; predicate
(set-union A B) → { 1 2 3 4 5 6 7 8 }
(set-substract A B) → { 1 2 }
(set-sym-diff A B) → { 1 2 6 7 8 } ; ∆ symmetric difference
(set-equal? A B) →  #f
(set-equal? { a b c} { c b a}) → #t ; order is unimportant
(set-subset? A B) → #f ; B in A or B = A
(set-subset? A { 3 4 }) → #t
(member 4 A) → (4 5) ; same as #t : true
(member 9 A) → #f

; check basic equalities
(set-equal? A (set-union (set-intersect A B) (set-substract A B))) → #t
(set-equal? (set-union A B) (set-union (set-sym-diff A B) (set-intersect A B))) → #t

; × : cartesian product of two sets : all pairs (a . b) , a in A, b in B
; returns a list (not a set)
(define A { albert simon})
(define B { antoinette ornella marylin})

(set-product A B)
→ ((albert . antoinette) (albert . marylin) (albert . ornella) (simon . antoinette) (simon . marylin) (simon . ornella))

; sets elements may be sets
{ { a b c} {c b a } { a b d}} → { { a b c } { a b d } } ; duplicate removed

; A few functions return sets :
(primes 10) → { 2 3 5 7 11 13 17 19 23 29 }


iex(1)> s = MapSet.new
#MapSet<[]>
iex(2)> sa = MapSet.put(s, :a)
#MapSet<[:a]>
iex(3)> sab = MapSet.put(sa, :b)
#MapSet<[:a, :b]>
iex(4)> sbc = Enum.into([:b, :c], MapSet.new)
#MapSet<[:b, :c]>
iex(5)> MapSet.member?(sab, :a)
true
iex(6)> MapSet.member?(sab, :c)
false
iex(7)> :a in sab
true
iex(8)> MapSet.union(sab, sbc)
#MapSet<[:a, :b, :c]>
iex(9)> MapSet.intersection(sab, sbc)
#MapSet<[:b]>
iex(10)> MapSet.difference(sab, sbc)
#MapSet<[:a]>
iex(11)> MapSet.disjoint?(sab, sbc)
false
iex(12)> MapSet.subset?(sa, sab)
true
iex(13)> MapSet.subset?(sab, sa)
false
iex(14)> sa == sab
false


2> S = sets:new().
3> Sa = sets:add_element(a, S).
4> Sab = sets:from_list([a, b]).
5> sets:is_element(a, Sa).
true
6> Union = sets:union(Sa, Sab).
7> sets:to_list(Union).
[a,b]
8> Intersection = sets:intersection(Sa, Sab).
9> sets:to_list(Intersection).
[a]
10> Subtract = sets:subtract(Sab, Sa).
11> sets:to_list(Subtract).
[b]
12> sets:is_subset(Sa, Sab).
true
13> Sa =:= Sab.
false


[<EntryPoint>]
let main args =
    // Create some sets (of int):
    let s1 = Set.ofList [1;2;3;4;3]
    let s2 = Set.ofArray [|3;4;5;6|]

    printfn "Some sets (of int):"
    printfn "s1 = %A" s1
    printfn "s2 = %A" s2
    printfn "Set operations:"
    printfn "2 ∈ s1? %A" (s1.Contains 2)
    printfn "10 ∈ s1? %A" (s1.Contains 10)
    printfn "s1 ∪ s2 = %A" (Set.union s1 s2)
    printfn "s1 ∩ s2 = %A" (Set.intersect s1 s2)
    printfn "s1 ∖ s2 = %A" (Set.difference s1 s2)
    printfn "s1 ⊆ s2? %A" (Set.isSubset s1 s1)
    printfn "{3, 1} ⊆ s1? %A" (Set.isSubset (Set.ofList [3;1]) s1)
    printfn "{3, 2, 4, 1} = s1? %A" ((Set.ofList [3;2;4;1]) = s1)
    printfn "s1 = s2? %A" (s1 = s2)
    printfn "More set operations:"
    printfn "#s1 = %A" s1.Count
    printfn "s1 ∪ {99} = %A" (s1.Add 99)
    printfn "s1 ∖ {3} = %A" (s1.Remove 3)
    printfn "s1 ⊂ s1? %A" (Set.isProperSubset s1 s1)
    printfn "s1 ⊂ s2? %A" (Set.isProperSubset s1 s2)
    0


( scratchpad ) USE: sets
( scratchpad ) HS{ 2 5 4 3 } HS{ 5 6 7 } union .
HS{ 2 3 4 5 6 7 }
( scratchpad ) HS{ 2 5 4 3 } HS{ 5 6 7 } intersect .
HS{ 5 }
( scratchpad ) HS{ 2 5 4 3 } HS{ 5 6 7 } diff .
HS{ 2 3 4 }
( scratchpad ) HS{ 2 5 4 3 } HS{ 5 6 7 } subset? .
f
( scratchpad ) HS{ 5 6 } HS{ 5 6 7 } subset? .
t
( scratchpad ) HS{ 5 6 } HS{ 5 6 7 } set= .
f
( scratchpad ) HS{ 6 5 7 } HS{ 5 6 7 } set= .
t


include FMS-SI.f
include FMS-SILib.f

: union {: a b -- c :}
  begin
    b each:
  while dup
    a indexOf: if 2drop else a add: then
  repeat b <free a dup sort: ; ok

i{ 2 5 4 3 } i{ 5 6 7 } union p: i{ 2 3 4 5 6 7 } ok

: free2 ( a b -- ) <free <free ;
: intersect {: a b | c -- c :}
  heap> 1-array2 to c
  begin
    b each:
  while dup
    a indexOf: if drop c add: else drop then
  repeat a b free2 c dup sort: ;

i{ 2 5 4 3 } i{ 5 6 7 } intersect p: i{ 5 } ok

: diff {: a b | c -- c :}
  heap> 1-array2 to c
  begin
    a each:
  while dup
    b indexOf: if 2drop else c add: then
  repeat a b free2 c dup sort: ;

i{ 2 5 4 3 } i{ 5 6 7 } diff p: i{ 2 3 4 } ok

: subset {: a b -- flag :}
  begin
    a each:
  while
    b indexOf: if drop else false exit then
  repeat a b free2 true ;

i{ 2 5 4 3 } i{ 5 6 7 } subset . 0 ok
i{ 5 6 } i{ 5 6 7 } subset .  -1 ok

: set= {: a b -- flag :}
  a size: b size: <> if a b free2 false exit then
  a sort: b sort:
  begin
    a each: drop b each:
  while
    <> if a b free2 false exit then
  repeat a b free2 true ;

i{ 5 6 } i{ 5 6 7 } set= .  0 ok
i{ 6 5 7 } i{ 5 6 7 } set= .  -1 ok


function is_in( N as integer, S() as integer ) as boolean
    'test if the value N is in the set S
    for i as integer = 0 to ubound(S)
        if N=S(i) then return true
    next i
    return false
end function

sub add_to_set( N as integer, S() as integer )
    'adds the element N to the set S
    if is_in( N, S() ) then return
    dim as integer k = ubound(S)
    redim preserve S(0 to k+1)
    S(k+1)=N
end sub

sub setunion( S() as integer, T() as integer, U() as integer )
    'makes U() the union of the sets S and T
    dim as integer k = ubound(S)
    redim U(-1)
    for i as integer = 0 to k
        add_to_set( S(i), U() )
    next i
    k = ubound(T)
    for i as integer = 0 to k
        if not is_in( T(i), U() ) then
            add_to_set( T(i), U() )
        end if
    next i
end sub

sub setintersect( S() as integer, T() as integer, U() as integer )
    'makes U() the intersection of the sets S and T
    dim as integer k = ubound(S)
    redim U(-1)
    for i as integer = 0 to k
        if is_in(S(i), T()) then add_to_set( S(i), U() )
    next i
end sub

sub setsubtract( S() as integer, T() as integer, U() as integer )
    'makes U() the difference of the sets S and T
    dim as integer k = ubound(S)
    redim U(-1)
    for i as integer = 0 to k
        if not is_in(S(i), T()) then add_to_set( S(i), U() )
    next i
end sub

function is_subset( S() as integer, T() as integer ) as boolean
    for i as integer = 0 to ubound(S)
        if not is_in( S(i), T() ) then return false
    next i
    return true
end function

function is_equal( S() as integer, T() as integer ) as boolean
    if not is_subset( S(), T() ) then return false
    if not is_subset( T(), S() ) then return false
    return true
end function

function is_proper_subset( S() as integer, T() as integer ) as boolean
    if not is_subset( S(), T() ) then return false
    if is_equal( S(), T() ) then return false
    return true
end function

sub show_set( L() as integer )
    'display a set
    dim as integer num = ubound(L)
    if num=-1 then
        print "[]"
        return
    end if
    print "[";
    for i as integer = 0 to num-1
        print str(L(i))+", ";
    next i
    print str(L(num))+"]"
end sub

'sets are created by making an empty array
redim as integer S1(-1), S2(-1), S3(-1), S4(-1), S5(-1)
'and populated by adding elements one-by-one
add_to_set( 20, S1() )  :  add_to_set( 30, S1() )
add_to_set( 40, S1() )  :  add_to_set( 50, S1() )
add_to_set( 19, S2() )  :  add_to_set( 20, S2() )
add_to_set( 21, S2() )  :  add_to_set( 22, S2() )
add_to_set( 22, S3() )  :  add_to_set( 21, S3() )
add_to_set( 19, S3() )  :  add_to_set( 20, S3() )
add_to_set( 21, S3() ) ' attempt to add a number that's already in the set
add_to_set( 21, S4() )
print "S1    ",
show_set S1()
print "S2    ",
show_set S2()
print "S3    ",
show_set S3()
print "S4    ",
show_set S4()
print "S5    ",
show_set S5()
print "----"
redim as integer S_U(-1)
setunion S1(), S2(), S_U()
print "S1 U S2    ",
show_set S_U()
redim as integer S_U(-1)
setintersect S1(), S2(), S_U()
print "S1 n S2    ",
show_set S_U()
redim as integer S_U(-1)
setsubtract S1(), S2(), S_U()
print "S1 \ S2    ",
show_set S_U()
redim as integer S_U(-1)
setsubtract S3(), S1(), S_U()
print "S3 \ S1    ",
show_set S_U()
print "S4 in S3? ", is_subset(S4(), S3())
print "S3 in S4? ", is_subset(S3(), S4())
print "S5 in S3? ", is_subset(S5(), S3())  'empty set is a subset of every set
print "S2 = S3?  ", is_equal(S2(), S3())
print "S4 proper subset of S3?   ", is_proper_subset( S4(), S3() )
print "S2 proper subset of S3?   ", is_proper_subset( S2(), S3() )


a = new set[1, 2]
b = toSet[[2,3]]   // Construct a set from an array

a.contains[2]  // Element test (returns true)
union[a,b]
intersection[a,b]
setDifference[a,b]
isSubset[a,b]  // Returns true if a is a subset of b
a==b           // set equality test


A = {1, 2, 3}
B = {3, 4, 5}
C = {1, 2, 3, 4, 5}
D = {2, 1, 3}

println( '2 is in A: ' + (2 in A) )
println( '4 is in A: ' + (4 in A) )
println( 'A union B: ' + A.union(B) )
println( 'A intersect B: ' + A.intersect(B) )
println( 'A difference B: ' + A.diff(B) )
println( 'A subset of B: ' + A.subsetOf(B) )
println( 'A subset of B: ' + A.subsetOf(C) )
println( 'A equal B: ' + (A == B) )
println( 'A equal D: ' + (A == D) )

S = set( A )

println( 'S (mutable version of A): ' + S )
S.add( 4 )
println( 'S with 4 added: ' + S )
println( 'S subset of C: ' + S.subsetOf(C) )
S.remove( 1 )
println( 'S after 1 removed: ' + S )


include "NSLog.incl"

local fn DoIt
  // create
  CFSetRef s1 = fn SetWithArray( @[@"a",@"b",@"c",@"d",@"e"] )
  CFSetRef s2 = fn SetWithArray( @[@"b",@"c",@"d",@"e",@"f",@"h"] )
  CFSetRef s3 = fn SetWithArray( @[@"b",@"c",@"d"] )
  CFSetRef s4 = fn SetWithArray( @[@"b",@"c",@"d"] )
  NSLog(@"s1: %@",s1)
  NSLog(@"s2: %@",s2)
  NSLog(@"s3: %@",s3)
  NSLog(@"s4: %@\n",s4)

  // membership
  NSLog(@"\"b\" in s1: %d", fn SetContainsObject( s1, @"b" ))
  NSLog(@"\"f\" in s1: %d\n", fn SetContainsObject( s1, @"f" ))

  // union
  CFMutableSetRef s12 = fn MutableSetWithSet( s1 )
  MutableSetUnionSet( s12, s2 )
  NSLog(@"s1 union s2: %@\n", s12)

  // intersection
  CFMutableSetRef s1i2 = fn MutableSetWithSet( s1 )
  MutableSetIntersectSet( s1i2, s2 )
  NSLog(@"s1 intersect s2: %@\n", s1i2)

  // difference
  CFMutableSetRef s1d2 = fn MutableSetWithSet( s1 )
  MutableSetMinusSet( s1d2, s2 )
  NSLog(@"s1 - s2: %@\n", s1d2)

  // subsetof
  NSLog(@"s3 subset of s1: %d\n", fn SetIsSubsetOfSet( s3, s1 ))

  // equality
  NSLog(@"s3 == s4: %d\n", fn SetIsEqual( s3, s4 ))

  // cardinality
  NSLog(@"size of s1: %lu\n", fn SetCount(s1))

  // has intersection (not disjoint)
  NSLog(@"s1 intersects s2: %d\n", fn SetIntersectsSet( s1, s2 ))

  // adding and removing elements from mutable set
  CFMutableSetRef s1mut = fn MutableSetWithSet( s1 )
  MutableSetAddObject( s1mut, @"g" )
  NSLog(@"s1mut after adding \"g\": %@\n", s1mut)
  MutableSetAddObject( s1mut, @"b" )
  NSLog(@"s1mut after adding \"b\" again: %@\n", s1mut)
  MutableSetRemoveObject( s1mut, @"c" )
  NSLog(@"s1mut after removing \"c\": %@\n", s1mut)
end fn

fn DoIt

HandleEvents


package main

import "fmt"

// Define set as a type to hold a set of complex numbers.  A type
// could be defined similarly to hold other types of elements.  A common
// variation is to make a map of interface{} to represent a set of
// mixed types.  Also here the map value is a bool.  By always storing
// true, the code is nicely readable.  A variation to use less memory
// is to make the map value an empty struct.  The relative advantages
// can be debated.
type set map[complex128]bool

func main() {
    // task: set creation
    s0 := make(set)             // create empty set
    s1 := set{3: true}          // create set with one element
    s2 := set{3: true, 1: true} // create set with two elements

    // option: another way to create a set
    s3 := newSet(3, 1, 4, 1, 5, 9)

    // option: output!
    fmt.Println("s0:", s0)
    fmt.Println("s1:", s1)
    fmt.Println("s2:", s2)
    fmt.Println("s3:", s3)

    // task: element predicate
    fmt.Printf("%v ∈ s0: %t\n", 3, s0.hasElement(3))
    fmt.Printf("%v ∈ s3: %t\n", 3, s3.hasElement(3))
    fmt.Printf("%v ∈ s3: %t\n", 2, s3.hasElement(2))

    // task: union
    b := set{4: true, 2: true}
    fmt.Printf("s3 ∪ %v: %v\n", b, union(s3, b))

    // task: intersection
    fmt.Printf("s3 ∩ %v: %v\n", b, intersection(s3, b))

    // task: difference
    fmt.Printf("s3 \\ %v: %v\n", b, difference(s3, b))

    // task: subset predicate
    fmt.Printf("%v ⊆ s3: %t\n", b, subset(b, s3))
    fmt.Printf("%v ⊆ s3: %t\n", s2, subset(s2, s3))
    fmt.Printf("%v ⊆ s3: %t\n", s0, subset(s0, s3))

    // task: equality
    s2Same := set{1: true, 3: true}
    fmt.Printf("%v = s2: %t\n", s2Same, equal(s2Same, s2))

    // option: proper subset
    fmt.Printf("%v ⊂ s2: %t\n", s2Same, properSubset(s2Same, s2))
    fmt.Printf("%v ⊂ s3: %t\n", s2Same, properSubset(s2Same, s3))

    // option: delete.  it's built in.
    delete(s3, 3)
    fmt.Println("s3, 3 deleted:", s3)
}

func newSet(ms ...complex128) set {
    s := make(set)
    for _, m := range ms {
        s[m] = true
    }
    return s
}

func (s set) String() string {
    if len(s) == 0 {
        return "∅"
    }
    r := "{"
    for e := range s {
        r = fmt.Sprintf("%s%v, ", r, e)
    }
    return r[:len(r)-2] + "}"
}

func (s set) hasElement(m complex128) bool {
    return s[m]
}

func union(a, b set) set {
    s := make(set)
    for e := range a {
        s[e] = true
    }
    for e := range b {
        s[e] = true
    }
    return s
}

func intersection(a, b set) set {
    s := make(set)
    for e := range a {
        if b[e] {
            s[e] = true
        }
    }
    return s
}

func difference(a, b set) set {
    s := make(set)
    for e := range a {
        if !b[e] {
            s[e] = true
        }
    }
    return s
}

func subset(a, b set) bool {
    for e := range a {
        if !b[e] {
            return false
        }
    }
    return true
}

func equal(a, b set) bool {
    return len(a) == len(b) && subset(a, b)
}

func properSubset(a, b set) bool {
    return len(a) < len(b) && subset(a, b)
}


def s1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as Set
def m1 = 6
def m2 = 7
def s2 = [0, 2, 4, 6, 8] as Set
assert m1 in s1                                        : 'member'
assert ! (m2 in s2)                                    : 'not a member'
def su = s1 + s2
assert su == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as Set : 'union'
def si = s1.intersect(s2)
assert si == [8, 6, 4, 2] as Set                       : 'intersection'
def sd = s1 - s2
assert sd == [1, 3, 5, 7, 9, 10] as Set                : 'difference'
assert s1.containsAll(si)                              : 'subset'
assert ! s1.containsAll(s2)                            : 'not a subset'
assert (si + sd) == s1                                 : 'equality'
assert (s2 + sd) != s1                                 : 'inequality'
assert s1 != su && su.containsAll(s1)                  : 'proper subset'
s1 << 0
assert s1 == su                                        : 'added element 0 to s1'


#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

#define LIMIT 15
int smallPrimes[LIMIT];

static void sieve() {
    int i = 2, j;
    int p = 5;

    smallPrimes[0] = 2;
    smallPrimes[1] = 3;

    while (i < LIMIT) {
        for (j = 0; j < i; j++) {
            if (smallPrimes[j] * smallPrimes[j] <= p) {
                if (p % smallPrimes[j] == 0) {
                    p += 2;
                    break;
                }
            } else {
                smallPrimes[i++] = p;
                p += 2;
                break;
            }
        }
    }
}

static bool is_prime(uint64_t n) {
    uint64_t i;

    for (i = 0; i < LIMIT; i++) {
        if (n % smallPrimes[i] == 0) {
            return n == smallPrimes[i];
        }
    }

    i = smallPrimes[LIMIT - 1] + 2;
    for (; i * i <= n; i += 2) {
        if (n % i == 0) {
            return false;
        }
    }

    return true;
}

static uint64_t divisor_count(uint64_t n) {
    uint64_t count = 1;
    uint64_t d;

    while (n % 2 == 0) {
        n /= 2;
        count++;
    }

    for (d = 3; d * d <= n; d += 2) {
        uint64_t q = n / d;
        uint64_t r = n % d;
        uint64_t dc = 0;
        while (r == 0) {
            dc += count;
            n = q;
            q = n / d;
            r = n % d;
        }
        count += dc;
    }

    if (n != 1) {
        return count *= 2;
    }
    return count;
}

static uint64_t OEISA073916(size_t n) {
    uint64_t count = 0;
    uint64_t result = 0;
    size_t i;

    if (is_prime(n)) {
        return (uint64_t)pow(smallPrimes[n - 1], n - 1);
    }

    for (i = 1; count < n; i++) {
        if (n % 2 == 1) {
            //  The solution for an odd (non-prime) term is always a square number
            uint64_t root = (uint64_t)sqrt(i);
            if (root * root != i) {
                continue;
            }
        }
        if (divisor_count(i) == n) {
            count++;
            result = i;
        }
    }

    return result;
}

int main() {
    size_t n;

    sieve();

    for (n = 1; n <= LIMIT; n++) {
        if (n == 13) {
            printf("A073916(%lu) = One more bit needed to represent result.\n", n);
        } else {
            printf("A073916(%lu) = %llu\n", n, OEISA073916(n));
        }
    }

    return 0;
}


Prelude> import Data.Set
Prelude Data.Set> empty :: Set Integer -- Empty set
fromList []
Prelude Data.Set> let s1 = fromList [1,2,3,4,3] -- Convert list into set
Prelude Data.Set> s1
fromList [1,2,3,4]
Prelude Data.Set> let s2 = fromList [3,4,5,6]
Prelude Data.Set> union s1 s2 -- Union
fromList [1,2,3,4,5,6]
Prelude Data.Set> intersection s1 s2 -- Intersection
fromList [3,4]
Prelude Data.Set> s1 \\ s2 -- Difference
fromList [1,2]
Prelude Data.Set> s1 `isSubsetOf` s1 -- Subset
True
Prelude Data.Set> fromList [3,1] `isSubsetOf` s1
True
Prelude Data.Set> s1 `isProperSubsetOf` s1 -- Proper subset
False
Prelude Data.Set> fromList [3,1] `isProperSubsetOf` s1
True
Prelude Data.Set> fromList [3,2,4,1] == s1 -- Equality
True
Prelude Data.Set> s1 == s2
False
Prelude Data.Set> 2 `member` s1 -- Membership
True
Prelude Data.Set> 10 `notMember` s1
True
Prelude Data.Set> size s1 -- Cardinality
4
Prelude Data.Set> insert 99 s1 -- Create a new set by inserting
fromList [1,2,3,4,99]
Prelude Data.Set> delete 3 s1 -- Create a new set by deleting
fromList [1,2,4]


#include <iostream>
#include <vector>

std::vector<int> smallPrimes;

bool is_prime(size_t test) {
    if (test < 2) {
        return false;
    }
    if (test % 2 == 0) {
        return test == 2;
    }
    for (size_t d = 3; d * d <= test; d += 2) {
        if (test % d == 0) {
            return false;
        }
    }
    return true;
}

void init_small_primes(size_t numPrimes) {
    smallPrimes.push_back(2);

    int count = 0;
    for (size_t n = 3; count < numPrimes; n += 2) {
        if (is_prime(n)) {
            smallPrimes.push_back(n);
            count++;
        }
    }
}

size_t divisor_count(size_t n) {
    size_t count = 1;
    while (n % 2 == 0) {
        n /= 2;
        count++;
    }
    for (size_t d = 3; d * d <= n; d += 2) {
        size_t q = n / d;
        size_t r = n % d;
        size_t dc = 0;
        while (r == 0) {
            dc += count;
            n = q;
            q = n / d;
            r = n % d;
        }
        count += dc;
    }
    if (n != 1) {
        count *= 2;
    }
    return count;
}

uint64_t OEISA073916(size_t n) {
    if (is_prime(n)) {
        return (uint64_t) pow(smallPrimes[n - 1], n - 1);
    }

    size_t count = 0;
    uint64_t result = 0;
    for (size_t i = 1; count < n; i++) {
        if (n % 2 == 1) {
            //  The solution for an odd (non-prime) term is always a square number
            size_t root = (size_t) sqrt(i);
            if (root * root != i) {
                continue;
            }
        }
        if (divisor_count(i) == n) {
            count++;
            result = i;
        }
    }
    return result;
}

int main() {
    const int MAX = 15;
    init_small_primes(MAX);
    for (size_t n = 1; n <= MAX; n++) {
        if (n == 13) {
            std::cout << "A073916(" << n << ") = One more bit needed to represent result.\n";
        } else {
            std::cout << "A073916(" << n << ") = " << OEISA073916(n) << '\n';
        }
    }

    return 0;
}


procedure display_set (s)
  writes ("[")
  every writes (!s || " ")
  write ("]")
end

# fail unless s1 and s2 contain the same elements
procedure set_equals (s1, s2)
  return subset(s1, s2) & subset(s2, s1)
end

# fail if every element in s2 is not contained in s1
procedure subset (s1, s2)
  every (a := !s2) do {
    if not(member(s1,a)) then fail
  }
  return s2
end

procedure main ()
  a := set(1, 1, 2, 3, 4)
  b := set(2, 3, 5)
  writes ("a: ")
  display_set (a)
  writes ("b: ")
  display_set (b)
  # basic set operations
  writes ("Intersection: ")
  display_set (a ** b)
  writes ("Union: ")
  display_set (a ++ b)
  writes ("Difference: ")
  display_set (a -- b)
  # membership
  if member(a, 2) then
    write ("2 is a member of a")
  else
    write ("2 is not a member of a")
  if member(a, 5) then
    write ("5 is a member of a")
  else
    write ("5 is not a member of a")
  # equality
  if set_equals(a, set(1,2,3,4,4)) then
    write ("a equals set(1,2,3,4,4)")
  else
    write ("a does not equal set(1,2,3,4,4)")
  if set_equals(a, b) then
    write ("a equals b")
  else
    write ("a does not equal b")
  # subset
  if subset(a, set(1,2)) then
    write ("(1,2) is included in a")
  else
    write ("(1,2) is not included in a")
  if subset(a, set(1,2,5)) then
    write ("(1,2,5) is included in a")
  else
    write ("(1,2,5) is not included in a")
end


import std.bigint;
import std.math;
import std.stdio;

bool isPrime(long test) {
    if (test == 2) {
        return true;
    }
    if (test % 2 == 0) {
        return false;
    }
    for (long d = 3 ; d * d <= test; d += 2) {
        if (test % d == 0) {
            return false;
        }
    }
    return true;
}

int[] calcSmallPrimes(int numPrimes) {
    int[] smallPrimes;
    smallPrimes ~= 2;

    int count = 0;
    int n = 3;
    while (count < numPrimes) {
        if (isPrime(n)) {
            smallPrimes ~= n;
            count++;
        }
        n += 2;
    }

    return smallPrimes;
}

immutable MAX = 45;
immutable smallPrimes = calcSmallPrimes(MAX);

int getDivisorCount(long n) {
    int count = 1;
    while (n % 2 == 0) {
        n /= 2;
        count += 1;
    }
    for (long d = 3; d * d <= n; d += 2) {
        long q = n / d;
        long r = n % d;
        int dc = 0;
        while (r == 0) {
            dc += count;
            n = q;
            q = n / d;
            r = n % d;
        }
        count += dc;
    }
    if (n != 1) {
        count *= 2;
    }
    return count;
}

BigInt OEISA073916(int n) {
    if (isPrime(n) ) {
        return BigInt(smallPrimes[n-1]) ^^ (n - 1);
    }
    int count = 0;
    int result = 0;
    for (int i = 1; count < n; i++) {
        if (n % 2 == 1) {
            //  The solution for an odd (non-prime) term is always a square number
            int root = cast(int) sqrt(cast(real) i);
            if (root * root != i) {
                continue;
            }
        }
        if (getDivisorCount(i) == n) {
            count++;
            result = i;
        }
    }
    return BigInt(result);
}

void main() {
    foreach (n; 1 .. MAX + 1) {
        writeln("A073916(", n, ") = ", OEISA073916(n));
    }
}


union=: [email protected],
intersection=: [ -. -.
difference=: -.
subset=: *./@e.
equality=: -:&(/:~)


import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.TreeSet;

public class Sets {
    public static void main(String[] args){
        Set<Integer> a = new TreeSet<>();
        //TreeSet sorts on natural ordering (or an optional comparator)
        //other options: HashSet (hashcode)
        //               LinkedHashSet (insertion order)
        //               EnumSet (optimized for enum values)
        //others at: http://download.oracle.com/javase/7/docs/api/java/util/Set.html
        Set<Integer> b = new TreeSet<>();
        Set<Integer> c = new TreeSet<>();
        Set<Integer> d = new TreeSet<>();

        a.addAll(Arrays.asList(1, 2, 3, 4, 5));
        b.addAll(Arrays.asList(2, 3, 4, 5, 6, 8));
        c.addAll(Arrays.asList(2, 3, 4));
        d.addAll(Arrays.asList(2, 3, 4));
        System.out.println("a: " + a);
        System.out.println("b: " + b);
        System.out.println("c: " + c);
        System.out.println("d: " + d);

        System.out.println("2 in a: " + a.contains(2));
        System.out.println("6 in a: " + a.contains(6));

        Set<Integer> ab = new TreeSet<>();
        ab.addAll(a);
        ab.addAll(b);
        System.out.println("a union b: " + ab);

        Set<Integer> a_b = new TreeSet<>();
        a_b.addAll(a);
        a_b.removeAll(b);
        System.out.println("a - b: " + a_b);

        System.out.println("c subset of a: " + a.containsAll(c));
        //use a.conatins() for single elements

        System.out.println("c = d: " + c.equals(d));
        System.out.println("d = c: " + d.equals(c));

        Set<Integer> aib = new TreeSet<>();
        aib.addAll(a);
        aib.retainAll(b);
        System.out.println("a intersect b: " + aib);

        System.out.println("add 7 to a: " + a.add(7));
        System.out.println("add 2 to a again: " + a.add(2));

        //other noteworthy things related to sets:
        Set<Integer> empty = Collections.EMPTY_SET; //immutable empty set
        //empty.add(2);  would fail
        empty.isEmpty(); //test if a set is empty
        empty.size();
        Collections.disjoint(a, b); //returns true if the sets have no common elems (based on their .equals() methods)
        Collections.unmodifiableSet(a); //returns an immutable copy of a
    }
}


USING: combinators formatting fry kernel lists lists.lazy
lists.lazy.examples literals math math.functions math.primes
math.primes.factors math.ranges sequences ;
IN: rosetta-code.nth-n-div

CONSTANT: primes $[ 100 nprimes ]

: prime ( m -- n ) 1 - [ primes nth ] [ ^ ] bi ;

: (non-prime) ( m quot -- n )
    '[
        [ 1 - ] [ drop @ ] [ ] tri '[ divisors length _ = ]
        lfilter swap [ cdr ] times car
    ] call ; inline

: non-prime ( m quot -- n )
    {
        { [ over 2 = ] [ 2drop 3 ] }
        { [ over 10 = ] [ 2drop 405 ] }
        [ (non-prime) ]
    } cond ; inline

: fn ( m -- n )
    {
        { [ dup even? ] [ [ evens ] non-prime ] }
        { [ dup prime? ] [ prime ] }
        [ [ squares ] non-prime ]
    } cond ;

: main ( -- ) 45 [1,b] [ dup fn "%2d : %d\n" printf ] each ;

MAIN: main


Dim As Integer n, num, pnum
Dim As Ulongint m, p
Dim As Ulongint limit = 18446744073709551615

Print "The first 15 terms of OEIS:A073916 are:"
For n = 1 To 15
    num = 0
    For m = 1 To limit
        pnum = 0
        For p = 1 To limit
            If (m Mod p = 0) Then pnum += 1
        Next p
        If pnum = n Then num += 1
        If num = n Then
            Print Using "## : &"; n; m
            Exit  For
        End If
    Next m
Next n
Sleep


package main

import (
    "fmt"
    "math"
    "math/big"
)

var bi = new(big.Int)

func isPrime(n int) bool {
    bi.SetUint64(uint64(n))
    return bi.ProbablyPrime(0)
}

func generateSmallPrimes(n int) []int {
    primes := make([]int, n)
    primes[0] = 2
    for i, count := 3, 1; count < n; i += 2 {
        if isPrime(i) {
            primes[count] = i
            count++
        }
    }
    return primes
}

func countDivisors(n int) int {
    count := 1
    for n%2 == 0 {
        n >>= 1
        count++
    }
    for d := 3; d*d <= n; d += 2 {
        q, r := n/d, n%d
        if r == 0 {
            dc := 0
            for r == 0 {
                dc += count
                n = q
                q, r = n/d, n%d
            }
            count += dc
        }
    }
    if n != 1 {
        count *= 2
    }
    return count
}

func main() {
    const max = 33
    primes := generateSmallPrimes(max)
    z := new(big.Int)
    p := new(big.Int)
    fmt.Println("The first", max, "terms in the sequence are:")
    for i := 1; i <= max; i++ {
        if isPrime(i) {
            z.SetUint64(uint64(primes[i-1]))
            p.SetUint64(uint64(i - 1))
            z.Exp(z, p, nil)
            fmt.Printf("%2d : %d\n", i, z)
        } else {
            count := 0
            for j := 1; ; j++ {
                if i%2 == 1 {
                    sq := int(math.Sqrt(float64(j)))
                    if sq*sq != j {
                        continue
                    }
                }
                if countDivisors(j) == i {
                    count++
                    if count == i {
                        fmt.Printf("%2d : %d\n", i, j)
                        break
                    }
                }
            }
        }
    }
}


var set = new Set();

set.add(0);
set.add(1);
set.add('two');
set.add('three');

set.has(0); //=> true
set.has(3); //=> false
set.has('two'); // true
set.has(Math.sqrt(4)); //=> false
set.has('TWO'.toLowerCase()); //=> true

set.size; //=> 4

set.delete('two');
set.has('two'); //==> false
set.size; //=> 3

//iterating set using ES6 for..of
//Set order is preserved in order items are added.
for (var item of set) {
  console.log('item is ' + item);
}


import           Control.Monad                         (guard)
import           Math.NumberTheory.ArithmeticFunctions (divisorCount)
import           Math.NumberTheory.Primes              (Prime, unPrime)
import           Math.NumberTheory.Primes.Testing      (isPrime)

calc :: Integer -> [(Integer, Integer)]
calc n = do
  x <- [1..]
  guard (even n || odd n && f x == x)
  [(x, divisorCount x)]
 where f n = floor (sqrt $ realToFrac n) ^ 2

havingNthDivisors :: Integer -> [(Integer, Integer)]
havingNthDivisors n = filter ((==n) . snd) $ calc n

nths :: [(Integer, Integer)]
nths = do
  n <- [1..35] :: [Integer]
  if isPrime n then
    pure (n, nthPrime (fromIntegral n) ^ pred n)
  else
    pure (n, f n)
 where
  f n = fst (havingNthDivisors n !! pred (fromIntegral n))
  nthPrime n = unPrime (toEnum n :: Prime Integer)

main :: IO ()
main = mapM_ print nths


A073916=: {{
  if.1 p: y do. (p:^x:)y-1 return.
  elseif.1|y do.
    f= *:
  else.
    f=. ]
  end. r=.i.0
  off=. 1
  while. y>#r do.
    r=. r,f off+I.y=*/|:1+_ q:f off+i.y
    off=. off+y
  end.
  (y-1){r
}}"0


julia> S1 = Set(1:4) ; S2 = Set(3:6) ; println(S1,"\n",S2)
Set{Int64}({4,2,3,1})
Set{Int64}({5,4,6,3})

julia> 5 in S1 , 5 in S2
(false,true)

julia> intersect(S1,S2)
Set{Int64}({4,3})

julia> union(S1,S2)
Set{Int64}({5,4,6,2,3,1})

julia> setdiff(S1,S2)
Set{Int64}({2,1})

julia> issubset(S1,S2)
false

julia> isequal(S1,S2)
false

julia> symdiff(S1,S2)
Set{Int64}({5,6,2,1})


import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

public class SequenceNthNumberWithExactlyNDivisors {

    public static void main(String[] args) {
        int max = 45;
        smallPrimes(max);
        for ( int n = 1; n <= max ; n++ ) {
            System.out.printf("A073916(%d) = %s%n", n, OEISA073916(n));
        }
    }

    private static List<Integer> smallPrimes = new ArrayList<>();

    private static void smallPrimes(int numPrimes) {
        smallPrimes.add(2);
        for ( int n = 3, count = 0 ; count < numPrimes ; n += 2 ) {
            if ( isPrime(n) ) {
                smallPrimes.add(n);
                count++;
            }
        }
    }

    private static final boolean isPrime(long test) {
        if ( test == 2 ) {
            return true;
        }
        if ( test % 2 == 0 ) {
            return false;
        }
        for ( long d = 3 ; d*d <= test ; d += 2 ) {
            if ( test % d == 0 ) {
                return false;
            }
        }
        return true;
    }

    private static int getDivisorCount(long n) {
        int count = 1;
        while ( n % 2 == 0 ) {
            n /= 2;
            count += 1;
        }
        for ( long d = 3 ; d*d <= n ; d += 2 ) {
            long q = n / d;
            long r = n % d;
            int dc = 0;
            while ( r == 0 ) {
                dc += count;
                n = q;
                q = n / d;
                r = n % d;
            }
            count += dc;
        }
        if ( n != 1 ) {
            count *= 2;
        }
        return count;
    }

    private static BigInteger OEISA073916(int n) {
        if ( isPrime(n) ) {
            return BigInteger.valueOf(smallPrimes.get(n-1)).pow(n - 1);
        }
        int count = 0;
        int result = 0;
        for ( int i = 1 ; count < n ; i++ ) {
            if ( n % 2 == 1 ) {
                //  The solution for an odd (non-prime) term is always a square number
                int sqrt = (int) Math.sqrt(i);
                if ( sqrt*sqrt != i ) {
                    continue;
                }
            }
            if ( getDivisorCount(i) == n ) {
                count++;
                result = i;
            }
        }
        return BigInteger.valueOf(result);
    }

}


// version 1.0.6

fun main(args: Array<String>) {
   val fruits  = setOf("apple", "pear", "orange", "banana")
   println("fruits  : $fruits")
   val fruits2 = setOf("melon", "orange", "lemon", "gooseberry")
   println("fruits2 : $fruits2\n")

   println("fruits  contains 'banana'     : ${"banana" in fruits}")
   println("fruits2 contains 'elderberry' : ${"elderbury" in fruits2}\n")

   println("Union        : ${fruits.union(fruits2)}")
   println("Intersection : ${fruits.intersect(fruits2)}")
   println("Difference   : ${fruits.minus(fruits2)}\n")

   println("fruits2 is a subset of fruits : ${fruits.containsAll(fruits2)}\n")
   val fruits3 = fruits
   println("fruits3 : $fruits3\n")
   var areEqual = fruits.containsAll(fruits2) && fruits3.containsAll(fruits)
   println("fruits2 and fruits are equal  : $areEqual")
   areEqual = fruits.containsAll(fruits3) && fruits3.containsAll(fruits)
   println("fruits3 and fruits are equal  : $areEqual\n")

   val fruits4 = setOf("apple", "orange")
   println("fruits4 : $fruits4\n")
   var isProperSubset = fruits.containsAll(fruits3) && !fruits3.containsAll(fruits)
   println("fruits3 is a proper subset of fruits : $isProperSubset")
   isProperSubset = fruits.containsAll(fruits4) && !fruits4.containsAll(fruits)
   println("fruits4 is a proper subset of fruits : $isProperSubset\n")

   val fruits5 = mutableSetOf("cherry", "blueberry", "raspberry")
   println("fruits5 : $fruits5\n")
   fruits5 += "guava"
   println("fruits5 + 'guava'  : $fruits5")
   println("fruits5 - 'cherry' : ${fruits5 - "cherry"}")
}


def count(stream): reduce stream as $i (0; .+1);

# To maintain precision:
def power($b): . as $in | reduce range(0;$b) as $i (1; . * $in);

def primes: 2, (range(3; infinite; 2) | select(is_prime));

# divisors as an unsorted stream
def divisors:
  if . == 1 then 1
  else . as $n
  | label $out
  | range(1; $n) as $i
  | ($i * $i) as $i2
  | if $i2 > $n then break $out
    else if $i2 == $n
         then $i
         elif ($n % $i) == 0
         then $i, ($n/$i)
         else empty
         end
    end
  end;


using Primes

function countdivisors(n)
    f = [one(n)]
    for (p, e) in factor(n)
        f = reduce(vcat, [f * p ^ j for j in 1:e], init = f)
    end
    length(f)
end

function nthwithndivisors(N)
    parray = findall(primesmask(100 * N))
    for i = 1:N
        if isprime(i)
            println("$i : ", BigInt(parray[i])^(i-1))
        else
            k = 0
            for j in 1:100000000000
                if (iseven(i) || Int(floor(sqrt(j)))^2 == j) &&
                    i == countdivisors(j) && (k += 1) == i
                    println("$i : $j")
                    break
                end
            end
        end
    end
end

nthwithndivisors(35)


// Version 1.3.21

import java.math.BigInteger
import kotlin.math.sqrt

const val MAX = 33

fun isPrime(n: Int) = BigInteger.valueOf(n.toLong()).isProbablePrime(10)

fun generateSmallPrimes(n: Int): List<Int> {
    val primes = mutableListOf<Int>()
    primes.add(2)
    var i = 3
    while (primes.size < n) {
        if (isPrime(i)) {
            primes.add(i)
        }
        i += 2
    }
    return primes
}

fun countDivisors(n: Int): Int {
    var nn = n
    var count = 1
    while (nn % 2 == 0) {
        nn = nn shr 1
        count++
    }
    var d = 3
    while (d * d <= nn) {
        var q = nn / d
        var r = nn % d
        if (r == 0) {
            var dc = 0
            while (r == 0) {
                dc += count
                nn = q
                q = nn / d
                r = nn % d
            }
            count += dc
        }
        d += 2
    }
    if (nn != 1) count *= 2
    return count
}

fun main() {
    var primes = generateSmallPrimes(MAX)
    println("The first $MAX terms in the sequence are:")
    for (i in 1..MAX) {
        if (isPrime(i)) {
            var z = BigInteger.valueOf(primes[i - 1].toLong())
            z = z.pow(i - 1)
            System.out.printf("%2d : %d\n", i, z)
        } else {
            var count = 0
            var j = 1
            while (true) {
                if (i % 2 == 1) {
                    val sq = sqrt(j.toDouble()).toInt()
                    if (sq * sq != j) {
                        j++
                        continue
                    }
                }
                if (countDivisors(j) == i) {
                    if (++count == i) {
                        System.out.printf("%2d : %d\n", i, j)
                        break
                    }
                }
                j++
            }
        }
    }
}


// Extend set type
define set->issubsetof(p::set) => .intersection(#p)->size == .size
define set->oncompare(p::set) => .intersection(#p)->size - .size

//	Set creation
local(set1) = set('j','k','l','m','n')
local(set2) = set('m','n','o','p','q')

//Test m ∈ S -- "m is an element in set S"
#set1 >> 'm'

// A ∪ B -- union; a set of all elements either in set A or in set B.
#set1->union(#set2)

//A ∩ B -- intersection; a set of all elements in both set A and set B.
#set1->intersection(#set2)

//A ∖ B -- difference; a set of all elements in set A, except those in set B.
#set1->difference(#set2)

//A ⊆ B -- subset; true if every element in set A is also in set B.
#set1->issubsetof(#set2)

//A = B -- equality; true if every element of set A is in set B and vice-versa.
#set1 == #set2


> (set set-1 (sets:new))
#(set 0 16 16 8 80 48 ...)
> (set set-2 (sets:add_element 'a set-1))
#(set 1 16 16 8 80 48 ...)
> (set set-3 (sets:from_list '(a b)))
#(set 2 16 16 8 80 48 ...)
> (sets:is_element 'a set-2)
true
> (set union (sets:union set-2 set-3))
#(set 2 16 16 8 80 48 ...)
> (sets:to_list union)
(a b)
> (set intersect (sets:intersection set-2 set-3))
#(set 1 16 16 8 80 48 ...)
> (sets:to_list intersect)
(a)
> (set subtr (sets:subtract set-3 set-2))
#(set 1 16 16 8 80 48 ...)
> (sets:to_list subtr)
(b)
> (sets:is_subset set-2 set-3)
true
> (=:= set-2 set-3)
false
> (set set-4 (sets:add_element 'b set-2))
#(set 2 16 16 8 80 48 ...)
> (=:= set-3 set-4)
true


d = Table[
  Length[Divisors[n]], {n,
   200000}]; t = {}; n = 0; ok = True; While[ok, n++;
 If[PrimeQ[n], AppendTo[t, Prime[n]^(n - 1)],
  c = Flatten[Position[d, n, 1, n]];
  If[Length[c] >= n, AppendTo[t, c[[n]]], ok = False]]];
t


import math, strformat
import bignum

type Record = tuple[num, count: Natural]

template isOdd(n: Natural): bool =
  (n and 1) != 0

func isPrime(n: int): bool =
  let bi = newInt(n)
  result = bi.probablyPrime(25) != 0

proc findPrimes(limit: Natural): seq[int] {.compileTime.} =
  result = @[2]
  var isComposite = newSeq[bool](limit + 1)
  var p = 3
  while true:
    let p2 = p * p
    if p2 > limit: break
    for i in countup(p2, limit, 2 * p):
      isComposite[i] = true
    while true:
      inc p, 2
      if not isComposite[p]: break
  for n in countup(3, limit, 2):
    if not isComposite[n]:
      result.add n

const Primes = findPrimes(22_000)

proc countDivisors(n: Natural): int =
  result = 1
  var n = n
  for i, p in Primes:
    if p * p > n: break
    if n mod p != 0: continue
    n = n div p
    var count = 1
    while n mod p == 0:
      n = n div p
      inc count
    result *= count + 1
    if n == 1: return
  if n != 1: result *= 2

const Max = 45
var records: array[0..Max, Record]
echo &"The first {Max} terms in the sequence are:"

for n in 1..Max:

  if n.isPrime:
    var z = newInt(Primes[n - 1])
    z = pow(z, culong(n - 1))
    echo &"{n:2}: {z}"

  else:
    var count = records[n].count
    if count == n:
      echo &"{n:2}: {records[n].num}"
      continue
    let odd = n.isOdd
    let d = if odd or n == 2 or n == 10: 1 else: 2
    var k = records[n].num
    while true:
      inc k, d
      if odd:
        let sq = sqrt(k.toFloat).int
        if sq * sq != k: continue
      let cd = k.countDivisors()
      if cd == n:
        inc count
        if count == n:
          echo &"{n:2}: {k}"
          break
      elif cd in (n + 1)..Max and records[cd].count < cd and
           k > records[cd].num and (d == 1 or d == 2 and not cd.isOdd):
        records[cd].num = k
        inc records[cd].count


use strict;
use warnings;
use bigint;
use ntheory <nth_prime is_prime divisors>;

my $limit = 20;

print "First $limit terms of OEIS:A073916\n";

for my $n (1..$limit) {
    if ($n > 4 and is_prime($n)) {
        print nth_prime($n)**($n-1) . ' ';
    } else {
        my $i = my $x = 0;
        while (1) {
            my $nn = $n%2 ? ++$x**2 : ++$x;
            next unless $n == divisors($nn) and ++$i == $n;
            print "$nn " and last;
      }
    }
}


with javascript_semantics
constant LIMIT = 24
include mpfr.e
mpz z = mpz_init()

sequence fn = repeat(0,LIMIT) fn[1] = 1
integer k = 1
printf(1,"The first %d terms in the sequence are:\n",LIMIT)
for i=1 to LIMIT do
    if is_prime(i) then
        mpz_ui_pow_ui(z,get_prime(i),i-1)
        printf(1,"%2d : %s\n",{i,mpz_get_str(z)})
    else
        while fn[i]<i do
            k += 1
            integer l = length(factors(k,1))
            if l<=LIMIT and fn[l]<l then
                fn[l] = iff(fn[l]+1<l?fn[l]+1:k)
            end if
        end while
        printf(1,"%2d : %d\n",{i,fn[i]})
    end if
end for


A$ ="red hot chili peppers rule OK"
B$ ="lady in red"

print " New set, in space-separated form. Extra spaces and duplicates will be removed. "
input newSet$
 newSet$  =trim$(           newSet$)
 newSet$  =stripBigSpaces$( newSet$)
 newSet$  =removeDupes$(    newSet$)
print " Set stored as the string '"; newSet$; "'"

print
print " 'red'  is an element of '"; A$; "' is "; isAnElementOf$( "red",  A$)
print " 'blue' is an element of '"; A$; "' is "; isAnElementOf$( "blue",  A$)
print " 'red'  is an element of '"; B$; "' is "; isAnElementOf$( "red",  B$)
print
print " Union        of '"; A$; "' & '"; B$; "' is '"; unionOf$( A$, B$); "'."
print
print " Intersection of '"; A$; "' & '"; B$; "' is '"; intersectionOf$( A$, B$); "'."
print
print " Difference   of '"; A$; "' & '"; B$; "' is '"; differenceOf$( A$, B$); "'."
print
print " '"; A$; "' equals '";        A$; "' is "; equalSets$( A$, A$)
print " '"; A$; "' equals '";        B$; "' is "; equalSets$( A$, B$)
print
print  " '"; A$; "' is a subset of '"; B$; "' is "; isSubsetOf$( A$, B$)
print  " 'red peppers' is a subset of 'red hot chili peppers rule OK' is "; isSubsetOf$( "red peppers", "red hot chili peppers rule OK")

end

function removeDupes$( a$)
    numElements =countElements( a$)
    redim elArray$( numElements)         '   ie 4 elements are array entries 1 to 4 and 0 is spare =""
    for m =0 to numElements
        el$ =word$( a$, m, " ")
        elArray$( m) =el$
    next m
    sort elArray$(), 0, numElements
    b$           =""
    penultimate$ ="999"
    for jk =0 to numElements    '   do not use "" ( nuls) or elementsalready seen
        if elArray$( jk) ="" then [on]
        if elArray$( jk) <>penultimate$ then b$ =b$ +elArray$( jk) +" ": penultimate$ =elArray$( jk)
        [on]
    next jk
    b$ =trim$( b$)
    removeDupes$ =b$
end function

function stripBigSpaces$( a$)   '   copy byte by byte, but id=f a space had a preceding space, ignore it.
    lenA =len( a$)
    penul$ =""
    for i =1 to len( a$)
        c$ =mid$( a$, i, 1)
        if c$ <>" " then
            if penul$ <>" " then
                b$ =b$ +c$
            else
                b$ =b$ +" " +c$
            end if
        end if
        penul$ =c$
    next i
    stripBigSpaces$ =b$
end function

function countElements( a$) '   count elements repr'd by space-separated words in string rep'n.
    if isNul$( a$) ="True" then countElements =0: exit function
    i  =0
    do
        el$ =word$( a$, i +1, " ")
        i =i +1
    loop until el$ =""
    countElements =i -1
end function

function isNul$( a$)    '   a nul set implies its string rep'n is length zero.
    if a$ ="" then isNul$ ="True" else isNul$ ="False"
end function

function isAnElementOf$( a$, b$)    '   check element a$ exists in set b$.
    isAnElementOf$ ="False"
    i  =0
    do
        el$ =word$( b$, i +1, " ")
        if a$ =el$ then isAnElementOf$ ="True"
        i =i +1
    loop until el$ =""
end function

function unionOf$( a$, b$)
    i  =1
    o$ =a$
    do
        w$ =word$( b$, i, " ")
        if w$ ="" then exit do
        if isAnElementOf$( w$, a$) ="False" then o$ =o$ +" " +w$
        i =i +1
    loop until w$ =""
    unionOf$ =o$
end function

function intersectionOf$( a$, b$)
    i  =1
    o$ =""
    do
        el$ =word$( a$, i, " ")
        if el$ ="" then exit do
        if ( isAnElementOf$( el$, b$) ="True") and ( o$ ="")  then o$ =el$
        if ( isAnElementOf$( el$, b$) ="True") and ( o$ <>el$) then o$ =o$ +" " +el$
        i =i +1
    loop until el$ =""
    intersectionOf$ =o$
end function

function equalSets$( a$, b$)
    if len( a$) <>len( b$) then equalSets$ ="False": exit function
    i =1
    do
        el$ =word$( a$, i, " ")
        if isAnElementOf$( el$, b$) ="False" then equalSets$ ="False": exit function
        i =i +1
    loop until w$ =""
    equalSets$ ="True"
end function

function differenceOf$( a$, b$)
    i  =1
    o$ =""
    do
        el$ =word$( a$, i, " ")
        if el$ ="" then exit do
        if ( isAnElementOf$( el$, b$) ="False") and ( o$ ="")   then o$ =el$
        if ( isAnElementOf$( el$, b$) ="False") and ( o$ <>el$) then o$ =o$ +" " +el$
        i =i +1
    loop until el$ =""
    differenceOf$ =o$
end function

function isSubsetOf$( a$, b$)
    isSubsetOf$ ="True"
    i  =1
    do
        el$ =word$( a$, i, " ")
        if el$ ="" then exit do
        if ( isAnElementOf$( el$, b$) ="False") then isSubsetOf$ ="False": exit function
        i =i +1
    loop until el$ =""
end function


def divisors(n):
    divs = [1]
    for ii in range(2, int(n ** 0.5) + 3):
        if n % ii == 0:
            divs.append(ii)
            divs.append(int(n / ii))
    divs.append(n)
    return list(set(divs))

def is_prime(n):
    return len(divisors(n)) == 2

def primes():
    ii = 1
    while True:
        ii += 1
        if is_prime(ii):
            yield ii

def prime(n):
    generator = primes()
    for ii in range(n - 1):
        generator.__next__()
    return generator.__next__()

def n_divisors(n):
    ii = 0
    while True:
        ii += 1
        if len(divisors(ii)) == n:
            yield ii

def sequence(max_n=None):
    if max_n is not None:
        for ii in range(1, max_n + 1):
            if is_prime(ii):
                yield prime(ii) ** (ii - 1)
            else:
                generator = n_divisors(ii)
                for jj, out in zip(range(ii - 1), generator):
                    pass
                yield generator.__next__()
    else:
        ii = 1
        while True:
            ii += 1
            if is_prime(ii):
                yield prime(ii) ** (ii - 1)
            else:
                generator = n_divisors(ii)
                for jj, out in zip(range(ii - 1), generator):
                    pass
                yield generator.__next__()

if __name__ == '__main__':
    for item in sequence(15):
        print(item)


sub div-count (\x) {
    return 2 if x.is-prime;
    +flat (1 .. x.sqrt.floor).map: -> \d {
        unless x % d { my \y = x div d; y == d ?? y !! (y, d) }
    }
}

my $limit = 20;

my @primes = grep { .is-prime }, 1..*;
@primes[$limit]; # prime the array. SCNR

put "First $limit terms of OEIS:A073916";
put (1..$limit).hyper(:2batch).map: -> $n {
    ($n > 4 and $n.is-prime) ??
    exp($n - 1, @primes[$n - 1]) !!
    do {
        my $i = 0;
        my $iterator = $n %% 2 ?? (1..*) !! (1..*).map: *²;
        $iterator.first: {
            next unless $n == .&div-count;
            next unless ++$i == $n;
            $_
        }
    }
};


function emptySet()         return { }  end
function insert(set, item)  set[item] = true  end
function remove(set, item)  set[item] = nil  end
function member(set, item)  return set[item]  end
function size(set)
	local result = 0
	for _ in pairs(set) do result = result + 1 end
	return result
end
function fromTable(tbl) -- ignore the keys of tbl
	local result = { }
	for _, val in pairs(tbl) do
		result[val] = true
	end
	return result
end
function toArray(set)
	local result = { }
	for key in pairs(set) do
		table.insert(result, key)
	end
	return result
end
function printSet(set)
	print(table.concat(toArray(set), ", "))
end
function union(setA, setB)
	local result = { }
	for key, _ in pairs(setA) do
		result[key] = true
	end
	for key, _ in pairs(setB) do
		result[key] = true
	end
	return result
end
function intersection(setA, setB)
	local result = { }
	for key, _ in pairs(setA) do
		if setB[key] then
			result[key] = true
		end
	end
	return result
end
function difference(setA, setB)
	local result = { }
	for key, _ in pairs(setA) do
		if not setB[key] then
			result[key] = true
		end
	end
	return result
end
function subset(setA, setB)
	for key, _ in pairs(setA) do
		if not setB[key] then
			return false
		end
	end
	return true
end
function properSubset(setA, setB)
	return subset(setA, setB) and (size(setA) ~= size(setB))
end
function equals(setA, setB)
	return subset(setA, setB) and (size(setA) == size(setB))
end


/*REXX program  finds and displays  the    Nth  number   with exactly   N   divisors.   */
parse arg N .                                    /*obtain optional argument from the CL.*/
if N=='' | N==","  then N= 15                    /*Not specified?  Then use the default.*/
if N>=50  then numeric digits 10                 /*use more decimal digits for large N. */
w= 50                                            /*W:  width of the 2nd column of output*/
say '─divisors─'  center("the Nth number with exactly N divisors", w, '─')      /*title.*/
@.1= 2;                                   Ps= 1  /*1st prime;  number of primes (so far)*/
        do p=3  until Ps==N                      /* [↓]  gen N primes, store in @ array.*/
        if \isPrime(p)  then iterate;     Ps= Ps + 1;        @.Ps= p
        end   /*gp*/
!.=                                              /*the  !  array is used for memoization*/
        do i=1  for N;      odd= i//2            /*step through a number of divisors.   */
        if odd  then  if isPrime(i)  then do;  _= pPow();            w= max(w, length(_) )
                                               call tell  commas(_);              iterate
                                          end
        #= 0;            even= \odd              /*the number of occurrences for #div.  */
            do j=1;      jj= j                   /*now, search for a number that ≡ #divs*/
            if odd  then jj= j*j                 /*Odd and non-prime?  Calculate square.*/
            if !.jj==.  then iterate             /*has this number already been found?  */
            d= #divs(jj)                         /*get # divisors;  Is not equal?  Skip.*/
            if even  then if d<i  then do;  !.j=.;  iterate;  end   /*Too low?  Flag it.*/
            if d\==i  then iterate               /*Is not equal?  Then skip this number.*/
            #= # + 1                             /*bump number of occurrences for #div. */
            if #\==i  then iterate               /*Not correct occurrence? Keep looking.*/
            call tell  commas(jj)                /*display Nth number with #divs*/
            leave                                /*found a number, so now get the next I*/
            end   /*j*/
        end       /*i*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
commas: parse arg _;  do j=length(_)-3  to 1  by -3; _=insert(',', _, j); end;    return _
pPow:   numeric digits 1000;  return @.i**(i-1)  /*temporarily increase decimal digits. */
tell: parse arg _; say center(i,10) right(_,max(w,length(_))); if i//5==0 then say; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
#divs: procedure; parse arg x 1 y                /*X and Y:  both set from 1st argument.*/
       if x<7  then do                           /*handle special cases for numbers < 7.*/
                    if x<3   then return x       /*   "      "      "    "  one and two.*/
                    if x<5   then return x - 1   /*   "      "      "    "  three & four*/
                    if x==5  then return 2       /*   "      "      "    "  five.       */
                    if x==6  then return 4       /*   "      "      "    "  six.        */
                    end
       odd= x // 2                               /*check if   X   is  odd  or not.      */
       if odd  then do;  #= 1;             end   /*Odd?   Assume  Pdivisors  count of 1.*/
               else do;  #= 3;    y= x%2;  end   /*Even?     "        "        "    " 3.*/
                                                 /* [↑]   start with known num of Pdivs.*/
                  do k=3  by 1+odd  while k<y    /*when doing odd numbers,  skip evens. */
                  if x//k==0  then do            /*if no remainder, then found a divisor*/
                                   #=#+2;  y=x%k /*bump  #  Pdivs,  calculate limit  Y. */
                                   if k>=y  then do;  #= #-1;  leave;  end      /*limit?*/
                                   end                                          /*  ___ */
                              else if k*k>x  then leave        /*only divide up to √ x  */
                  end   /*k*/                    /* [↑]  this form of DO loop is faster.*/
       return #+1                                /*bump "proper divisors" to "divisors".*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
isPrime: procedure; parse arg #;         if wordpos(#, '2 3 5 7 11 13')\==0  then return 1
         if #<2  then return 0;    if #//2==0 | #//3==0 | #//5==0 | #//7==0  then return 0
                                         if # // 2==0 | # // 3    ==0  then return 0
           do j=11  by 6  until j*j>#;   if # // j==0 | # // (J+2)==0  then return 0
           end   /*j*/                           /*           ___                       */
         return 1                                /*Exceeded  √ #  ?    Then # is prime. */


Module Sets {
	setA=("apple", "cherry", "grape")
	setB=("banana","cherry", "date")

	Print Len(setA)=3 'true
	Print setA#pos("apple")>=0=true   ' exist
	Print setA#pos("banana")>=0=False  ' not exist

	intersection=lambda  SetB (x$)-> SetB#pos(x$)>=0
	SetC=SetA#filter(intersection,(,))
	Print SetC

	Difference= lambda (aSet)->{
		=lambda  aSet (x$)-> aSet#pos(x$)<0
	}
	IsetC=SetB#filter(Difference(setA),(,))
	Print SetC
	SetC=SetA#filter(Difference(setB),(,))
	Print SetC

	k=each(setB)
	SetC=cons(setA)
	while k
		if setA#pos(SetB#val$(k^))<0 then Append SetC, (SetB#val$(k^),)
	end while
	Print SetC
	\\ subset if items exists in same order
	Print SetA#pos("cherry","grape")>=0 ' true ' is a subset of SetA
	Print SetA#pos(("apple", "cherry"))>=0 ' true ' is a subset of SetA
	Print SetA#pos(("apple","grape"))>=0 ' false ' is not a subset of SetA in that order
	\\ subset in any position
	fold1=lambda (aSet)-> {
		=lambda aSet (x$, cond) ->{
			push cond and aSet#pos(x$)>=0
		}
	}
	SetC=("banana", "date")
	print SetC#Fold(fold1(SetA), True)  ' False
	print SetC#Fold(fold1(SetB), True)  ' True
	SetC=("cherry",)
	print SetC#Fold(fold1(SetA), True)  ' True
	print SetC#Fold(fold1(SetB), True)  ' True
	\\ Mutation
	\\ change value at position 0
	return SetC, 0:="banana"
	print SetC#Fold(fold1(SetA), True)  ' False
	print SetC#Fold(fold1(SetB), True)  ' True

	\\ equality
	SetC=Cons(SetA)  ' we get a copy of one or more tuple
	\\ SetC is subset of SetA and SetA is subset of  SetC
	Print SetC#Fold(fold1(SetA), True)=SetA#Fold(fold1(SetC), True)  ' True
	\\ another way
	Print Len(SetC#filter(Difference(setA),(,)))=0   ' true   \\ difference is an empty tuple
	append SetC, SetB
	Print Len(SetC)=6 ' true
	print SetC#pos(0 ->"cherry")=1 ' true
	print SetC#pos(2 -> "cherry")=4 ' true
	print SetC#pos(5 -> "cherry")=-1 ' true
	print SetC#pos(0 -> "banana","cherry")=3 ' true
	print SetC#pos( "banana","cherry")=3 ' true
	mapU=lambda ->{
		push ucase$(letter$)
	}
	fold2=lambda (x$, k$)->{
		push replace$(")(", ", ",k$+"("+quote$(x$)+")")
	}
	Print SetC#map(mapU)#fold$(fold2, "") ' ("APPLE", "CHERRY", "GRAPE", "BANANA", "CHERRY", "DATE")
	Print SetC#map(mapU)  ' APPLE CHERRY GRAPE BANANA CHERRY DATE
	Print SetC#fold$(fold2, "")  ' ("apple", "cherry", "grape", "banana", "cherry", "date")

}
Sets


load "stdlib.ring"

num = 0
limit = 22563490300366186081

see "working..." + nl
see "the first 15 terms of the sequence are:" + nl

for n = 1 to 15
    num = 0
    for m = 1 to limit
        pnum = 0
        for p = 1 to limit
            if (m % p = 0)
               pnum = pnum + 1
            ok
        next
        if pnum = n
           num = num + 1
           if num = n
              see "" + n + ": " + m + " " + nl
              exit
           ok
        ok
     next
next

see nl + "done..." + nl


def isPrime(n)
    return false if n < 2
    return n == 2 if n % 2 == 0
    return n == 3 if n % 3 == 0

    k = 5
    while k * k <= n
        return false if n % k == 0
        k = k + 2
    end

    return true
end

def getSmallPrimes(numPrimes)
    smallPrimes = [2]
    count = 0
    n = 3
    while count < numPrimes
        if isPrime(n) then
            smallPrimes << n
            count = count + 1
        end
        n = n + 2
    end
    return smallPrimes
end

def getDivisorCount(n)
    count = 1
    while n % 2 == 0
        n = (n / 2).floor
        count = count + 1
    end

    d = 3
    while d * d <= n
        q = (n / d).floor
        r = n % d
        dc = 0
        while r == 0
            dc = dc + count
            n = q
            q = (n / d).floor
            r = n % d
        end
        count = count + dc
        d = d + 2
    end
    if n != 1 then
        count = 2 * count
    end
    return count
end

MAX = 15
@smallPrimes = getSmallPrimes(MAX)

def OEISA073916(n)
    if isPrime(n) then
        return @smallPrimes[n - 1] ** (n - 1)
    end

    count = 0
    result = 0
    i = 1
    while count < n
        if n % 2 == 1 then
            # The solution for an odd (non-prime) term is always a square number
            root = Math.sqrt(i)
            if root * root != i then
                i = i + 1
                next
            end
        end
        if getDivisorCount(i) == n then
            count = count + 1
            result = i
        end
        i = i + 1
    end
    return result
end

n = 1
while n <= MAX
    print "A073916(", n, ") = ", OEISA073916(n), "\n"
    n = n + 1
end


func f(n {.is_prime}) {
    n.prime**(n-1)
}

func f(n) {
    n.th { .sigma0 == n }
}

say 20.of { f(_+1) }


import "/math" for Int
import "/big" for BigInt
import "/fmt" for Fmt

var MAX = 33
var primes = Int.primeSieve(MAX * 5)
System.print("The first %(MAX) terms in the sequence are:")
for (i in 1..MAX) {
    if (Int.isPrime(i)) {
        var z = BigInt.new(primes[i-1]).pow(i-1)
        Fmt.print("$2d : $i", i, z)
    } else {
        var count = 0
        var j = 1
        while (true) {
            var cont = false
            if (i % 2 == 1) {
                var sq = j.sqrt.floor
                if (sq * sq != j) {
                    j = j + 1
                    cont = true
                }
            }
            if (!cont) {
                if (Int.divisors(j).count == i) {
                    count = count + 1
                    if (count == i) {
                        Fmt.print("$2d : $d", i, j)
                        break
                    }
                }
                j = j + 1
            }
        }
    }
}


set1 = {"a", "b", "c", "d", "e"}; set2 = {"a", "b", "c", "d", "e", "f", "g"};
MemberQ[set1, "a"]
Union[set1 , set2]
Intersection[set1 , set2]
Complement[set2, set1](*Set Difference*)
MemberQ[Subsets[set2], set1](*Subset*)
set1 == set2(*Equality*)
set1 == set1(*Equality*)


    % Set creation
	s = [1, 2, 4];     % numeric values
	t = {'a','bb','ccc'}; % cell array of strings
        u = unique([1,2,3,3,2,3,2,4,1]);   % set consists only of unique elements
    % Test m ∈ S -- "m is an element in set S"
        ismember(m, S)
    % A ∪ B -- union; a set of all elements either in set A or in set B.
	union(A, B)
    % A ∩ B -- intersection; a set of all elements in both set A and set B.
	intersect(A, B)
    % A ∖ B -- difference; a set of all elements in set A, except those in set B.
	setdiff(A, B)
    % A ⊆ B -- subset; true if every element in set A is also in set B.
        all(ismember(A, B))
    % A = B -- equality; true if every element of set A is in set B and vice-versa.
        isempty(setxor(A, B))


var [const] BI=Import("zklBigNum"), pmax=25;  // libGMP
p:=BI(1);
primes:=pmax.pump(List(0), p.nextPrime, "copy");  //-->(0,3,5,7,11,13,17,19,...)

fcn countDivisors(n){
   count:=1;
   while(n%2==0){ n/=2; count+=1; }
   foreach d in ([3..*,2]){
      q,r := n/d, n%d;
      if(r==0){
	 dc:=0;
	 while(r==0){
	    dc+=count;
	    n,q,r = q, n/d, n%d;
	 }
	 count+=dc;
      }
      if(d*d > n) break;
   }
   if(n!=1) count*=2;
   count
}

println("The first ", pmax, " terms in the sequence are:");
foreach i in ([1..pmax]){
   if(BI(i).probablyPrime()) println("%2d : %,d".fmt(i,primes[i].pow(i-1)));
   else{
      count:=0;
      foreach j in ([1..*]){
         if(i%2==1 and j != j.toFloat().sqrt().toInt().pow(2)) continue;
	 if(countDivisors(j) == i){
	    count+=1;
	    if(count==i){
	       println("%2d : %,d".fmt(i,j));
	       break;
	    }
	 }
      }
   }
}