Find ranges of True values in a list

Pyth, 18 bytes

CxR.:++~Zkz02_B_`T

Test suite

True is represented as 1, False as 0.

Ranges are represented inclusively.


Retina, 82 34 27 bytes

\b(?<=(.)*_?)
$#1
_+

S_`:

The empty line should contain a single space.

Input is a flat string of _ for true and : for false. Output is space-separated pairs, each on a separate line.

Try it online.

Explanation

The heavy golfing from 82 down to 27 bytes was possible by clever choice of the representation of true and false. I've picked a word character, _, (that isn't a digit) for true and a non-word character, :, (that doesn't need escaping) for false. That allows me to detect the ends of ranges as word boundaries.

\b(?<=(.)*_?)
$#1

We match a word boundary. We want to replace that boundary with the corresponding index of the truthy value. In principle that is quite easy with Retina's recent $# feature, which counts the number of captures of a group. We simply capture each character in front of that position into a group. By counting those characters we get the position. The only catch is that the ends of the range are off by one now. We actually want the index of the character in front the match. That is also easily fixed by optionally matching a _ which isn't captured, thereby skipping one character when we're at the end of a range.

_+
<space>

Now we replace all runs of underscores with a space. That is, we insert a space between the beginning and end of each range, while getting rid of the underscores.

S_`:

That leaves the colons (and we still need to separate pairs). We do that by splitting the entire string into lines around each colon. The S actives split mode, and the _ suppresses empty segments such that don't get tons of empty lines when we have runs of colons.


Pyth, 17 16 bytes

fT.b*Y,~+ZNtZrQ8

Uses some fancy post-assign counter magic together with run length encoding.

Takes input as an array of 0s and 1s, e.g. [1, 1, 0, 1, 0]. Outputs like in the challenge, e.g. [[0, 1], [3, 3]].

Test Suite