def yield_all_compositions_of_integer(n): """ Yields all compositions of positive integer ``n``. .. container:: example >>> for tuple_ in abjad.mathtools.yield_all_compositions_of_integer(5): ... tuple_ ... (5,) (4, 1) (3, 2) (3, 1, 1) (2, 3) (2, 2, 1) (2, 1, 2) (2, 1, 1, 1) (1, 4) (1, 3, 1) (1, 2, 2) (1, 2, 1, 1) (1, 1, 3) (1, 1, 2, 1) (1, 1, 1, 2) (1, 1, 1, 1, 1) Lists parts in descending lex order. Parts sum to ``n``. Finds small values of ``n`` easily. Takes around 4 seconds for ``n`` equal to 17. Returns integer tuple generator. """ from abjad import mathtools compositions = [] integer = 0 string_length = n while integer < 2 ** (n - 1): binary_string = mathtools.integer_to_binary_string(integer) binary_string = binary_string.zfill(string_length) digits = [int(_) for _ in list(binary_string)] partition = [] generator = itertools.groupby(digits, lambda _: _) for value, group in generator: partition.append(list(group)) sublengths = [len(part) for part in partition] composition = tuple(sublengths) compositions.append(composition) integer += 1 for composition in reversed(sorted(compositions)): yield composition
def yield_all_compositions_of_integer(n): """ Yields all compositions of positive integer ``n``. .. container:: example >>> for tuple_ in abjad.mathtools.yield_all_compositions_of_integer(5): ... tuple_ ... (5,) (4, 1) (3, 2) (3, 1, 1) (2, 3) (2, 2, 1) (2, 1, 2) (2, 1, 1, 1) (1, 4) (1, 3, 1) (1, 2, 2) (1, 2, 1, 1) (1, 1, 3) (1, 1, 2, 1) (1, 1, 1, 2) (1, 1, 1, 1, 1) Lists parts in descending lex order. Parts sum to ``n``. Finds small values of ``n`` easily. Takes around 4 seconds for ``n`` equal to 17. Returns integer tuple generator. """ from abjad import mathtools compositions = [] integer = 0 string_length = n while integer < 2**(n - 1): binary_string = mathtools.integer_to_binary_string(integer) binary_string = binary_string.zfill(string_length) digits = [int(_) for _ in list(binary_string)] partition = [] generator = itertools.groupby(digits, lambda _: _) for value, group in generator: partition.append(list(group)) sublengths = [len(part) for part in partition] composition = tuple(sublengths) compositions.append(composition) integer += 1 for composition in reversed(sorted(compositions)): yield composition
def dot_count(self): r""" Gets dot count. .. container:: example Gets dot count: >>> for n in range(1, 16 + 1): ... try: ... duration = abjad.Duration(n, 16) ... sixteenths = duration.with_denominator(16) ... dot_count = duration.dot_count ... string = f'{sixteenths!s}\t{dot_count}' ... print(string) ... except abjad.AssignabilityError: ... sixteenths = duration.with_denominator(16) ... print(f'{sixteenths!s}\t--') ... 1/16 0 2/16 0 3/16 1 4/16 0 5/16 -- 6/16 1 7/16 2 8/16 0 9/16 -- 10/16 -- 11/16 -- 12/16 1 13/16 -- 14/16 2 15/16 3 16/16 0 Dot count defined equal to number of dots required to notate duration. Raises assignability error when duration is not assignable. Returns positive integer. """ if not self.is_assignable: raise exceptions.AssignabilityError binary_string = mathtools.integer_to_binary_string(self.numerator) digit_sum = sum([int(x) for x in list(binary_string)]) dot_count = digit_sum - 1 return dot_count
def yield_partitions(self): """ Yields partitions of sequence. .. container:: example >>> enumerator = abjad.Enumerator([0, 1, 2]) >>> for partition in enumerator.yield_partitions(): ... partition ... Sequence([Sequence([0, 1, 2])]) Sequence([Sequence([0, 1]), Sequence([2])]) Sequence([Sequence([0]), Sequence([1, 2])]) Sequence([Sequence([0]), Sequence([1]), Sequence([2])]) .. container:: example >>> enumerator = abjad.Enumerator([0, 1, 2, 3]) >>> for partition in enumerator.yield_partitions(): ... partition ... Sequence([Sequence([0, 1, 2, 3])]) Sequence([Sequence([0, 1, 2]), Sequence([3])]) Sequence([Sequence([0, 1]), Sequence([2, 3])]) Sequence([Sequence([0, 1]), Sequence([2]), Sequence([3])]) Sequence([Sequence([0]), Sequence([1, 2, 3])]) Sequence([Sequence([0]), Sequence([1, 2]), Sequence([3])]) Sequence([Sequence([0]), Sequence([1]), Sequence([2, 3])]) Sequence([Sequence([0]), Sequence([1]), Sequence([2]), Sequence([3])]) Returns generator of nested sequences. """ length = len(self.sequence) - 1 for i in range(2 ** length): binary_string = mathtools.integer_to_binary_string(i) binary_string = binary_string.zfill(length) part = list(self.sequence[0:1]) partition = [part] for n, token in zip(self.sequence[1:], binary_string): if int(token) == 0: part.append(n) else: part = [n] partition.append(part) parts = [Sequence(items=_) for _ in partition] partition = Sequence(items=parts) yield partition
def dot_count(self) -> int: r""" Gets dot count. .. container:: example Gets dot count: >>> for n in range(1, 16 + 1): ... try: ... duration = abjad.Duration(n, 16) ... sixteenths = duration.with_denominator(16) ... dot_count = duration.dot_count ... string = f'{sixteenths!s}\t{dot_count}' ... print(string) ... except abjad.AssignabilityError: ... sixteenths = duration.with_denominator(16) ... print(f'{sixteenths!s}\t--') ... 1/16 0 2/16 0 3/16 1 4/16 0 5/16 -- 6/16 1 7/16 2 8/16 0 9/16 -- 10/16 -- 11/16 -- 12/16 1 13/16 -- 14/16 2 15/16 3 16/16 0 Dot count defined equal to number of dots required to notate duration. Raises assignability error when duration is not assignable. """ if not self.is_assignable: raise exceptions.AssignabilityError binary_string = mathtools.integer_to_binary_string(self.numerator) digit_sum = sum([int(x) for x in list(binary_string)]) dot_count = digit_sum - 1 return dot_count
def is_assignable_integer(argument): r""" Is true when ``argument`` is equivalent to an integer that can be written without recourse to ties. .. container:: example >>> for n in range(0, 16 + 1): ... print('%s\t%s' % (n, abjad.mathtools.is_assignable_integer(n))) ... 0 False 1 True 2 True 3 True 4 True 5 False 6 True 7 True 8 True 9 False 10 False 11 False 12 True 13 False 14 True 15 True 16 True Returns true or false. """ from abjad import mathtools if isinstance(argument, int): if 0 < argument: if "01" not in mathtools.integer_to_binary_string(argument): return True return False
def is_assignable_integer(argument): r""" Is true when ``argument`` is equivalent to an integer that can be written without recourse to ties. .. container:: example >>> for n in range(0, 16 + 1): ... print('%s\t%s' % (n, abjad.mathtools.is_assignable_integer(n))) ... 0 False 1 True 2 True 3 True 4 True 5 False 6 True 7 True 8 True 9 False 10 False 11 False 12 True 13 False 14 True 15 True 16 True Returns true or false. """ from abjad import mathtools if isinstance(argument, int): if 0 < argument: if '01' not in mathtools.integer_to_binary_string(argument): return True return False
def yield_combinations(self, minimum_length=None, maximum_length=None): """ Yields combinations of sequence items. .. container:: example >>> enumerator = abjad.Enumerator([1, 2, 3, 4]) >>> for combination in enumerator.yield_combinations(): ... combination Sequence([]) Sequence([1]) Sequence([2]) Sequence([1, 2]) Sequence([3]) Sequence([1, 3]) Sequence([2, 3]) Sequence([1, 2, 3]) Sequence([4]) Sequence([1, 4]) Sequence([2, 4]) Sequence([1, 2, 4]) Sequence([3, 4]) Sequence([1, 3, 4]) Sequence([2, 3, 4]) Sequence([1, 2, 3, 4]) .. container:: example >>> enumerator = abjad.Enumerator([1, 2, 3, 4]) >>> for combination in enumerator.yield_combinations( ... minimum_length=3, ... ): ... combination Sequence([1, 2, 3]) Sequence([1, 2, 4]) Sequence([1, 3, 4]) Sequence([2, 3, 4]) Sequence([1, 2, 3, 4]) .. container:: example >>> enumerator = abjad.Enumerator([1, 2, 3, 4]) >>> for combination in enumerator.yield_combinations( ... maximum_length=2, ... ): ... combination Sequence([]) Sequence([1]) Sequence([2]) Sequence([1, 2]) Sequence([3]) Sequence([1, 3]) Sequence([2, 3]) Sequence([4]) Sequence([1, 4]) Sequence([2, 4]) Sequence([3, 4]) .. container:: example >>> enumerator = abjad.Enumerator([1, 2, 3, 4]) >>> for combination in enumerator.yield_combinations( ... minimum_length=2, ... maximum_length=2, ... ): ... combination Sequence([1, 2]) Sequence([1, 3]) Sequence([2, 3]) Sequence([1, 4]) Sequence([2, 4]) Sequence([3, 4]) .. container:: example >>> enumerator = abjad.Enumerator('text') >>> for combination in enumerator.yield_combinations(): ... ''.join([str(_) for _ in combination]) '' 't' 'e' 'te' 'x' 'tx' 'ex' 'tex' 't' 'tt' 'et' 'tet' 'xt' 'txt' 'ext' 'text' Yields combinations in binary string order. Returns sequence generator. """ length = len(self.sequence) for i in range(2 ** length): binary_string = mathtools.integer_to_binary_string(i) binary_string = binary_string.zfill(length) sublist = [] for j, digit in enumerate(reversed(binary_string)): if digit == "1": sublist.append(self.sequence[j]) yield_sublist = True if minimum_length is not None: if len(sublist) < minimum_length: yield_sublist = False if maximum_length is not None: if maximum_length < len(sublist): yield_sublist = False if yield_sublist: if isinstance(self.sequence, str): yield "".join(sublist) else: yield Sequence(items=sublist)
def partition_integer_into_canonic_parts(n, decrease_parts_monotonically=True): """ Partitions integer ``n`` into canonic parts. .. container:: example Returns all parts positive on positive ``n``: >>> for n in range(1, 11): ... print(n, abjad.mathtools.partition_integer_into_canonic_parts(n)) ... 1 (1,) 2 (2,) 3 (3,) 4 (4,) 5 (4, 1) 6 (6,) 7 (7,) 8 (8,) 9 (8, 1) 10 (8, 2) .. container:: example Returns all parts negative on negative ``n``: >>> for n in reversed(range(-20, -10)): ... print(n, abjad.mathtools.partition_integer_into_canonic_parts(n)) ... -11 (-8, -3) -12 (-12,) -13 (-12, -1) -14 (-14,) -15 (-15,) -16 (-16,) -17 (-16, -1) -18 (-16, -2) -19 (-16, -3) -20 (-16, -4) .. container:: example Returns parts that increase monotonically: >>> for n in range(11, 21): ... print(n, abjad.mathtools.partition_integer_into_canonic_parts(n, ... decrease_parts_monotonically=False)) ... 11 (3, 8) 12 (12,) 13 (1, 12) 14 (14,) 15 (15,) 16 (16,) 17 (1, 16) 18 (2, 16) 19 (3, 16) 20 (4, 16) Returns tuple with parts that decrease monotonically. Returns tuple of integers. """ from abjad import mathtools assert isinstance(n, int), repr(n) assert isinstance(decrease_parts_monotonically, bool) if n == 0: return (0,) result = [] previous_empty = True binary_n = mathtools.integer_to_binary_string(abs(n)) binary_length = len(binary_n) for i, character in enumerate(binary_n): if character == "1": place_value = 2 ** (binary_length - i - 1) if previous_empty: result.append(place_value) else: result[-1] += place_value previous_empty = False else: previous_empty = True sign_n = mathtools.sign(n) if mathtools.sign(n) == -1: result = [sign_n * _ for _ in result] if decrease_parts_monotonically: return tuple(result) else: return tuple(reversed(result))
def partition_integer_into_canonic_parts(n, decrease_parts_monotonically=True): """ Partitions integer ``n`` into canonic parts. .. container:: example Returns all parts positive on positive ``n``: >>> for n in range(1, 11): ... print(n, abjad.mathtools.partition_integer_into_canonic_parts(n)) ... 1 (1,) 2 (2,) 3 (3,) 4 (4,) 5 (4, 1) 6 (6,) 7 (7,) 8 (8,) 9 (8, 1) 10 (8, 2) .. container:: example Returns all parts negative on negative ``n``: >>> for n in reversed(range(-20, -10)): ... print(n, abjad.mathtools.partition_integer_into_canonic_parts(n)) ... -11 (-8, -3) -12 (-12,) -13 (-12, -1) -14 (-14,) -15 (-15,) -16 (-16,) -17 (-16, -1) -18 (-16, -2) -19 (-16, -3) -20 (-16, -4) .. container:: example Returns parts that increase monotonically: >>> for n in range(11, 21): ... print(n, abjad.mathtools.partition_integer_into_canonic_parts(n, ... decrease_parts_monotonically=False)) ... 11 (3, 8) 12 (12,) 13 (1, 12) 14 (14,) 15 (15,) 16 (16,) 17 (1, 16) 18 (2, 16) 19 (3, 16) 20 (4, 16) Returns tuple with parts that decrease monotonically. Returns tuple of integers. """ from abjad import mathtools assert isinstance(n, int), repr(n) assert isinstance(decrease_parts_monotonically, bool) if n == 0: return (0, ) result = [] previous_empty = True binary_n = mathtools.integer_to_binary_string(abs(n)) binary_length = len(binary_n) for i, character in enumerate(binary_n): if character == '1': place_value = 2**(binary_length - i - 1) if previous_empty: result.append(place_value) else: result[-1] += place_value previous_empty = False else: previous_empty = True sign_n = mathtools.sign(n) if mathtools.sign(n) == -1: result = [sign_n * _ for _ in result] if decrease_parts_monotonically: return tuple(result) else: return tuple(reversed(result))