Do is not ¨returning¨ array (campanology)

First off, oh my gosh I’m so sorry for not realizing that! That’s great.

How how hard would it be to take the basic Plaint Hunt script and modify it to produce it’s more complex cousin, Plain Bob? There seems to me only one crucial difference that would need to be implemented to create this more complex pattern from the existing script, which is the “first pair stays, rest swaps” aspect:

Plain Bob:

[ 1, 2, 3, 4, 5, 6 ] - starts off like Plain Hunt i.e. “[ 1, 2, 3, 4, 5, 6 ].campanology(1);”
[ 2, 1, 4, 3, 6, 5 ]
[ 2, 4, 1, 6, 3, 5 ]
[ 4, 2, 6, 1, 5, 3 ]
[ 4, 6, 2, 5, 1, 3 ]
[ 6, 4, 5, 2, 3, 1 ]
[ 6, 5, 4, 3, 2, 1 ]
[ 5, 6, 3, 4, 1, 2 ]
[ 5, 3, 6, 1, 4, 2 ]
[ 3, 5, 1, 6, 2, 4 ]
[ 3, 1, 5, 2, 6, 4 ]
[ 1, 3, 2, 5, 4, 6 ] - where the current Plain Hunt script ends

[ 1, 3, 5, 2, 6, 4 ] - first pair stays, rest swap, then “[ 1, 3, 5, 2, 6, 4 ].campanology(1);”
[ 3, 2, 1, 4, 5, 6 ]
[ 2, 3, 4, 1, 6, 5 ]
[ 2, 4, 3, 6, 1, 5 ]
[ 4, 2, 6, 3, 5, 1 ]
[ 4, 6, 2, 5, 3, 1 ]
[ 6, 4, 5, 2, 1, 3 ]
[ 6, 5, 4, 1, 2, 3 ]
[ 5, 6, 1, 4, 3, 2 ]
[ 5, 1, 6, 3, 4, 2 ]
[ 1, 5, 3, 6, 2, 4 ]

[ 1, 5, 6, 3, 4, 2 ] - first pair stays, rest swap, then “[ 1, 5, 3, 6, 2, 4 ].campanology(1);”
[ 5, 1, 3, 6, 2, 4 ]
[ 5, 3, 1, 2, 6, 4 ]
[ 3, 5, 2, 1, 4, 6 ]
[ 3, 2, 5, 4, 1, 6 ]
[ 2, 3, 4, 5, 6, 1 ]
[ 2, 4, 3, 6, 5, 1 ]
[ 4, 2, 6, 3, 1, 5 ]
[ 4, 6, 2, 1, 3, 5 ]
[ 6, 4, 1, 2, 5, 3 ]
[ 6, 1, 4, 5, 2, 3 ]
[ 1, 6, 5, 4, 3, 2 ]

etc. etc.

Note this image focuses on the (2) bell’s direction change, but the above way of thinking produces the same result:

Plain-bob-minor_2

I see.
This is a specific way to do it for 6 bells. The idea is to generalize from 3 bells to 12 bells, and why not for any number beyond. I do not know much about campanology, I am just interested in combinatory. So, for now, I am quite a bit busy, but I am going to study that and think about a way to implement it if indeed it is relevant to do so.
Meanwhile, you are welcome to propose solutions, even in pseudo-code.
:nerd_face:

1 Like

I really don’t know much about arrays, but if the script uses a swap neighbors kind of command, it might be easiest to retain it as is and then swap the first pair again since no matter how large the initial array is, it’s always the first pair that stays the same (or in this case swaps twice). In other words, rather than coding in a kind of immunity from swapping the first pair, it might be easier to double-swap.

So something like:

[original array].campanology
x = last row
x = x with Index 1 and 2 swapped
[x].campanology
Etc.
End when x = [original array]

As a general note, as is customary for all eccentric pursuits that are popular in Britain, there is a society for campanology that has an active mailing list.

https://lists.ringingworld.co.uk/mailman/listinfo/ringing-chat

1 Like

Yeah I’m subscribed to a lot of it! Unfortunately, the issue for me isn’t understanding change ringing methods (that would be an easy fix given the resources that are out there), but my problem (given that I’m still just getting in SC) is learning how to create code in SC to generate the methods I love :).

To me, it is precisely the contrary.
This is why I suggested there:

The first idea is maybe to list the needed methods: Method ringing - Wikipedia or to list the parameters of the method campanology able to build any combination needed.
Also, it would be more relevant and more readable to create a new thread for this topic.

Hey Yann,

So I posted the pseudo code above for how to do Plain Bob, which is probably be the most basic and also most popular method in the world. Other favorites include Grandsire, Stedman, Cambridge, and Yorkshire.

