janhardo

840 Reputation

12 Badges

11 years, 221 days

MaplePrimes Activity


These are replies submitted by janhardo

@dharr 

How about this ?

restart:
with(Fractals[LSystem]):
with(plots):

L := (Init,Ang,Par,Rules,Col) ->
display(
  [seq(
     LSystemPlot(
       `if`(i=0, Init, Iterate(Init, Rules, i)),
       Par,
       initialangle=Ang,
       color=Col,
       scaling=constrained,
       axes=none,
       thickness=2
     ),
   i=0..7)],
  insequence=true,
  frames=64
):

# --- L-system 17 ---
L("X",90,
  ["F"="draw:1","+"="turn:-25.7","-"="turn:25.7",
   "["="push:position;push:angle","]"="pop:position;pop:angle"],
  ["F"="FF","X"="F[+X][-X]FX"],
  "Red");

# --- L-system 18 ---
L("X",90,
  ["F"="draw:1","+"="turn:20","-"="turn:-20",
   "["="push:position;push:angle","]"="pop:position;pop:angle"],
  ["F"="FF","X"="F[+X]F[-X]+X"],
  "DarkGreen");


==========================================================

restart:
with(Fractals[LSystem]):
with(plots):

Frame := (i, S) ->
display(
  [seq(
     LSystemPlot(
       `if`(i=0, s[1], Iterate(s[1], s[4], i)),
       s[3],
       initialangle=s[2],
       color=s[5],
       scaling=constrained,
       axes=none,
       thickness=2
     ),
   s in S)]
):

Animate := (Systems, N) ->
display(
  [seq(Frame(i, Systems), i=0..N)],
  insequence=true,
  frames=64
):

# --- Definieer L-systems als lijsten ---
LS := [
 ["X",90,
  ["F"="draw:1","+"="turn:-25.7","-"="turn:25.7",
   "["="push:position;push:angle","]"="pop:position;pop:angle"],
  ["F"="FF","X"="F[+X][-X]FX"],
  "Red"],

 ["X",90,
  ["F"="draw:1","+"="turn:20","-"="turn:-20",
   "["="push:position;push:angle","]"="pop:position;pop:angle"],
  ["F"="FF","X"="F[+X]F[-X]+X"],
  "DarkGreen"]
]:

# --- Start animatie ---
Animate(LS, 7);

Used seq command for plot construction.
Seems that more animations at the same time can be runnning ..

restart;


# ============================================
# UNIVERSAL MANDALA MAKER WITH CLASSIC STYLE USING SEQ
# ============================================

