Set consolidation: Difference between revisions

From Rosetta Code
Content added Content deleted
No edit summary
m (tidy up task description)
Line 1: Line 1:
{{task}}
{{task}}
Given two sets of items then if any item is common to any set then the result of applying ''consolidation'' to those sets is a set of sets whose contents is:
See also:
* The two input sets if no common item exists between the two input sets of items.
* The single set that is the union of the two input sets if they share a common item.


Given N sets of items where N>2 then the result is the same as repeatedly replacing all combinations of two sets by their consolidation until no further consolidation between set pairs is possible.
Given two sets of items then if any item is common to any set then
the result of applying consolidation to those sets is:
If N<2 then consolidation has no strict meaning and the input can be returned.
* The two input sets if no common item exists between those two sets of items.
* Or one set of all the items from both sets if they share a common item.
Given N sets of items where N>=2 then the result is the same as repeatedly
replacing all combinations of two sets by their consolidation
until no further consolidation between set pairs is possible.
If N<2 then consolidation has no meaning and the input can be returned.


;'''Example 1:'''
:Given the two sets <tt>{A,B}</tt> and <tt>{C,D}</tt> then there is no common element between the sets and the result is the same as the input.
;'''Example 2:'''
:Given the two sets <tt>{A,B}</tt> and <tt>{B,D}</tt> then there is a common element <tt>B</tt> between the sets and the result is the single set <tt>{B,D,A}</tt>. (Note that order of items in a set is immaterial: <tt>{A,B,D}</tt> is the same as <tt>{B,D,A} and <tt>{D,A,B}</tt>, etc).
;'''Example 3:'''
:Given the three sets <tt>{A,B}</tt> and <tt>{C,D}</tt> and <tt>{D,B}</tt> then there is no common element between the sets <tt>{A,B}</tt> and <tt>{C,D}</tt> but the sets <tt>{A,B}</tt> and <tt>{D,B}</tt> do share a common element that consolidates to produce the result <tt>{B,D,A}</tt>. On examining this result with the remaining set, <tt>{C,D}</tt>, they share a common element and so consolidate to the final output of the single set <tt>{A,B,C,D}</tt>
;'''Example 4:'''
:The consolidation of the five sets:
::<tt>{H,I,K}</tt>, <tt>{A,B}</tt>, <tt>{C,D}</tt>, <tt>{D,B}</tt>, and <tt>{F,G,H}</tt>
:Is the two sets:
::<tt>{A, C, B, D}</tt>, and <tt>{G, F, I, H, K}</tt>


'''See also:'''

'''Example 1:'''<br>
Given the two sets {A,B} and {C,D} then there is no common
element between the sets and the result is the same as the
input.
'''Example 2:'''<br>
Given the two sets {A,B} and {B,D} then there is a common
element B between the sets and the result is the set {B,D,A}.
(Note that order of items in a set is immaterial - {A,B,D} is
the same as {B,D,A} and {D,A,B} etc).

'''Example 3:'''<br>
Given the three sets {A,B} and {C,D} and {D,B} then there is no
common element between the sets {A,B} and {C,D} but the sets
{A,B} and and {D,B} do share a common element that
consolidates to produce the result {B,D,A}.
On examining this result with the remaining set {C,D} they
share a common element and so consolidate to the final output
of the single set {A,B,C,D}

'''Example 4:'''<br>
The consolidation of the five sets:
{H,I,K}, {A,B}, {C,D}, {D,B}, and {F,G,H}
Is the two sets:
{'A', 'C', 'B', 'D'}, and {'G', 'F', 'I', 'H', 'K'}


=={{header|Ela}}==
=={{header|Ela}}==

This solution emulate sets using linked lists:
This solution emulate sets using linked lists:

<lang ela>open Core
<lang ela>open Core


Line 55: Line 34:
conso (x::xs)@r (y::ys) | intersect x y <> [] = conso ((merge x y)::xs) ys
conso (x::xs)@r (y::ys) | intersect x y <> [] = conso ((merge x y)::xs) ys
| else = conso (r ++ [y]) ys</lang>
| else = conso (r ++ [y]) ys</lang>