I’d be happy to contribute ideas and thoughts about what the most significant methods are, and try my best to help break down what makes the different methods unique and what methods might need new code solutions. Luckily, I think some of the most fundamental coding issues have already been solved here, so it should possible to construct most of the methods using the tools you’ve already built.

If you want to work on this together, I’d be thrilled to help in any way I can, and I agree that starting a new thread for this endeavor would make sense: perhaps something like “Campanology and Change Ringing in SuperCollider and Cycle”?

Either way, I’ll gladly share with you the most popular methods in common use, and we can figure out how to implement them. Even though there are gazillions of methods out there, the truth is that a handful of methods comprise most of the ringing that is performed throughout the world. Most of the challenges and variation encountered in daily ringing are due to towers having a different number of bells, odd or even number of bells, etc. For us, using SC, this is basically a non-issue. It’s really just a matter of understanding how and when each methods swaps, dodges, and hunts.

-Mark

Quite interesting. The number of different permutations (and computations) with those algorithms and slightly larger arrays (let’s say, 10), can be a bit excessive. It would be cool to implement it with lazy evaluation too (just calculate the next list when required etc)

AbstractFunction does that, but it could also be a Pattern.

A while back I was exploring combinatoric algorithms along those lines, and I implemented Per Nørgård’s “infinity sequence”, or “infinite melody”, an algorithm that also tries to balance variation and repetition: a(2n) = -a(n), a(2n+1) = a(n) + 1, a(0)=0.

I’m now wondering if he was inspired by bells. It’s possible!

Code: GitHub - smoge/InfinitySeries: Nørgård’s infinite series implementation in SuperCollider

Pinf : Pattern {
	var <>start=0, <>step=1, <>length=inf;

	*new { arg start = 0, step = 1, length=inf;
		^super.newCopyArgs(start, step, length)
	}

	storeArgs { ^[start,step,length] }

	embedInStream { arg inval;
		var outval, counter = 0;
		var cur = start.value(inval);
		var len = length.value(inval);
		var stepStr = step.asStream, stepVal;
		while { counter < len } {
			stepVal = stepStr.next(inval);
			if(stepVal.isNil) { ^inval };
			outval = cur;
			cur = cur + stepVal;
			counter = counter + 1;
			inval = outval.infiniteNumber.yield;
		};
		^inval;
	}
}


+Number {
	infiniteNumber {
		^this.asBinaryDigits.filterLeftZeros.infinityDigits
	}
}

+Collection {
	filterLeftZeros {
		var output=[];
		var firstOne=false;
		this.do({|i|
			if(i==1, {output=output++1; firstOne=true});
			if(i==0 && firstOne, {output=output++0});
		});
		^output
	}

	infinityDigits {
		var output=0;
		this.do({|i|
			case
			{i==0} {output = output * (-1)}
			{i==1} {output = output + 1 };
		});
		^output
	}
}

+SequenceableCollection {
	*infinitySeries { arg size, start=0, step=1;
		var obj = this.new(size);
		size.do {|i|
			obj.add((start + (step * i)).infiniteNumber);
		};
		^obj
	}
}

Example:

(0..20) collect: _.infiniteNumber;

Array.infinitySeries(100).plot

Pbind( \note, Pinf(3, 1) * 1/2 + 12, \dur, Pinf(3, 1).abs * 0.1).play;
1 Like

This is pretty rad. Love that series.

1 Like

The current record for humans in change ringing is performing a method with 24 handbells. Would be cool to be able to use more than 10. Say… 25? :slight_smile:

Yea)))

Another way to generate this number series in SuperCollider would be:

~norgardInfinitySeq = { |len=100|
    var sequence = Array.newClear(len);
    sequence.put(0, 0); // a(0) = 0

    len.do { |n|
        if((n % 2) == 0, {
            sequence.put(n, sequence.at(n/2).neg); // a(2n) = -a(n)
        }, {
            sequence.put(n, sequence.at((n-1)/2) + 1); // a(2n+1) = a(n) + 1
        });
    };

    sequence;
};

~norgardInfinitySeq.value(100).postln;

Yes, I used a completely different method/algorithm to create the series. That’s one of the curious qualities of it:

It’s such a pretty sequence. Just for kicks made this mp3 real quick. Melody is simply the sequence mapped to major scale deg and bass voice is mapped to major scale degree and it’s mtransposition. It’s just absurdly gorgeous even as is:

https://drive.google.com/file/d/1fhhovN1AtLQWg3iHfdBc_V6HpbioLD8m/view?usp=sharing

1 Like

Thank you for sharing. It’s quite beautiful as is. It’s interesting how composers, using all sorts of arbitrary methods, can create mathematical pearls with pure intuition. (And also, how mathematicians have their fair share of arbitrariness and intuition too)

1 Like