dpaukov / combinatoricslib3

Combinatorial objects stream generators for Java.
Apache License 2.0
177 stars 24 forks source link

Subsets number #17

Closed ghYura closed 2 years ago

ghYura commented 2 years ago

Please, implement Subsets-(and other - also useful) generator limitation number, i.e.:

BEFORE:

   Generator.subset("one", "two", "three")
        .simple()
        .before(2)//
        .stream()
        .forEach(System.out::println);
   []
   [one]
   [two]
   [three]

AFTER:

   Generator.subset("one", "two", "three")
        .simple()
        .after(1)//
        .stream()
        .forEach(System.out::println);
   [one, two]
   [one, three]
   [two, three]
   [one, two, three]

STRICT or EXACT:

   Generator.subset("one", "two", "three")
        .simple()
        .strict(2)//.exact(2)
        .stream()
        .forEach(System.out::println);
   [one, two]
   [one, three]
   [two, three]

GIVEN:

   Generator.subset("one", "two", "three")
        .simple()
        .given(1, 3)//
        .stream()
        .forEach(System.out::println);
   [one]
   [two]
   [three]
   [one, two, three]

RANGE:

   Generator.subset("one", "two", "three")
        .simple()
        .range(1, 3)//
        .stream()
        .forEach(System.out::println);
   [one]
   [two]
   [one, two]
   [three]
   [one, three]
   [two, three]
   [one, two, three]
dpaukov commented 2 years ago

You can achieve the same result by using the existing simple combination generator. If you need to generate all subsets that have an exact number of elements, you can use Generator.combination(array).simple(number). You can adapt this approach to generate all subsets ordered by the number of elements. For example, the following method (that is based on the combination generator) can generate all the requested sequences:

static <T> void orderedSubSets(T[] arr, int start, int end) {
     assert(start >= 0);
     assert(end <= arr.length);
     IntStream.rangeClosed(start, end)
         .forEach(i -> Generator.combination(arr)
             .simple(i)
             .stream()
             .forEach(System.out::println));
 }

Assuming we have an array of 3 elements String[] arr = new String[]{"one", "two", "three"};

BEFORE:

// all subsets before 2
orderedSubSets(arr, 0, 1);
[]
[one]
[two]
[three]

AFTER:

// all subsets after 1
orderedSubSets(arr, 2, arr.length);
[one, two]
[one, three]
[two, three]
[one, two, three]

STRICT or EXACT:

// all subsets of size 2
orderedSubSets(arr, 2, 2);
[one, two]
[one, three]
[two, three]

RANGE:

// all subsets of size 1 to 3
orderedSubSets(arr, 1, 3);
[one]
[two]
[three]
[one, two]
[one, three]
[two, three]
[one, two, three]

GIVEN: In this case the method can be either called several times as 'strict' or IntStream.rangeClosed(start, end) can be changed to IntStream.of(int... values) with the given numbers

static <T> void givenSubSets(T[] arr, int... given) {
     IntStream.of(given)
         .forEach(i -> Generator.combination(arr)
             .simple(i)
             .stream()
             .forEach(System.out::println));
}
givenSubSets(arr, 1, 3);
[one]
[two]
[three]
[one, two, three]
dpaukov commented 2 years ago

I assume I can close this issue.