MANDALA := proc(f, kind, sym, layers)
    local P, n, trace_list, i, Colors;
    uses plots, plottools;
    trace_list := [seq(i, i=1..f)];
    
    if kind = "classic" then
        # CLASSIC STYLE - WITH SEQ for full rotation animation
        Colors := [seq(op(["LightBlue","Indigo","Violet","Red","Orange","Yellow","Green"]), i=1..ceil(f/7))];
        Colors := Colors[1..f];
        
        P := proc(nn)
            local plot_obj, color_idx, rotations, j;
            
            color_idx := round(nn);
            if color_idx < 1 then color_idx := 1;
            elif color_idx > f then color_idx := f; end if;
            
            plot_obj := plot([x^(1+0.1*(nn-1)), x^(1/(1+0.1*(nn-1)))], 
                            x=0..1, 
                            thickness=5, 
                            color=Colors[color_idx], 
                            transparency=0.4);
            
            # WITH SEQ for full rotation animation
            # Create 1 rotation per frame that rotates completely
            rotations := seq(
                rotate(plot_obj, Pi*nn/f + 2*Pi*j, [0.5,0.5]),
                j = 0..0  # One rotation per frame, but with progressive angle
            );
            
            return display(rotations, axes=none);
        end proc;
        
    elif kind = "original" then
        # ORIGINAL STYLE - with seq for symmetry
        local Colors2;
        Colors2 := [seq(op(["LightBlue","Indigo","Violet","Red","Orange","Yellow","Green"]), i=1..ceil(f/7))];
        Colors2 := Colors2[1..f];
        
        P := proc(nn)
            local plot_obj, color_idx, exponent_val, rotations, j;
            
            color_idx := round(nn);
            if color_idx < 1 then color_idx := 1;
            elif color_idx > f then color_idx := f; end if;
            
            exponent_val := 1 + 0.1*(nn-1);
            
            plot_obj := plot([x^exponent_val, x^(1/exponent_val)], 
                            x=0..1,
                            thickness=3,
                            color=Colors2[color_idx],
                            transparency=0.4);
            
            # Add symmetry WITH SEQ
            rotations := display(
                seq(
                    rotate(plot_obj, 2*Pi*j/sym, [0.5,0.5]),
                    j = 0..sym-1
                ),
                axes=none
            );
            
            return rotations;
        end proc;
        
    elif kind = "power" then
        # POWER FUNCTIONS - with seq for layers and symmetry
        P := proc(nn)
            local t_val, exp_val, plot_obj, color_hue, rotation_seq, i, j;
            
            t_val := (nn-1.0)/(f-1.0);
            exp_val := 0.5 + 4.5*t_val;
            color_hue := COLOR(HUE, t_val);
            
            plot_obj := plot([x^exp_val, x^(1/exp_val)], 
                            x=0..1,
                            thickness=2,
                            color=color_hue,
                            transparency=0.3);
            
            # Layers and symmetry WITH NESTED SEQ
            rotation_seq := seq(
                seq(
                    rotate(plot_obj,
                           Pi*nn/f + 2*Pi*j/sym + (i-1)*Pi/(layers*2),
                           [0.5,0.5]),
                    j = 0..sym-1
                ),
                i = 1..layers
            );
            
            return display(rotation_seq, axes=none);
        end proc;
        
    elif kind = "sine" then
        # SINE WAVES - with seq for layers and symmetry
        P := proc(nn)
            local t_val, freq_val, plot_obj, color_hue, rotation_seq, i, j;
            
            t_val := (nn-1.0)/(f-1.0);
            freq_val := 1 + 9*t_val;
            color_hue := COLOR(HUE, t_val);
            
            plot_obj := plot([0.5+0.3*sin(2*Pi*freq_val*x),
                             0.5+0.3*cos(2*Pi*freq_val*x)],
                            x=0..1,
                            thickness=2,
                            color=color_hue,
                            transparency=0.3);
            
            # Layers and symmetry WITH NESTED SEQ
            rotation_seq := seq(
                seq(
                    rotate(plot_obj,
                           Pi*nn/f + 2*Pi*j/sym + (i-1)*Pi/(layers*2),
                           [0.5,0.5]),
                    j = 0..sym-1
                ),
                i = 1..layers
            );
            
            return display(rotation_seq, axes=none);
        end proc;
        
    else
        error "Unknown mandala kind: %1", kind;
    end if;
    
    # Animate for all styles
    return animate(P, [n], n=1..f, frames=f,
                   trace=trace_list,
                   axes=none,
                   size=[500,500],
                   paraminfo=false);
end proc:

# ============================================
# TEST 4 ANIMATIONS - ALL USING SEQ
# ============================================

print("========================================");
print("TEST 4 MANDALA ANIMATIONS - ALL USING SEQ");
print("========================================");
print("");

print("=== 1. CLASSIC STYLE (WITH SEQ) ===");
print("Classic with seq for progressive rotation: Pi*nn/f");
MANDALA(30, "classic", 8, 1);

print("");
print("=== 2. ORIGINAL STYLE (WITH SEQ) ===");
print("With seq for symmetry: 12-fold");
MANDALA(30, "original", 12, 1);

print("");
print("=== 3. POWER FUNCTIONS (WITH NESTED SEQ) ===");
print("With nested seq for layers and symmetry");
MANDALA(25, "power", 8, 2);

print("");
print("=== 4. SINE WAVES (WITH NESTED SEQ) ===");
print("With nested seq for layers and symmetry");
MANDALA(20, "sine", 12, 3);

print("");
print("========================================");
print("NOW EVERYTHING USES SEQ!");
print("========================================");



 

@acer ,I think the AI is crazy about loops, given my coding experience, and I don't immediately think of the seq command.
AI coding only becomes powerful when you really understand Maple coding.
I'll see if the code can be improved with the help of programming other than standard loop programming, at least if I understand correctly?

Indeed, I used Kitonum's ingenious approach of two exponential functions, which are each other's inverse, and rotate them.

restart;
with(plots): with(plottools):

# ============================================
# 1. DE ORIGINELE MANDALA (EXACT JOUW CODE)
# ============================================

ORIGINELE_MANDALA := proc()
    local Colors, P, n;
    
    Colors := [seq(op(["LightBlue","Indigo","Violet","Red","Orange","Yellow","Green"]), n=1..14)];
    
    P := proc(n)
        uses plots, plottools;
        display(rotate(plot([x^(1+0.1*(n-1)), x^(1/(1+0.1*(n-1)))], 
                           x=0..1, 
                           thickness=5, 
                           color=Colors[round(n)], 
                           transparency=0.4),
                       Pi*n/98, 
                       [0.5,0.5]));
    end proc:
    
    plots:-animate(P, [n], n=1..98, frames=98, trace=[$1..98], 
                   axes=none, size=[700,700], paraminfo=false);
end proc:

# ============================================
# 2. UNIVERSELE MANDALA MAKER - EENVOUDIG
# ============================================

