Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate aperiodic MOS scales #10

Open
frostburn opened this issue Jan 8, 2024 · 2 comments
Open

Generate aperiodic MOS scales #10

frostburn opened this issue Jan 8, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@frostburn
Copy link
Member

https://en.xen.wiki/w/Hypercubic_billiard_word

@frostburn frostburn added the enhancement New feature or request label Jan 8, 2024
@frostburn
Copy link
Member Author

The parameters would be the sizes of large and small steps and the ratio of large steps to small steps with some sane defaults for the initial state of the "billiard ball".

If we want to generalize this package to larger varieties the parameters would be the sizes of steps and an array of proportionalities between them.

@frostburn
Copy link
Member Author

0.5° 🌜Today at 5:24 PM
my billiard-related Python code, for comparison, is:

def collisions(alphabet: Sequence[str],
               vel: Sequence[Fraction],
               start_pos: Sequence[Fraction]) -> Iterator[str]:
    dim = len(alphabet)
    if dim == 0:
        raise ValueError('alphabet should be nonempty')
    if len(vel) != dim:
        raise ValueError('len(vel) should equal len(alphabet)')
    if len(start_pos) != dim:
        raise ValueError('len(start_pos) should equal len(alphabet)')
    if any(v <= 0 for v in vel):
        raise ValueError('vel should contain positive numbers')
    if not all(0 <= x < 1 for x in start_pos):
        raise ValueError('start_pos should contain numbers 0 <= x < 1')

    # we’ll decrement to 0 with unit velocity in each dimension
    pos = [(1 - x) / v for x, v in zip(start_pos, vel)]
    start_pos = pos.copy()
    bounds = tuple(1 / v for v in vel)
    while True:
        times = [(x, j) for j, x in enumerate(pos)]
        times.sort()
        t0 = times[0][0]  # the first imminent collision time
        for t, j in times:
            if t == t0:
                pos[j] = bounds[j]
                # in a tie, different j should go in increasing order
                yield alphabet[j]
            else:
                pos[j] -= t0
        if pos == start_pos:
            return  # cycle

should be fully general due to start_pos
also usually the first velocity is okay to be equally 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant