2015-01-22 5 views
1

У меня есть список наборов:Как найти список всех пересечений нескольких множеств в Java?

setlist = [s1,s2,s3...sn] 

Я хочу все сравнения пути множеств, которая 2^п числа множеств:

setIntersection = [s1 ∩ s2, s1 ∩ s2 ∩ s3, ....., s2 ∩ s3 ∩ s4, ...., sn-1 ∩ sn] 

Что бы быть лучшим способом сделать это в Java?

Например, если я использовал только 5 комплектов. Я хотел бы быть в состоянии заполнить все перехлеста в 5 circle venn diagram.

Я пытаюсь сделать это с помощью списка наборов:

List<Set<People>> lListSets = new ArrayList<Set<People>>(); 
for (DaysObject day : listOfDaysInJanuary) { 
     lListSets.add(day.peopleOneInternet()); 
} 
findPowerSetsAndCompare(lListSets, listOfDaysInJanuary); 

Я хотел бы найти какой-то результат, как:

January 1 (Bob, Sally, Tommy) 
January 1, January 2 (Sally, Tommy) 
... 
so on for all possible combination of days. 

По существу, я спрашиваю, как применить powerset algorithm в сочетании с объединением набора.

+0

Вы пытались использовать пару простых циклов (внешний для проверки всех возможных масок, внутренних для вычисления пересечения)? – kraskevich

+0

Кажется, что это будет очень сложно. – Whitecat

+0

Я так не думаю. Это буквально всего два цикла, один оператор if, чтобы проверить, установлен ли бит в маске, и метод, который находит пересечение двух наборов. – kraskevich

ответ

4

Что было бы лучшим способом сделать это на Java?

Первая часть, которую вы описываете, - это powerset (так как я отредактировал ваш вопрос, чтобы включить на прошлой неделе). Затем вы получите пересечение для каждого набора множеств в силовом наборе.

Поскольку вы выполняете набор наборов функций, а не простой силовой набор чего-то вроде целых чисел, реализация будет немного более сложной.

Extra Credit

Я написал основную реализацию ваших требований, в качестве примера того, как вы могли бы это сделать. Все методы и типы в этом примере являются членами класса Example.

Пример класс с его методом main, который демонстрирует рабочий код. Я уверен, вы простите мне использование устаревших конструкторов Date для демонстрации.

import java.text.*; 
import java.util.*; 

public class Example 
{ 
    public static void main(String[] args) { 
     // create simple test harness 
     Set<PeopleByDays> peepsByDay = new HashSet<PeopleByDays>(); 
     peepsByDay.add(new PeopleByDays(new Date(2015 - 1900, Calendar.JANUARY, 1), 
      Person.BOB, Person.FRANK, Person.JIM, Person.JUDY, Person.SALLY)); 
     peepsByDay.add(new PeopleByDays(new Date(2015 - 1900, Calendar.JANUARY, 2), 
      Person.BOB, Person.FRANK, Person.JIM, Person.JUDY, Person.TOMMY)); 
     peepsByDay.add(new PeopleByDays(new Date(2015 - 1900, Calendar.JANUARY, 3), 
      Person.BOB, Person.FRANK, Person.JIM, Person.SALLY, Person.TOMMY)); 
     peepsByDay.add(new PeopleByDays(new Date(2015 - 1900, Calendar.JANUARY, 4), 
      Person.BOB, Person.FRANK, Person.JUDY, Person.SALLY, Person.TOMMY)); 
     peepsByDay.add(new PeopleByDays(new Date(2015 - 1900, Calendar.JANUARY, 5), 
      Person.BOB, Person.JIM, Person.JUDY, Person.SALLY, Person.TOMMY)); 

     // make powerSet, then intersect, then sort 
     Set<Set<PeopleByDays>> powerPeeps = powerSet(peepsByDay); 
     List<PeopleByDays> powerPeepsIntersected = intersect(powerPeeps); 
     sort(powerPeepsIntersected); 

     // print out results 
     for (PeopleByDays peeps: powerPeepsIntersected) { 
      String daysFormatted = format(peeps.getDays()); 
      System.out.print(daysFormatted); 
      System.out.println(peeps); 
     } 
    } 

    // all other Example members as defined in this answer 
} 

Человек простой enum типа для имен людей. Преимущество использования перечисления здесь заключается в том, что он позаботится о соответствующих equals() и hashCode() реализациях для желаемого поведения HashSet.

static enum Person { 
     BOB, FRANK, JIM, JUDY, SALLY, TOMMY; 
    } 

PeopleByDays расширяет HashSet<Person> собрать дополнительный набор Date объектов для представления дни. Переопределяет retainAll() (пересекается) для объединения дней; переопределяет equals() и hashSet() для правильного поведения во внешнем наборе.

static class PeopleByDays extends HashSet<Person> { 
     private final Set<Date> days = new HashSet<Date>(); 

     public PeopleByDays() { 
      super(); 
     } 
     public PeopleByDays(Date day, Person... people) { 
      super(Arrays.asList(people)); 
      this.days.add(day); 
     } 
     public PeopleByDays(PeopleByDays other) { 
      super(other); 
      this.days.addAll(other.days); 
     } 

     public List<Date> getDays() { 
      return new ArrayList<Date>(this.days); 
     } 

     @Override 
     public boolean retainAll(Collection<?> c) { 
      if (c instanceof PeopleByDays) { 
       this.days.addAll(((PeopleByDays)c).days); 
      } 
      return super.retainAll(c); 
     } 

     @Override 
     public boolean equals(Object o) { 
      return super.equals(o) && this.days.equals(((PeopleByDays) o).days); 
     } 
     @Override 
     public int hashCode() { 
      return super.hashCode() + this.days.hashCode(); 
     } 
    } 

POWERSET() метод, взятый дословно из this answer.

public static <T> Set<Set<T>> powerSet(Set<T> originalSet) { 
     Set<Set<T>> sets = new HashSet<Set<T>>(); 
     if (originalSet.isEmpty()) { 
      sets.add(new HashSet<T>()); 
      return sets; 
     } 
     List<T> list = new ArrayList<T>(originalSet); 
     T head = list.get(0); 
     Set<T> rest = new HashSet<T>(list.subList(1, list.size())); 
     for (Set<T> set: powerSet(rest)) { 
      Set<T> newSet = new HashSet<T>(); 
      newSet.add(head); 
      newSet.addAll(set); 
      sets.add(newSet); 
      sets.add(set); 
     } 
     return sets; 
    } 

пересекаются() метод создания пересечения для каждого набора множеств в Powerset.

static List<PeopleByDays> intersect(Set<Set<PeopleByDays>> powerSet) { 
     List<PeopleByDays> intersected = new ArrayList<PeopleByDays>(); 
     for (Set<PeopleByDays> powerElement: powerSet) { 
      PeopleByDays intersection = null; 
      if (powerElement.isEmpty()) { 
       intersection = new PeopleByDays(); 
      } else for (PeopleByDays peeps: powerElement) { 
       if (intersection == null) { 
        intersection = new PeopleByDays(peeps); 
       } else { 
        intersection.retainAll(peeps); 
       } 
      } 
      intersected.add(intersection); 
     } 
     return intersected; 
    } 

сортировки() способ сортировки наборов пересекались в результате чего по дате.

static void sort(List<PeopleByDays> peeps) { 
     Collections.sort(peeps, new Comparator<PeopleByDays>() { 
      @Override 
      public int compare(PeopleByDays p1, PeopleByDays p2) { 
       List<Date> days1 = p1.getDays(); 
       List<Date> days2 = p2.getDays(); 
       Collections.sort(days1); 
       Collections.sort(days2); 
       for (int i = 0; i < days1.size() && i < days2.size(); i++) { 
        int compare = days1.get(i).compareTo(days2.get(i)); 
        if (compare != 0) { 
         return compare; 
        } 
       } 
       return days1.size() - days2.size(); 
      } 
     }); 
    } 

формат) метод (форматировать список дней для каждого перекрестка.

static String format(List<Date> days) { 
     if (days.isEmpty()) { 
      return ""; 
     } 
     StringBuilder sb = new StringBuilder(); 
     DateFormat format = new SimpleDateFormat("MMM d"); 
     Collections.sort(days); 
     String separator = ""; 
     for (Date day: days) { 
      sb.append(separator); 
      sb.append(format.format(day)); 
      separator = ", "; 
     } 
     sb.append(" "); 
     return sb.toString(); 
    } 

И, наконец, выход.

[] 
Jan 1 [BOB, JUDY, FRANK, JIM, SALLY] 
Jan 1, Jan 2 [BOB, JUDY, FRANK, JIM] 
Jan 1, Jan 2, Jan 3 [BOB, FRANK, JIM] 
Jan 1, Jan 2, Jan 3, Jan 4 [BOB, FRANK] 
Jan 1, Jan 2, Jan 3, Jan 4, Jan 5 [BOB] 
Jan 1, Jan 2, Jan 3, Jan 5 [BOB, JIM] 
Jan 1, Jan 2, Jan 4 [BOB, JUDY, FRANK] 
Jan 1, Jan 2, Jan 4, Jan 5 [BOB, JUDY] 
Jan 1, Jan 2, Jan 5 [BOB, JUDY, JIM] 
Jan 1, Jan 3 [BOB, FRANK, JIM, SALLY] 
Jan 1, Jan 3, Jan 4 [BOB, FRANK, SALLY] 
Jan 1, Jan 3, Jan 4, Jan 5 [BOB, SALLY] 
Jan 1, Jan 3, Jan 5 [BOB, JIM, SALLY] 
Jan 1, Jan 4 [BOB, JUDY, FRANK, SALLY] 
Jan 1, Jan 4, Jan 5 [BOB, JUDY, SALLY] 
Jan 1, Jan 5 [BOB, JUDY, JIM, SALLY] 
Jan 2 [BOB, JUDY, TOMMY, FRANK, JIM] 
Jan 2, Jan 3 [BOB, TOMMY, FRANK, JIM] 
Jan 2, Jan 3, Jan 4 [BOB, TOMMY, FRANK] 
Jan 2, Jan 3, Jan 4, Jan 5 [BOB, TOMMY] 
Jan 2, Jan 3, Jan 5 [BOB, TOMMY, JIM] 
Jan 2, Jan 4 [BOB, JUDY, TOMMY, FRANK] 
Jan 2, Jan 4, Jan 5 [BOB, JUDY, TOMMY] 
Jan 2, Jan 5 [BOB, JUDY, TOMMY, JIM] 
Jan 3 [BOB, TOMMY, FRANK, JIM, SALLY] 
Jan 3, Jan 4 [BOB, TOMMY, FRANK, SALLY] 
Jan 3, Jan 4, Jan 5 [BOB, TOMMY, SALLY] 
Jan 3, Jan 5 [BOB, TOMMY, JIM, SALLY] 
Jan 4 [BOB, JUDY, TOMMY, FRANK, SALLY] 
Jan 4, Jan 5 [BOB, JUDY, TOMMY, SALLY] 
Jan 5 [BOB, JUDY, TOMMY, JIM, SALLY] 

Надеюсь, что это поможет. Я возился с ним намного дольше, чем я предполагал;) Тем не менее, не отсортировал имена Person на выходе.

+2

Ты много работал. Это потрясающе! – Whitecat

+1

Рад помочь :) Кроме того, это весело. – gknicker

 Смежные вопросы

  • Нет связанных вопросов^_^