2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -2,7 +2,7 @@ Given two sets of items then if any item is common to any set then the result of
* 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.
<br>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:'''
@ -16,6 +16,7 @@ If N<2 then consolidation has no strict meaning and the input can be returned.
::<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:'''
<br>
'''See also'''
* [[wp:Connected component (graph theory)|Connected component (graph theory)]]
<br><br>

View file

@ -0,0 +1,107 @@
using System;
using System.Linq;
using System.Collections.Generic;
public class SetConsolidation
{
public static void Main()
{
var setCollection1 = new[] {new[] {"A", "B"}, new[] {"C", "D"}};
var setCollection2 = new[] {new[] {"A", "B"}, new[] {"B", "D"}};
var setCollection3 = new[] {new[] {"A", "B"}, new[] {"C", "D"}, new[] {"B", "D"}};
var setCollection4 = new[] {new[] {"H", "I", "K"}, new[] {"A", "B"}, new[] {"C", "D"},
new[] {"D", "B"}, new[] {"F", "G", "H"}};
var input = new[] {setCollection1, setCollection2, setCollection3, setCollection4};
foreach (var sets in input) {
Console.WriteLine("Start sets:");
Console.WriteLine(string.Join(", ", sets.Select(s => "{" + string.Join(", ", s) + "}")));
Console.WriteLine("Sets consolidated using Nodes:");
Console.WriteLine(string.Join(", ", ConsolidateSets1(sets).Select(s => "{" + string.Join(", ", s) + "}")));
Console.WriteLine("Sets consolidated using Set operations:");
Console.WriteLine(string.Join(", ", ConsolidateSets2(sets).Select(s => "{" + string.Join(", ", s) + "}")));
Console.WriteLine();
}
}
/// <summary>
/// Consolidates sets using a connected-component-finding-algorithm involving Nodes with parent pointers.
/// The more efficient solution, but more elaborate code.
/// </summary>
private static IEnumerable<IEnumerable<T>> ConsolidateSets1<T>(IEnumerable<IEnumerable<T>> sets,
IEqualityComparer<T> comparer = null)
{
if (comparer == null) comparer = EqualityComparer<T>.Default;
var elements = new Dictionary<T, Node<T>>();
foreach (var set in sets) {
Node<T> top = null;
foreach (T value in set) {
Node<T> element;
if (elements.TryGetValue(value, out element)) {
if (top != null) {
var newTop = element.FindTop();
top.Parent = newTop;
element.Parent = newTop;
top = newTop;
} else {
top = element.FindTop();
}
} else {
elements.Add(value, element = new Node<T>(value));
if (top == null) top = element;
else element.Parent = top;
}
}
}
foreach (var g in elements.Values.GroupBy(element => element.FindTop().Value))
yield return g.Select(e => e.Value);
}
private class Node<T>
{
public Node(T value, Node<T> parent = null) {
Value = value;
Parent = parent ?? this;
}
public T Value { get; }
public Node<T> Parent { get; set; }
public Node<T> FindTop() {
var top = this;
while (top != top.Parent) top = top.Parent;
//Set all parents to the top element to prevent repeated iteration in the future
var element = this;
while (element.Parent != top) {
var parent = element.Parent;
element.Parent = top;
element = parent;
}
return top;
}
}
/// <summary>
/// Consolidates sets using operations on the HashSet&lt;T&gt; class.
/// Less efficient than the other method, but easier to write.
/// </summary>
private static IEnumerable<IEnumerable<T>> ConsolidateSets2<T>(IEnumerable<IEnumerable<T>> sets,
IEqualityComparer<T> comparer = null)
{
if (comparer == null) comparer = EqualityComparer<T>.Default;
var currentSets = sets.Select(s => new HashSet<T>(s)).ToList();
int previousSize;
do {
previousSize = currentSets.Count;
for (int i = 0; i < currentSets.Count - 1; i++) {
for (int j = currentSets.Count - 1; j > i; j--) {
if (currentSets[i].Overlaps(currentSets[j])) {
currentSets[i].UnionWith(currentSets[j]);
currentSets.RemoveAt(j);
}
}
}
} while (previousSize > currentSets.Count);
foreach (var set in currentSets) yield return set.Select(value => value);
}
}

View file

@ -1,4 +1,9 @@
open console
open monad io
consolidate [['H','I','K'], ['A','B'], ['C','D'], ['D','B'], ['F','G','H']] |> writen $
consolidate [['A','B'], ['B','D']] |> writen
:::IO
do
x <- return $ consolidate [['H','I','K'], ['A','B'], ['C','D'], ['D','B'], ['F','G','H']]
putLn x
y <- return $ consolidate [['A','B'], ['B','D']]
putLn y

View file

