// Forked from "Pisano sequence 🧮" by Jurgen
// https://turtletoy.net/turtle/6c8aa31631

const mod = 131; //min=1 max=300 step=1
const stepSize = 5;//min=1 max=50 step=1
const iterations = 773;//min=1 max=1000 step=1
const startX = -5;//min=-100 max=100 step=1
const startY = 60;//min=-100 max=100 step=1
const angle = 60;//min=0 max=360 step=1
const sequence = 0; //min=0 max=4 step=1 (Fibonacci, Lucas, Triangular, MultiplesOfFour, Recamán terms 600-700)
const progressOnZero = 1; //min=0 max=1 step=1 (No, Yes)

// You can find the Turtle API reference here: https://turtletoy.net/syntax
Canvas.setpenopacity(1);

// Global code will be evaluated once.
const turtle = new Turtle();
turtle.jump(startX, startY);

const series = [[fibonacci,[0n,1n]], [fibonacci,[2n,1n]], [triangular,[]], [multiples,[4]], [recaman, [600, 700]]];

const numbers = pisano(mod, series[sequence][0](...series[sequence][1]));
// The walk function will be called until it returns false.
function walk(i) {
    if(progressOnZero === 1) turtle.forward(stepSize);
    if(numbers[i%numbers.length] !== 0) {
        if(progressOnZero === 0) turtle.forward(stepSize);
        switch(numbers[i%numbers.length]%2) {
            case 0:
                turtle.left(angle);
                break;
            default:
                turtle.right(angle);
                break;
        }
    }

    return i < iterations;
}

function* recaman(skip = 0, take = 0) {
    const sequence = [0];
    for(let i = 1; take==0||i<skip+take+1; i++) {
        if(i > skip) yield BigInt(sequence[i - 1]);
        [sequence[i-1]-i].forEach(next => sequence.push(next > 0 && !sequence.includes(next)? next: sequence[i-1]+i));
    }
}
function* multiples(base) {
    for(let n = 0n, i = BigInt(base); true; n++) {
        yield n*i;
    }
}
function* triangular() {
    for(let n = 0n, i = 1n; true; i++) {
        yield n;
        n += i;
    }
}
function* fibonacci(a = 0n, b = 1n) {
    yield a;
    yield b;
    while(true) {
        const c = a + b;
        yield c;
        a = b, b = c;
    }
}

function pisano(modulo, iterator = null) {
    const sequence = [];
    const mod = BigInt(modulo);
    let start = null;
    for(let f of iterator) {
        const nxt = f % mod;
        if(nxt === start && sequence.length % 2 == 0 && sequence.length > 0) {
            const l = sequence.length / 2;
            if(sequence.every((v, i, a) => i >= l? true: v == a[i+l])) {
                return sequence.filter((v, i) => i < l);
            }
        }
        if(start == null) start = nxt;
        sequence.push(Number(nxt));
    }
    return sequence; //if finite series
}