Usage:
Usage:


In this example sets are filled with variants (somewhat similar to atoms in Lisp). One can use any other values (such as strings or chars) as well.
In this example sets are filled with variants (somewhat similar to atoms in Lisp). One can use any other values (such as strings or chars) as well.

<lang ela>open Con
<lang ela>open Con


consolidate [[H,I,K], [A,B], [C,D], [D,B], [F,G,H]] |> writen $
consolidate [[H,I,K], [A,B], [C,D], [D,B], [F,G,H]] |> writen $
consolidate [[A,B], [B,D]] |> writen
consolidate [[A,B], [B,D]] |> writen</lang>
</lang>

{{out}}
{{out}}

<pre>[[K,I,F,G,H],[A,C,D,B]]
<pre>[[K,I,F,G,H],[A,C,D,B]]
[[A,B,D]]</pre>
[[A,B,D]]</pre>
Line 133: Line 107:
[map[A:true C:true B:true D:true] map[G:true F:true I:true H:true K:true]]
[map[A:true C:true B:true D:true] map[G:true F:true I:true H:true K:true]]
</pre>
</pre>

=={{header|Python}}==
=={{header|Python}}==
===Iterative===
===Iterative===
Line 177: Line 152:
s1.clear()
s1.clear()
s1 = s2
s1 = s2
return [s for s in setlist if s]
return [s for s in setlist if s]</lang>
</lang>


===Recursive===
===Recursive===
Line 188: Line 162:
if r[0].intersection(x): r[0].update(x)
if r[0].intersection(x): r[0].update(x)
else: r.append(x)
else: r.append(x)
return r
return r</lang>
</lang>

Revision as of 19:23, 10 May 2012

Task
Set consolidation
You are encouraged to solve this task according to the task description, using any language you may know.

Given two sets of items then if any item is common to any set then the result of applying consolidation to those sets is a set of sets whose contents is:

  • The two input sets if no common item exists between the two input sets of items.
  • The single set that is the union of the two input sets if they share a common item.

Given N sets of items where N>2 then the result is the same as repeatedly replacing all combinations of two sets by their consolidation until no further consolidation between set pairs is possible. If N<2 then consolidation has no strict meaning and the input can be returned.

Example 1:
Given the two sets {A,B} and {C,D} then there is no common element between the sets and the result is the same as the input.
Example 2:
Given the two sets {A,B} and {B,D} then there is a common element B between the sets and the result is the single set {B,D,A}. (Note that order of items in a set is immaterial: {A,B,D} is the same as {B,D,A} and {D,A,B}, etc).
Example 3:
Given the three sets {A,B} and {C,D} and {D,B} then there is no common element between the sets {A,B} and {C,D} but the sets {A,B} and {D,B} do share a common element that consolidates to produce the result {B,D,A}. On examining this result with the remaining set, {C,D}, they share a common element and so consolidate to the final output of the single set {A,B,C,D}
Example 4:
The consolidation of the five sets:
{H,I,K}, {A,B}, {C,D}, {D,B}, and {F,G,H}
Is the two sets:
{A, C, B, D}, and {G, F, I, H, K}

See also:

Ela

This solution emulate sets using linked lists: <lang ela>open Core

let merge [] ys = ys

   merge (x::xs) ys | x `elem` ys = merge xs ys
                    | else = merge xs (x::ys)

let consolidate (_::[])@xs = xs

   consolidate (x::xs) = conso [x] (consolidate xs)
                   where conso xs [] = xs
                         conso (x::xs)@r (y::ys) | intersect x y <> [] = conso ((merge x y)::xs) ys
                                                 | else = conso (r ++ [y]) ys</lang>

Usage:

In this example sets are filled with variants (somewhat similar to atoms in Lisp). One can use any other values (such as strings or chars) as well. <lang ela>open Con

