def test_sequencetools_repeat_sequence_to_weight_at_most_01(): assert sequencetools.repeat_sequence_to_weight_at_most([5, -5, -5], 23) == [5, -5, -5, 5]
def split_sequence_by_weights(sequence, weights, cyclic=False, overhang=False): '''Split sequence by weights. .. container:: example **Example 1.** Split sequence cyclically by weights with overhang: :: >>> sequencetools.split_sequence_by_weights( ... (10, -10, 10, -10), ... (3, 15, 3), ... cyclic=True, ... overhang=True, ... ) [(3,), (7, -8), (-2, 1), (3,), (6, -9), (-1,)] .. container:: example **Example 2.** Split sequence cyclically by weights without overhang: :: >>> sequencetools.split_sequence_by_weights( ... (10, -10, 10, -10), ... (3, 15, 3), ... cyclic=True, ... overhang=False, ... ) [(3,), (7, -8), (-2, 1), (3,), (6, -9)] .. container:: example **Example 3.** Split sequence once by weights with overhang: :: >>> sequencetools.split_sequence_by_weights( ... (10, -10, 10, -10), ... (3, 15, 3), ... cyclic=False, ... overhang=True, ... ) [(3,), (7, -8), (-2, 1), (9, -10)] .. container:: example **Example 4.** Split sequence once by weights without overhang: :: >>> sequencetools.split_sequence_by_weights( ... (10, -10, 10, -10), ... (3, 15, 3), ... cyclic=False, ... overhang=False, ... ) [(3,), (7, -8), (-2, 1)] Returns list of sequence types. ''' from abjad.tools import sequencetools result = [] current_index = 0 current_piece = [] if cyclic: weights = sequencetools.repeat_sequence_to_weight_at_most(weights, mathtools.weight(sequence)) for weight in weights: current_piece_weight = mathtools.weight(current_piece) while current_piece_weight < weight: current_piece.append(sequence[current_index]) current_index += 1 current_piece_weight = mathtools.weight(current_piece) if current_piece_weight == weight: current_piece = type(sequence)(current_piece) result.append(current_piece) current_piece = [] elif weight < current_piece_weight: overage = current_piece_weight - weight current_last_element = current_piece.pop(-1) needed = abs(current_last_element) - overage needed *= mathtools.sign(current_last_element) current_piece.append(needed) current_piece = type(sequence)(current_piece) result.append(current_piece) overage *= mathtools.sign(current_last_element) current_piece = [overage] if overhang: last_piece = current_piece last_piece.extend(sequence[current_index:]) if last_piece: last_piece = type(sequence)(last_piece) result.append(last_piece) return result
def partition_sequence_by_counts(sequence, counts, cyclic=False, overhang=False, copy_elements=False): r"""Partition sequence by counts. .. container:: example **Example 1a.** Partition sequence once by counts without overhang: :: >>> sequencetools.partition_sequence_by_counts( ... range(10), ... [3], ... cyclic=False, ... overhang=False, ... ) [[0, 1, 2]] .. container:: example **Example 1b.** Partition sequence once by counts without overhang: :: >>> sequencetools.partition_sequence_by_counts( ... range(16), ... [4, 3], ... cyclic=False, ... overhang=False, ... ) [[0, 1, 2, 3], [4, 5, 6]] .. container:: example **Example 2a.** Partition sequence cyclically by counts without overhang: :: >>> sequencetools.partition_sequence_by_counts( ... range(10), ... [3], ... cyclic=True, ... overhang=False, ... ) [[0, 1, 2], [3, 4, 5], [6, 7, 8]] .. container:: example **Example 2b.** Partition sequence cyclically by counts without overhang: :: >>> sequencetools.partition_sequence_by_counts( ... range(16), ... [4, 3], ... cyclic=True, ... overhang=False, ... ) [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9, 10], [11, 12, 13]] .. container:: example **Example 3a.** Partition sequence once by counts with overhang: :: >>> sequencetools.partition_sequence_by_counts( ... range(10), ... [3], ... cyclic=False, ... overhang=True, ... ) [[0, 1, 2], [3, 4, 5, 6, 7, 8, 9]] .. container:: example **Example 3b.** Partition sequence once by counts with overhang: :: >>> sequencetools.partition_sequence_by_counts( ... range(16), ... [4, 3], ... cyclic=False, ... overhang=True, ... ) [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9, 10, 11, 12, 13, 14, 15]] .. container:: example **Example 4a.** Partition sequence cyclically by counts with overhang: :: >>> sequencetools.partition_sequence_by_counts( ... range(10), ... [3], ... cyclic=True, ... overhang=True, ... ) [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]] .. container:: example **Example 4b.** Partition sequence cyclically by counts with overhang: :: >>> sequencetools.partition_sequence_by_counts( ... range(16), ... [4, 3], ... cyclic=True, ... overhang=True, ... ) [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9, 10], [11, 12, 13], [14, 15]] Returns list of sequence objects. """ from abjad.tools import sequencetools result = [] if cyclic: if overhang: counts = sequencetools.repeat_sequence_to_weight_exactly(counts, len(sequence)) else: counts = sequencetools.repeat_sequence_to_weight_at_most(counts, len(sequence)) elif overhang: weight_counts = mathtools.weight(counts) len_sequence = len(sequence) if weight_counts < len_sequence: counts = list(counts) counts.append(len(sequence) - weight_counts) for start, stop in mathtools.cumulative_sums_pairwise(counts): result.append(type(sequence)(sequence[start:stop])) return result