MANDALA := proc(f, soort, sym, lagen)
    # f = aantal frames
    # soort = "origineel", "macht", of "sinus"
    # sym = symmetrie (6, 8, 12, etc.)
    # lagen = aantal lagen (1-5)
    
    local P, n, i, j, trace_lst;
    
    # Maak trace lijst
    trace_lst := [seq(i, i=1..f)];
    
    if soort = "origineel" then
        # Originele stijl
        local Colors2;
        Colors2 := [seq(op(["LightBlue","Indigo","Violet","Red","Orange","Yellow","Green"]), i=1..ceil(f/7))];
        Colors2 := Colors2[1..f];
        
        P := proc(nn)
            local plotje, kleur_idx, exponent_val;
            
            kleur_idx := round(nn);
            if kleur_idx < 1 then kleur_idx := 1;
            elif kleur_idx > f then kleur_idx := f; end if;
            
            exponent_val := 1 + 0.1*(nn-1);
            
            plotje := plot([x^exponent_val, x^(1/exponent_val)], 
                          x=0..1,
                          thickness=3,
                          color=Colors2[kleur_idx],
                          transparency=0.4);
            
            # Symmetrie toevoegen
            local result := plotje;
            for i from 1 to sym-1 do
                result := result, rotate(plotje, 2*Pi*i/sym, [0.5,0.5]);
            end do;
            
            return display(result, axes=none);
        end proc;
        
    elif soort = "macht" then
        # Macht functies
        P := proc(nn)
            local t_val, exp_val, plotje, kleur;
            
            t_val := (nn-1.0)/(f-1.0);
            exp_val := 0.5 + 4.5*t_val;
            kleur := COLOR(HUE, t_val);
            
            plotje := plot([x^exp_val, x^(1/exp_val)], 
                          x=0..1,
                          thickness=2,
                          color=kleur,
                          transparency=0.3);
            
            # Lagen en symmetrie toevoegen
            local result := NULL;
            for i from 1 to lagen do
                for j from 0 to sym-1 do
                    result := result, 
                        rotate(plotje, Pi*nn/f + 2*Pi*j/sym + (i-1)*Pi/(lagen*2), [0.5,0.5]);
                end do;
            end do;
            
            return display(result, axes=none);
        end proc;
        
    elif soort = "sinus" then
        # Sinus golven
        P := proc(nn)
            local t_val, freq_val, plotje, kleur;
            
            t_val := (nn-1.0)/(f-1.0);
            freq_val := 1 + 9*t_val;
            kleur := COLOR(HUE, t_val);
            
            plotje := plot([0.5+0.3*sin(2*Pi*freq_val*x), 
                           0.5+0.3*cos(2*Pi*freq_val*x)], 
                          x=0..1,
                          thickness=2,
                          color=kleur,
                          transparency=0.3);
            
            # Lagen en symmetrie toevoegen
            local result := NULL;
            for i from 1 to lagen do
                for j from 0 to sym-1 do
                    result := result, 
                        rotate(plotje, Pi*nn/f + 2*Pi*j/sym + (i-1)*Pi/(lagen*2), [0.5,0.5]);
                end do;
            end do;
            
            return display(result, axes=none);
        end proc;
        
    else
        # Default: macht functies
        P := proc(nn)
            local t_val, exp_val, plotje, kleur;
            
            t_val := (nn-1.0)/(f-1.0);
            exp_val := 0.5 + 4.5*t_val;
            kleur := COLOR(HUE, t_val);
            
            plotje := plot([x^exp_val, x^(1/exp_val)], 
                          x=0..1,
                          thickness=2,
                          color=kleur,
                          transparency=0.3);
            
            # Lagen en symmetrie toevoegen
            local result := NULL;
            for i from 1 to lagen do
                for j from 0 to sym-1 do
                    result := result, 
                        rotate(plotje, Pi*nn/f + 2*Pi*j/sym + (i-1)*Pi/(lagen*2), [0.5,0.5]);
                end do;
            end do;
            
            return display(result, axes=none);
        end proc;
    end if;
    
    # Maak de animatie
    animate(P, [n], n=1..f, frames=f,
            trace=trace_lst,
            axes=none,
            size=[500,500],
            paraminfo=false);
end proc:

# ============================================
# 3. TESTEN - BEGIN MET ORIGINEEL
# ============================================

print("=== TEST 1: ORIGINELE MANDALA ===");
ORIGINELE_MANDALA();

# Wacht even voordat we verder gaan
# (In Maple kun je niet echt wachten, maar we printen een bericht)
print("Originele mandala wordt geladen... (klik op play in de plot)");

# ============================================
# 4. KLEINERE VOORBEELDEN
# ============================================

print("=== TEST 2: ORIGINELE STIJL (kleiner) ===");
MANDALA(30, "origineel", 12, 1);

print("=== TEST 3: MACHT MANDALA ===");
MANDALA(25, "macht", 8, 2);

print("=== TEST 4: SINUS MANDALA ===");
MANDALA(20, "sinus", 12, 3);

# ============================================
# 5. SIMPELE GEBRUIKERSFUNCTIES
# ============================================

# Voor snel gebruik
SNEL_MANDALA := proc()
    MANDALA(20, "macht", 8, 2);
end proc:

# Origineel maar kleiner
KLEIN_ORIGINEEL := proc()
    MANDALA(40, "origineel", 12, 1);
end proc:

# Sinus effect
SINUS_EFFECT := proc()
    MANDALA(30, "sinus", 10, 2);
end proc:

# ============================================
# 6. DEMO
# ============================================

DEMO := proc()
    print("=== MANDALA DEMO ===");
    
    print("1. Origineel (klein)");
    MANDALA(15, "origineel", 8, 1);
    
    print("2. Macht functies");
    MANDALA(15, "macht", 12, 2);
    
    print("3. Sinus golven");
    MANDALA(15, "sinus", 10, 3);
    
    print("=== DEMO KLAAR ===");
