#+title: Task 4: Decomposing a Set into Intervals

#+author: JirR02
* Task
:PROPERTIES:
:CUSTOM_ID: task
:END:
Any finite set of integers can be uniquely decomposed as a union of
disjoint maximal integer intervals, e.g as the union of non-overlapping
intervals which are as large as possible. For example, the set
\(X = \{ 1,2,3,5,6,8 \}\) decomposes as
\(X = [1,3] cup [5,6] cup [8,8]\). Note that
\(X = [1,2] cup [3,3] cup [5,6] cup [8,8]\) or
\(X = [1,2] cup [5,6] cup [5,6] cup [8,9]\) are not valid
decompositions, as \([1,2]\) and \([3,3]\) are not maximal interval
subsets of , and intervals may not repeat.

Write a program that inputs a set of integers, as the (possibly
repeating) sequence of its members, and outputs the interval
decomposition of the set in ascending order of boundaries.

/Reminder/: ordered sets can be represented in C++ using the
=std::set<...>= container, in which elements are added using the
=insert= method. Iteration (using iterators) in ordered sets takes place
in increasing order.

=Hint=: You may first define a function that, from two =std::set=
iterators =first= and =last=, finds the largest integer interval
starting from =first= and ending before =last=, and returns an iterator
just after this interval.

* Input
:PROPERTIES:
:CUSTOM_ID: input
:END:
A set of non-negative integer, given as the sequence of its members
followed by a negative integer. The sequence can be in any order and may
feature repetitions.

Example:

#+begin_src shell
3 5 8 6 5 3 2 1 -1
#+end_src

* Output
:PROPERTIES:
:CUSTOM_ID: output
:END:
The interval decomposition of the input set, with interval given in
increasing order of boundaries. The interval decomposition must be given
as a parenthesized sequence of intervals, with intervals separated by
the character U. Intervals themselves must be given by their lower and
upper bound, separated by a comma and parenthesized by brackets, with
the lower bound coming first.

Example:

#+begin_src shell
([1,3]U[5,6]U[8,8])
#+end_src

* Solution
:PROPERTIES:
:CUSTOM_ID: solution
:END:
#+begin_src cpp
#include <iostream>
#include <set>

using namespace std;

void find_interval(set<int>::iterator &first, set<int>::iterator &last,
                   set<pair<int, int>> &Interval) {
  if (first == last)
    return;

  int firstElement = *first;
  int curElement = *first;

  while ((++first != last) && (*first - curElement <= 1)) {
    curElement = *first;
  }

  pair<int, int> curInterval = {firstElement, curElement};
  Interval.insert(curInterval);

  find_interval(first, last, Interval);
}

int main() {
  int in;
  set<int> Set;
  set<pair<int, int>> Interval;

  cin >> in;

  while (in >= 0) {
    Set.insert(in);
    cin >> in;
  }

  set<int>::iterator first = Set.begin();
  set<int>::iterator last = Set.end();

  find_interval(first, last, Interval);

  int size = Interval.size();
  int count = 1;

  cout << "(";
  for (pair<int, int> h : Interval) {
    cout << "[" << h.first << "," << h.second;
    if (count < size)
      cout << "]" << "U";
    else
      cout << "]";
    ++count;
  }
  cout << ")";

  return 0;
}
#+end_src

  --------------

  Made by JirR02 in Switzerland 🇨🇭
