Added pick and select for lists

Pick: (1 2 3 4)?4 or (1 2 3 4)?(3 2)
Select: (1 2 3 4)~2 or (1 2 3 4)~(2 3)
This commit is contained in:
2023-04-26 21:14:21 +03:00
parent cc3497fd29
commit 8f5d8adf48
6 changed files with 57 additions and 7 deletions

View File

@ -2,6 +2,7 @@
from dataclasses import dataclass, field, replace from dataclasses import dataclass, field, replace
from itertools import product from itertools import product
from math import floor from math import floor
import random
from types import LambdaType from types import LambdaType
from copy import deepcopy from copy import deepcopy
import operator import operator
@ -403,6 +404,47 @@ class ListOperation(Sequence):
return flattened_list return flattened_list
def _pick_from_list(left, right, options):
"""Pick random numbers from a list"""
if isinstance(left, Sequence):
left = _filter_operation(left, options)
if isinstance(right, Sequence):
right = _filter_operation(right, options)
if not isinstance(right, (list, Sequence)):
right = Sequence(values=[right])
result = []
for num in right.values:
for _ in range(num.get_value(options)):
result.append(random.choice(left.values))
return flatten(result)
def _select_from_list(left, right, options):
"""Select number of items from shuffled list"""
if isinstance(left, Sequence):
left = _filter_operation(left, options)
if isinstance(right, Sequence):
right = _filter_operation(right, options)
if not isinstance(right, (list, Sequence)):
right = Sequence(values=[right])
result = []
left = left.values
for num in right.values:
random.shuffle(left)
num = num.get_value(options)
new_list = [left[i % len(left)] for i in range(num)]
result += new_list
return flatten(result)
def _vertical_arpeggio(left, right, options): def _vertical_arpeggio(left, right, options):
"""Vertical arpeggio operation, eg. (135)@(q 1 2 021)""" """Vertical arpeggio operation, eg. (135)@(q 1 2 021)"""
left = _filter_operation(left, options) left = _filter_operation(left, options)
@ -537,8 +579,13 @@ class ListOperation(Sequence):
left = _vertical_arpeggio(left, right, options) left = _vertical_arpeggio(left, right, options)
elif operation == "horizontal": elif operation == "horizontal":
left = _horizontal_arpeggio(left, right, options) left = _horizontal_arpeggio(left, right, options)
if operation == "zip": elif operation == "zip":
left = _cyclic_zip(left, right, options) left = _cyclic_zip(left, right, options)
elif operation == "pick":
left = _pick_from_list(left, right, options)
elif operation == "select":
left = _select_from_list(left, right, options)
else: else:
left = _python_operations(left, right, options) left = _python_operations(left, right, options)
return left return left

View File

@ -62,7 +62,9 @@ OPERATORS = MappingProxyType({
">>": operator.irshift, ">>": operator.irshift,
"@": "vertical", "@": "vertical",
"#": "horizontal", "#": "horizontal",
"<>": "zip" "<>": "zip",
"?": "pick",
"~": "select"
}) })

View File

@ -431,7 +431,7 @@ class ZiffersTransformer(Transformer):
def lisp_operation(self, items): def lisp_operation(self, items):
"""Parse lisp like list operation""" """Parse lisp like list operation"""
op = items[0] op = items[0]
values = items[1:] values = items[2]
return LispOperation( return LispOperation(
operator=op, operator=op,
values=values, values=values,

View File

@ -73,7 +73,6 @@ def zparse(expr: str, **opts) -> Ziffers:
parsed.init_opts(opts) parsed.init_opts(opts)
return parsed return parsed
# pylint: disable=invalid-name # pylint: disable=invalid-name

View File

@ -56,8 +56,9 @@
right_op: list | number right_op: list | number
// Operators that work only on lists: | << >> // Operators that work only on lists: | << >>
list_operator: /(\||<<|>>|<>|#|@)(?=[(\d])/ list_operator: /(\||<<|>>|<>|#|@)(?=[(\d])/
// /(\||<<|>>|<>|#|@)(?=[(\d])/
// Common operators that works with numbers 3+5 3-5 etc. // Common operators that works with numbers 3+5 3-5 etc.
operator: /([\+\-\*\/%\&])/ operator: /(\+|-|\*|\/|%|&|\?|~)/
// Euclidean cycles // Euclidean cycles
// TODO: Support randomization etc. // TODO: Support randomization etc.
@ -66,7 +67,8 @@
?euclid_operator: /<[0-9]+,[0-9]+(,[0-9])?>/ ?euclid_operator: /<[0-9]+,[0-9]+(,[0-9])?>/
// Lisp like list operation // Lisp like list operation
lisp_operation: "(" operator WS sequence ")" lisp_operator: /([\+\-\*\/%\&])/
lisp_operation: "(" lisp_operator WS sequence ")"
// Subdivision // Subdivision
subdivision: "[" subitems "]" subdivision: "[" subitems "]"