end proc:

# ============================================
# 7. START HIER!
# ============================================

print("=== START MET ORIGINELE MANDALA ===");
ORIGINELE_MANDALA();

print("=== DAARNA PROBEER DIT: ===");
print("1. Voor snelle test: SNEL_MANDALA();");
print("2. Voor origineel kleiner: KLEIN_ORIGINEEL();");
print("3. Voor sinus: SINUS_EFFECT();");
print("4. Voor volledige demo: DEMO();");

 

Its not yet similar :-)

@Jean-Michel 

Take another look, but I'm afraid Maple won't be able to achieve the same effect in MMA.

bye
Jan

@Jean-Michel 
I am a dutch , from the Netherlands, yeah :-) 
But what is the intention of you examples ?
Tip:  for better reading your code use : the insert code snippet knob - right next  A , use tooltip too

Try to do something now with the Head construction from MMA and this apply in Maple ?

@Jean-Michel 

I tried to extend the module code with this new expression, but it appears to be impossible to obtain the same result in Maple.

.

# Debug versie - show all found paths
N := [a, a, 1 + a, [[1/a] + a^2, [a]]]:
result := FindPositions:-ModuleApply(N, a, 'explain'=true);
Expression: [a, a, 1+a, [[1/a]+a^2, [a]]]
Looking for: a
Levelspec: infinity
Found at 6 position(s):
1. Path [1]
2. Path [2]
3. Path [3, 2]
4. Path [4, 1, 1, 1, 1]
5. Path [4, 1, 2, 1]
6. Path [4, 2, 1]

  result := [[1], [2], [3, 2], [4, 1, 1, 1, 1], [4, 1, 2, 1], 

    [4, 2, 1]]

@Jean-Michel 

Calulated by module code 

M := [[a], [[a, [a]], a]];
                   M := [[a], [[a, [a]], a]]

FindPositions(M, a);
           [[1, 1], [2, 1, 1], [2, 1, 2, 1], [2, 2]]

Now using module code ...
Findposions_module_5_vb_werken_DEF_22-1-2026_.mw

ah, yes a special bier , i like that too :-)

@sand15 
Thank you for the recommendations. So, I should see if I can interpret them correctly in order to improve this procedure, so that something new comes out of it?

@Jean-Michel 

"maple.ini in user" ,  i  removed it in the code this ( forget to remove)   , it is a initialization for a new worksheet , has nothing to do with the code 
Now it works the  code.

"i'm too tired :) and it's only 9:30 pm" ..what have you done today  :-)

@Jean-Michel 
Hello,
Tried something , but need more testing., but the example works.
I am also investigating using a module structure in Maple to make it easier to program the FindPositions ( ) overload command.

