This method clusters some bitvectors based on their length. An example output is

        2: [0.5, 1]
        4: [1, 0.75, 1, 1]

        Meaning there were two message lengths: 2 and 4 bit.
        (0.5, 1) means, the first bit was equal in 50% of cases (meaning maximum difference) and bit 2 was equal in all messages

        A simple XOR would not work as it would be error prone.

        :rtype: dict[int, tuple[np.ndarray, int]]

def cluster_lengths(self):
        """
        This method clusters some bitvectors based on their length. An example output is

        2: [0.5, 1]
        4: [1, 0.75, 1, 1]

        Meaning there were two message lengths: 2 and 4 bit.
        (0.5, 1) means, the first bit was equal in 50% of cases (meaning maximum difference) and bit 2 was equal in all messages

        A simple XOR would not work as it would be error prone.

        :rtype: dict[int, tuple[np.ndarray, int]]
        """

        number_ones = dict()  # dict of tuple. 0 = number ones vector, 1 = number of blocks for this vector
        for vector in self.bitvectors:
            vec_len = 4 * (len(vector) // 4)
            if vec_len == 0:
                continue

            if vec_len not in number_ones:
                number_ones[vec_len] = [np.zeros(vec_len, dtype=int), 0]

            number_ones[vec_len][0] += vector[0:vec_len]
            number_ones[vec_len][1] += 1

        # Calculate the relative numbers and normalize the equalness so e.g. 0.3 becomes 0.7
        return {vl: (np.vectorize(lambda x: x if x >= 0.5 else 1 - x)(number_ones[vl][0] / number_ones[vl][1]))
                for vl in number_ones if number_ones[vl][1] >= self.MIN_MESSAGES_PER_CLUSTER}