Dictionary inside Pattern

hey, thanks for your further ideas :slight_smile: at least for the initial L-System which is created by ~getDur inside ~getAbs you already creating streams. is this kind of redundant then, when combined with ~resetL ?

(
~rewriteWord = {|word, rules, iter=6|
	iter.do{
		word = Array.newFrom(word)
		.collect{|c| rules[c.asSymbol]}
		.join;
	};
	word
};

~getDur = {|word, durDict|
	// streams are created inside this function
	// so every time we call ~getDur, streams are resetted
	var streams = durDict.collect{|seq| Pseq(seq,inf).asStream};
	Array.newFrom(word).collect{|c| streams[c.asSymbol].next }
};

// function for cropping L-System

~sumUpTo = {|array, total|
	var sum = 0, i = 0, result = Array.new;
	while { i < array.size and: { sum < total } } {
		sum = sum + array[i];
		if(sum > total) {
			result = result.add(array[i] - (sum - total));
		} {
			result = result.add(array[i]);
		};
		i = i + 1;
	};
	result
};

// creating abstractions with lesser density: reduce the density by joining two values

~low_dens = {|array|
	var ioi, min_index, neighbor_index, result = [];
	ioi = array.copy();

	while {ioi.size() > 1} {
		// in every step, we will reduce ioi until it has size 1
		var intermediate_result = [];
		min_index = ioi.minIndex;

		// if first element is minimum element, the neighor can only be to the right
		if (min_index == 0) {
			neighbor_index = 1;
		} {
			// else if last element is minimum element, the neighbor can only be to the left
			if (min_index == (ioi.size - 1)) {
				neighbor_index = (ioi.size - 2);
			} {
				// else we're in the middle, so use the neighbor which is smallest (arbitrary choice)
				var dir = 1;
				if (ioi[min_index - 1] < ioi[min_index + 1]) {
					dir = -1;
				};
				neighbor_index = min_index + dir;
			};
		};
		// swap neighbor and min_index so that neighbor is always bigger than min_index
		// - this makes copying easier in the next step
		if (neighbor_index < min_index) {
			var tmp = min_index;
			min_index = neighbor_index;
			neighbor_index = tmp;
		};

		// make a new list consisting of everything before min_index, sum of min el and its neighbor, everything after neighbor
		intermediate_result = ioi.copyRange(0, min_index-1) ++ (ioi[min_index] + ioi[neighbor_index]) ++ ioi.copyRange(neighbor_index+1, (ioi.size-1));

		if (intermediate_result.size >= ioi.size) {
			"ERROR!".postln;
		};

		// add it to the list of results
		result = result.add(intermediate_result);

		// and update our starting point with the reduced list
		ioi = intermediate_result.copy();
	};

	// return the complete list of reductions
	result;
};

// creating abstractions with higher density by replacing a value with:
// a smaller potential IOI value and the difference between it and the value being replaced

~high_dens = {|array|
	var ioi, ioi_sort, pot_ioi, index_max, result = [];
	ioi = array.copy();

	ioi_sort = ioi.as(Set).as(Array).sort;
	pot_ioi = ioi_sort.minItem;

	while { ioi.maxItem > pot_ioi } {
		var intermediate_result = [];

		index_max = ioi.findAll([ioi.maxItem]).choose;

		intermediate_result = intermediate_result.add(ioi);
		intermediate_result = intermediate_result.insert(index_max+1, [ioi[index_max] - pot_ioi, pot_ioi]).flat;
		intermediate_result.removeAt(index_max);

		// add it to the list of results
		result = result.add(intermediate_result);

		// and update our starting point with the reduced list
		ioi = intermediate_result.copy();

	};

	result;
};

~getAbs = {|rules, durations|
	var axiom, lsys, low_abs, high_abs, abstractions = [];

	// axiom
	axiom = "A";

	// rewrite iteration
	axiom = ~rewriteWord.(axiom, rules, 6);

	// get durations
	lsys = ~getDur.(axiom, durations);

	//crop initial L-System to a specific length
	lsys = ~sumUpTo.(lsys, 4);
	lsys.debug("L-System");

	//add abstractions with lower density to the array of abstractions
	low_abs = ~low_dens.(lsys);
	low_abs.do({
		arg el, elindex;
		abstractions = abstractions.add(el);
	});

	//add the initial L-System to the array of abstractions
	abstractions = abstractions.add(lsys);

	//add abstractions with higher density to the array of abstractions
	high_abs = ~high_dens.(lsys);
	high_abs.do({
		arg el, elindex;
		abstractions = abstractions.add(el);
	});

	//order array of abstractions by size: low -> high
    abstractions = abstractions.sort({|a, b| a.size < b.size});

	abstractions.indexOf(lsys).debug("L-System index");
	abstractions.debug("abstractions");
};

// define rules
~rules = (A:"AB", B:"A");

// define durations for each symbol
~durations = (A: [0.25, 0.5], B: [0.5, 0.125]);

~absArray = ~getAbs.(~rules, ~durations);
)

in the end im trying to use the L-System abstractions as a Pulse inside PSPdiv and not sure right now if Data Sharing with Pbindef(\measure) from @PitchTrebler or your appraoch works best here. but this is already working correctly i think:

(
Pdef(\kick,
	Pbind(
	[...]
)
);

Pdef(\sd,
	Pbind(
	[...]
)
);

Pdef(\hh,
	Pbind(
	[...]
)
);
)

(
~index = Pn(Pseq([3,5,7], inf)).asStream.trace(prefix: "measure index: ");
~pulse = Pdict(~patDict, Pfin(1, PL(\index))).trace;

~div_kick = 4;
~div_sd = 3;
~div_hh = 5;

~divBase_kick = 1;
~divBase_sd = 2;
~divBase_hh = 1;

~divType = \seq;

Pdef(\rhythms,
	PSPdiv(
		PL(\pulse),
		[Pdef(\kick), Pdef(\sd), Pdef(\hh)],
		[PL(\div_kick), PL(\div_sd), PL(\div_hh)],
		[PL(\divBase_sd), PL(\divBase_sd), PL(\divBase_hh)],
		PL(\divType),
	),
).play(t, quant:1);
)

// update ~absArray on the fly:
(
~rules = (A:"AB", B:"AC", C:"BA");
~durations = (A: [0.25, 0.5], B: [0.5, 0.125], C: [0.333, 0.167]);
~absArray = ~getAbs.(~rules, ~durations);
~resetL.(~absArray);
)