restart;
FindPositions := proc()
    local 
        parse_levelspec,
        should_process_level,
        recursive_search,
        extract_first_n,
        explain_result,
        compare_paths_mathematica,
        
        arg_list, expr, pattern, levelspec, n, heads,
        min_level, max_level, result, i, ls_temp,
        explanation, test_expected, temp_result, item;
    
    arg_list := [args];
    
    if nops(arg_list) < 2 then
        error "FindPositions expects at least 2 arguments: expression and pattern";
    end if;
    
    expr := arg_list[1];
    pattern := arg_list[2];
    
    levelspec := infinity;
    n := infinity;
    heads := false;
    explanation := false;
    test_expected := false;
    
    i := 3;
    while i <= nops(arg_list) do
        if (type(arg_list[i], {integer, list, set, identical(infinity)}) 
           and levelspec = infinity) then
            if type(arg_list[i], set) then
                levelspec := [op(arg_list[i])];
            else
                levelspec := arg_list[i];
            end if;
        elif type(arg_list[i], posint) and n = infinity then
            n := arg_list[i];
        elif type(arg_list[i], 'identical'('heads'='true', 'heads'='false')) then
            heads := op(2, arg_list[i]);
        elif type(arg_list[i], 'equation') and lhs(arg_list[i]) = 'Heads' then
            heads := rhs(arg_list[i]);
        elif type(arg_list[i], 'identical'('explain'='true', 'explain'='false')) then
            explanation := op(2, arg_list[i]);
        elif type(arg_list[i], 'equation') and lhs(arg_list[i]) = 'Explain' then
            explanation := rhs(arg_list[i]);
        elif type(arg_list[i], 'equation') and lhs(arg_list[i]) = 'Test' then
            test_expected := rhs(arg_list[i]);
        else
            error "Invalid argument at position %1: %2", i, arg_list[i];
        end if;
        i := i + 1;
    end do;
    
    # GECORRIGEERDE parse_levelspec die sets accepteert
    parse_levelspec := proc(ls)
    local ls_list;
        if ls = infinity then
            return [0, infinity];
        elif type(ls, integer) and ls >= 0 then
            return [ls, ls];
        elif type(ls, list) then
            if nops(ls) = 1 and type(ls[1], integer) and ls[1] >= 0 then
                return [ls[1], ls[1]];
            elif nops(ls) = 2 and type(ls[1], integer) and ls[1] >= 0 
                 and (ls[2] = infinity or (type(ls[2], integer) and ls[2] >= ls[1])) then
                return [ls[1], ls[2]];
            end if;
        elif type(ls, set) then
            # Converteer set naar list
            ls_list := [op(ls)];
            if nops(ls_list) = 1 and type(ls_list[1], integer) and ls_list[1] >= 0 then
                return [ls_list[1], ls_list[1]];
            elif nops(ls_list) = 2 and type(ls_list[1], integer) and ls_list[1] >= 0 
                 and (ls_list[2] = infinity or (type(ls_list[2], integer) and ls_list[2] >= ls_list[1])) then
                return [ls_list[1], ls_list[2]];
            end if;
        end if;
        error "levelspec must be n, {n}, {m,n}, or Infinity, received: %1", ls;
    end proc;
    
    should_process_level := proc(current, minlvl, maxlvl)
        if current < minlvl then
            return false;
        elif maxlvl = infinity then
            return true;
        else
            return current <= maxlvl;
        end if;
    end proc;
    
    compare_paths_mathematica := proc(a, b)
    local k, min_len;
        min_len := min(nops(a), nops(b));
        
        for k to min_len do
            if a[k] < b[k] then
                return true;
            elif a[k] > b[k] then
                return false;
            end if;
        end do;
        
        return nops(a) < nops(b);
    end proc;
    
    # GECORRIGEERDE recursieve zoekfunctie voor {1,2}
    recursive_search := proc(expr, pattern, minlvl, maxlvl, path, current_level, heads)
    local i, n_items, result, next_level, args_list, term, sub_result, sub;
        result := [];
        
        if expr = pattern and should_process_level(current_level, minlvl, maxlvl) then
            result := [path];
        end if;
        
        if maxlvl <> infinity and current_level >= maxlvl then
            return result;
        end if;
        
        next_level := current_level + 1;
        
        if type(expr, list) then
            n_items := numelems(expr);
            for i to n_items do
                result := [op(result), 
                          op(procname(expr[i], pattern, minlvl, maxlvl, 
                                     [op(path), i], next_level, heads))];
            od;
            
        elif type(expr, `+`) then
            args_list := [op(expr)];
            n_items := numelems(args_list);
            
            # AANPASSING voor {1,2}: bij beperkte niveaus moeten we anders omgaan met sommen
            if maxlvl <> infinity then
                # Voor {1,2}: alleen exacte matches, niet has()
                for i to n_items do
                    term := args_list[i];
                    if term = pattern and should_process_level(next_level, minlvl, maxlvl) then
                        result := [op(result), [op(path), i]];
                    end if;
                od;
            else
                # Voor infinity: gebruik has() voor patronen binnen termen
                for i to n_items do
                    term := args_list[i];
                    
                    if has(term, pattern) and should_process_level(next_level, minlvl, maxlvl) then
                        result := [op(result), [op(path), i]];
                    end if;
                    
                    if maxlvl = infinity or next_level < maxlvl then
                        sub_result := procname(term, pattern, minlvl, maxlvl,
                                              [op(path), i], next_level, heads);
                        for sub in sub_result do
                            result := [op(result), op(sub)];
                        end do;
                    end if;
                od;
            end if;
            
        elif type(expr, `*`) then
            args_list := [op(expr)];
            n_items := numelems(args_list);
            for i to n_items do
                result := [op(result), 
                          op(procname(args_list[i], pattern, minlvl, maxlvl,
                                     [op(path), i], next_level, heads))];
            od;
        end if;
        
        return result;
    end proc;
    
    extract_first_n := proc(results, n)
    local sorted_results;
        if n = infinity or n >= nops(results) then
            return results;
        else
            sorted_results := sort(results, compare_paths_mathematica);
            return sorted_results[1..min(n, nops(sorted_results))];
        end if;
    end proc;
    
    (min_level, max_level) := op(parse_levelspec(levelspec));
    
    result := recursive_search(expr, pattern, min_level, max_level, [], 0, heads);
    
    temp_result := [];
    for item in result do
        if type(item, list) and nops(item) > 0 then
            temp_result := [op(temp_result), item];
        end if;
    end do;
    result := temp_result;
    
    result := convert(convert(result, 'set'), 'list');
    
    result := sort(result, compare_paths_mathematica);
    
    result := extract_first_n(result, n);
    
    if explanation then
        printf("Expression: %a\n", expr);
        printf("Looking for: %a\n", pattern);
        printf("Found at %d position(s):\n", nops(result));
        for i to nops(result) do
            printf("%d. Path %a\n", i, result[i]);
        od;
    end if;
    
    if test_expected <> false then
        if result = test_expected then
            printf("✓ TEST PASSED: Result matches expected output\n");
        else
            printf("✗ TEST FAILED:\n");
            printf("  Expected: %a\n", test_expected);
            printf("  Got:      %a\n", result);
        end if;
    end if;
    
    return result;