consolidate [[H,I,K], [A,B], [C,D], [D,B], [F,G,H]] |> writen $ consolidate [[A,B], [B,D]] |> writen</lang>

Output:
[[K,I,F,G,H],[A,C,D,B]]
[[A,B,D]]

Go

Translation of: Python

<lang go>package main

import "fmt"

type set map[string]bool

var testCase = []set{

   set{"H": true, "I": true, "K": true},
   set{"A": true, "B": true},
   set{"C": true, "D": true},
   set{"D": true, "B": true},
   set{"F": true, "G": true, "H": true},

}

func main() {

   fmt.Println(consolidate(testCase))

}

func consolidate(sets []set) []set {

   setlist := []set{}
   for _, s := range sets {
       if s != nil && len(s) > 0 {
           setlist = append(setlist, s)
       }
   }
   for i, s1 := range setlist {
       if len(s1) > 0 {
           for _, s2 := range setlist[i+1:] {
               if s1.disjoint(s2) {
                   continue
               }
               for e := range s1 {
                   s2[e] = true
                   delete(s1, e)
               }
               s1 = s2
           }
       }
   }
   r := []set{}
   for _, s := range setlist {
       if len(s) > 0 {
           r = append(r, s)
       }
   }
   return r

}

func (s1 set) disjoint(s2 set) bool {

   for e := range s2 {
       if s1[e] {
           return false
       }
   }
   return true

}</lang>

Output:
[map[A:true C:true B:true D:true] map[G:true F:true I:true H:true K:true]]

Python

Iterative

The docstring contains solutions to all the examples as well as a check to show the order-independence of the sets given to the consolidate function. <lang python>def consolidate(sets):

   
   >>> # Define some variables
   >>> A,B,C,D,E,F,G,H,I,J,K = 'A,B,C,D,E,F,G,H,I,J,K'.split(',')
   >>> # Consolidate some lists of sets
   >>> consolidate([{A,B}, {C,D}])
   [{'A', 'B'}, {'C', 'D'}]
   >>> consolidate([{A,B}, {B,D}])
   [{'A', 'B', 'D'}]
   >>> consolidate([{A,B}, {C,D}, {D,B}])
   [{'A', 'C', 'B', 'D'}]
   >>> consolidate([{H,I,K}, {A,B}, {C,D}, {D,B}, {F,G,H}])
   [{'A', 'C', 'B', 'D'}, {'G', 'F', 'I', 'H', 'K'}]
   >>> consolidate([{A,H}, {H,I,K}, {A,B}, {C,D}, {D,B}, {F,G,H}])
   [{'A', 'C', 'B', 'D', 'G', 'F', 'I', 'H', 'K'}]
   >>> consolidate([{H,I,K}, {A,B}, {C,D}, {D,B}, {F,G,H}, {A,H}])
   [{'A', 'C', 'B', 'D', 'G', 'F', 'I', 'H', 'K'}]
   >>> # Confirm order-independence
   >>> from copy import deepcopy
   >>> import itertools
   >>> sets = [{H,I,K}, {A,B}, {C,D}, {D,B}, {F,G,H}, {A,H}]
   >>> answer = consolidate(deepcopy(sets))
   >>> for perm in itertools.permutations(sets):
           assert consolidate(deepcopy(perm)) == answer


   >>> answer
   [{'A', 'C', 'B', 'D', 'G', 'F', 'I', 'H', 'K'}]
   >>> len(list(itertools.permutations(sets)))
   720
   >>>     
   
   setlist = [s for s in sets if s]
   for i, s1 in enumerate(setlist):
       if s1:
           for s2 in setlist[i+1:]:
               intersection = s1.intersection(s2)
               if intersection:
                   s2.update(s1)
                   s1.clear()
                   s1 = s2
   return [s for s in setlist if s]</lang>

Recursive

<lang python>def conso(s): if len(s) < 2: return s

r, b = [s[0]], conso(s[1:]) for x in b: if r[0].intersection(x): r[0].update(x) else: r.append(x) return r</lang>