@ -0,0 +1,23 @@
defmodule RC do
def set_consolidate(sets, result\\[])
def set_consolidate([], result), do: result
def set_consolidate([h|t], result) do
case Enum.find(t, fn set -> not MapSet.disjoint?(h, set) end) do
nil -> set_consolidate(t, [h | result])
set -> set_consolidate([MapSet.union(h, set) | t -- [set]], result)
end
end
end
examples = [[[:A,:B], [:C,:D]],
[[:A,:B], [:B,:D]],
[[:A,:B], [:C,:D], [:D,:B]],
[[:H,:I,:K], [:A,:B], [:C,:D], [:D,:B], [:F,:G,:H]]]
|> Enum.map(fn sets ->
Enum.map(sets, fn set -> MapSet.new(set) end)
end)
Enum.each(examples, fn sets ->
IO.write "#{inspect sets} =>\n\t"
IO.inspect RC.set_consolidate(sets)
end)

View file

@ -0,0 +1,47 @@
use strict;
use English;
use Smart::Comments;
my @ex1 = consolidate( (['A', 'B'], ['C', 'D']) );
### Example 1: @ex1
my @ex2 = consolidate( (['A', 'B'], ['B', 'D']) );
### Example 2: @ex2
my @ex3 = consolidate( (['A', 'B'], ['C', 'D'], ['D', 'B']) );
### Example 3: @ex3
my @ex4 = consolidate( (['H', 'I', 'K'], ['A', 'B'], ['C', 'D'], ['D', 'B'], ['F', 'G', 'H']) );
### Example 4: @ex4
exit 0;
sub consolidate {
scalar(@ARG) >= 2 or return @ARG;
my @result = ( shift(@ARG) );
my @recursion = consolidate(@ARG);
foreach my $r (@recursion) {
if (set_intersection($result[0], $r)) {
$result[0] = [ set_union($result[0], $r) ];
}
else {
push @result, $r;
}
}
return @result;
}
sub set_union {
my ($a, $b) = @ARG;
my %union;
foreach my $a_elt (@{$a}) { $union{$a_elt}++; }
foreach my $b_elt (@{$b}) { $union{$b_elt}++; }
return keys(%union);
}
sub set_intersection {
my ($a, $b) = @ARG;
my %a_hash;
foreach my $a_elt (@{$a}) { $a_hash{$a_elt}++; }
my @result;
foreach my $b_elt (@{$b}) {
push(@result, $b_elt) if exists($a_hash{$b_elt});
}
return @result;
}

View file

@ -1,52 +1,52 @@
/*REXX program demonstrates a method of consolidating some sample sets. */
/*REXX program demonstrates a method of consolidating some sample sets. */
@.=; @.1 = '{A,B} {C,D}'
@.2 = "{A,B} {B,D}"
@.3 = '{A,B} {C,D} {D,B}'
@.4 = '{H,I,K} {A,B} {C,D} {D,B} {F,G,H}'
@.5 = '{snow,ice,slush,frost,fog} {icebergs,icecubes} {rain,fog,sleet}'
do j=1 while @.j\=='' /*traipse through each of sample sets. */
call SETconsolidate @.j /*have the function do the heavy work. */
do j=1 while @.j\=='' /*traipse through each of sample sets. */
call SETconsolidate @.j /*have the function do the heavy work. */
end /*j*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────ISIN SUBRoutine───────────────────────────*/
isIn: return wordpos(arg(1), arg(2))\==0 /*is (word) arg1 in set arg2 ? */
/*──────────────────────────────────SETCONSOLIDATE subroutine─────────────────*/
SETconsolidate: procedure; parse arg old,new; #=words(old) /*nullify NEW.*/
say ' the old set=' space(old)
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
isIn: return wordpos(arg(1), arg(2))\==0 /*is (word) argument 1 in the set arg2?*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
SETconsolidate: procedure; parse arg old; #=words(old); new=
say ' the old set=' space(old)
do k=1 for # /* [↓] change all commas to a blank. */
!.k=translate(word(old,k), , '},{') /*create a list of words (aka, a set).*/
end /*k*/ /* [↑] ··· and also remove the braces.*/
do k=1 for # /* [↓] change all commas to a blank. */
!.k=translate(word(old,k), , '},{') /*create a list of words (aka, a set).*/
end /*k*/ /* [↑] ··· and also remove the braces.*/
do until \changed; changed=0 /*consolidate some sets (well, maybe).*/
do set=1 for #-1
do item=1 for words(!.set); x=word(!.set,item)
do other=set+1 to #
if isIn(x,!.other) then do; changed=1 /*has changed*/
!.set=!.set !.other; !.other=
iterate set
end
end /*other*/
end /*item */
end /*set */
end /*until*/
/* ╔╦══════════════════════════════════════════════════elide any duplicates.*/
do set=1 for #; $= /*nullify $ */
do items=1 for words(!.set); x=word(!.set, items)
if x==',' then iterate; if x=='' then leave
$=$ x /*build new. */
do until \isIn(x, !.set)
_=wordpos(x, !.set)
!.set=subword(!.set,1,_-1) ',' subword(!.set,_+1) /*purify set.*/
end /*until ¬isIn ··· */
end /*items*/
!.set=translate(strip($), ',', " ")
end /*set*/
do until \changed; changed=0 /*consolidate some sets (well, maybe).*/
do set=1 for #-1
do item=1 for words(!.set); x=word(!.set, item)
do other=set+1 to #
if isIn(x, !.other) then do; changed=1 /*it's changed*/
!.set=!.set !.other; !.other=
iterate set
end
end /*other*/
end /*item */
end /*set */
end /*until ¬changed*/
do i=1 for #; if !.i=='' then iterate
new=space(new '{'!.i"}")
end /*i*/
do set=1 for #; $= /*elide dups*/
do items=1 for words(!.set); x=word(!.set, items)
if x==',' then iterate; if x=='' then leave
$=$ x /*build new. */
do until \isIn(x, !.set)
_=wordpos(x, !.set)
!.set=subword(!.set, 1, _-1) ',' subword(!.set, _+1) /*purify set*/
end /*until ¬isIn ··· */
end /*items*/
!.set=translate(strip($), ',', " ")
end /*set*/
say ' the new set=' new; say
return
do i=1 for #; if !.i=='' then iterate /*ignore any set that is a null set. */
new=space(new '{'!.i"}") /*prepend and append a set identifier. */
end /*i*/
say ' the new set=' new; say
return