end proc:
                   
# TEST 
M := [[1, a], a, [[3 + a]], 2*a - 1]:

# Verify that the other tests still work
printf("\n=============================================\n");
printf("VERIFICATION OF OTHER TESTS:\n");
printf("=============================================\n");

printf("TEST 1: All positions of 'a' in M\n");
result1 := FindPositions(M, a, 'Test' = [[1, 2], [2], [3, 1, 1, 2], [4, 1]]);
printf("Result: %a\n\n", result1);

printf("TEST 2: Level 1 only\n");
result2 := FindPositions(M, a, 1, 'Test' = [[2]]);
printf("Result: %a\n\n", result2);

printf("=============================================\n");
printf("TEST 3 ONLY: Levels 1 and 2\n");
printf("Expected: [[1, 2], [2]]\n");
printf("=============================================\n");
result3 := FindPositions(M, a, {1, 2}, 'Test' = [[1, 2], [2]]);
printf("Result: %a\n", result3);

printf("TEST 4: From level 2 onwards\n");
result4 := FindPositions(M, a, {2, infinity}, 'Test' = [[1, 2], [3, 1, 1, 2], [4, 1]]);
printf("Result: %a\n\n", result4);

printf("TEST 5: First 2 results\n");
result5 := FindPositions(M, a, infinity, 2, 'Test' = [[1, 2], [2]]);
printf("Result: %a\n", result5);

@Jean-Michel 
Need to clarify which test examples for Mathematica are available for the Position function?
Maybe the desired functionality can be done in Maple ?

1 2 3 4 5 6 7 Last Page 1 of 82