View file

@ -1,26 +1,25 @@
@(do
(defun mkset (p x) (set [p x] (or [p x] x)))
(defun mkset (p x) (set [p x] (or [p x] x)))
(defun fnd (p x) (if (eq [p x] x) x (fnd p [p x])))
(defun fnd (p x) (if (eq [p x] x) x (fnd p [p x])))
(defun uni (p x y)
(let ((xr (fnd p x)) (yr (fnd p y)))
(set [p xr] yr)))
(defun uni (p x y)
(let ((xr (fnd p x)) (yr (fnd p y)))
(set [p xr] yr)))
(defun consoli (sets)
(let ((p (hash)))
(each ((s sets))
(each ((e s))
(mkset p e)
(uni p e (car s))))
(hash-values
[group-by (op fnd p) (hash-keys
[group-by identity (flatten sets)])])))
(defun consoli (sets)
(let ((p (hash)))
(each ((s sets))
(each ((e s))
(mkset p e)
(uni p e (car s))))
(hash-values
[group-by (op fnd p) (hash-keys
[group-by identity (flatten sets)])])))
;; tests
;; tests
(each ((test '(((a b) (c d))
((a b) (b d))
((a b) (c d) (d b))
((h i k) (a b) (c d) (d b) (f g h)))))
(format t "~s -> ~s\n" test (consoli test))))
(each ((test '(((a b) (c d))
((a b) (b d))
((a b) (c d) (d b))
((h i k) (a b) (c d) (d b) (f g h)))))
(format t "~s -> ~s\n" test (consoli test)))

View file

@ -1,21 +1,20 @@
@(do
(defun mkset (items) [group-by identity items])
(defun mkset (items) [group-by identity items])
(defun empty-p (set) (zerop (hash-count set)))
(defun empty-p (set) (zerop (hash-count set)))
(defun consoli (ss)
(defun comb (cs s)
(cond ((empty-p s) cs)
((null cs) (list s))
((empty-p (hash-isec s (first cs)))
(cons (first cs) (comb (rest cs) s)))
(t (consoli (cons (hash-uni s (first cs)) (rest cs))))))
[reduce-left comb ss nil])
(defun consoli (ss)
(defun combi (cs s)
(cond ((empty-p s) cs)
((null cs) (list s))
((empty-p (hash-isec s (first cs)))
(cons (first cs) (combi (rest cs) s)))
(t (consoli (cons (hash-uni s (first cs)) (rest cs))))))
[reduce-left combi ss nil])
;; tests
(each ((test '(((a b) (c d))
((a b) (b d))
((a b) (c d) (d b))
((h i k) (a b) (c d) (d b) (f g h)))))
(format t "~s -> ~s\n" test
[mapcar hash-keys (consoli [mapcar mkset test])])))
;; tests
(each ((test '(((a b) (c d))
((a b) (b d))
((a b) (c d) (d b))
((h i k) (a b) (c d) (d b) (f g h)))))
(format t "~s -> ~s\n" test
[mapcar hash-keys (consoli [mapcar mkset test])]))