MaplePrimes Posts

MaplePrimes Posts are for sharing your experiences, techniques and opinions about Maple, MapleSim and related products, as well as general interests in math and computing.

Latest Post
  • Latest Posts Feed
  • I think a new integer subtype is needed: integer greater than one, gtoint.

    isgto := proc(x::anything)
      local X;
      X:=x;
      return type(X,integer) and (X>1);
    end:

    AddType(gtoint,z->not isgto(z));

    Hello,

    This is a simple dynamics example illustrating the behavior of a disc as a pendulum under ideal conditions. Source attached.

    Simple_Disk_Pendulum.mw

    I am very happy to announce the first public release of a project which I have been working on for the last couple of years.

    NODEMaple consists of a set of Maple workbooks and a library for structural design based on the Eurocode.

    Currently the main development of the workbooks is focused on "Eurocode 5: Design of timber structures" with the Norwegian Annex.

    This software has been made public in the hope of that it might be useful for other structural designers, professionals as well as students. Everyone interested is very Welcome to contribute to this project. The code is published under the GPLv3 license.

    For more information see https://github.com/Anthrazit68/NODEMaple.

    I didn't put it in the title, but of course this is a post about Advent of Code, in particular Days 16 and 18 which feature a perenial favorite type of problem: finding shortest paths in mazes.

    Your input for these is always a maze given as an ascii map.  Like so:

    ###############
    #.......#....E#
    #.#.###.#.###.#
    #.....#.#...#.#
    #.###.#####.#.#
    #.#....#....#.#
    #.#.#####.###.#
    #...........#.#
    ###.#.#####.#.#
    #...#.....#.#.#
    #.#.#.###.#.#.#
    #.....#...#.#.#
    #.###.#.#.#.#.#
    #S......#.#...#
    ###############
    

    There's lots of ways to import one of these into Maple and then solve the maze, but I am to highlight how to do it with GraphTheory.  I am going to start with a GridGraph and then remove the walls in order to leave a just the vertices that represent the paths:

    with(StringTools): with(GraphTheory):
    maze:=
    "###############
    #.......#....E#
    #.#.###.#.###.#
    #.....#.#...#.#
    #.###.#####.#.#
    #.#....#....#.#
    #.#.#####.###.#
    #...........#.#
    ###.#.#####.#.#
    #...#.....#.#.#
    #.#.#.###.#.#.#
    #.....#...#.#.#
    #.###.#.#.#.#.#
    #S......#.#...#
    ###############
    ":
    mazelines := (Split(Trim(maze), "\n")):
    sgrid := ListTools:-Reverse((map(Explode, mazelines)) ):
    m,n := nops(sgrid), nops(sgrid[1]);
    tgrid := table([seq(seq([i,j]=sgrid[i,j],i=1..m),j=1..n)]):
    start := lhs(select(e->rhs(e)="S", [entries(tgrid,'pairs')])[]);
    finish := lhs(select(e->rhs(e)="E", [entries(tgrid,'pairs')])[]);

    Now the maze is stored in the table tgrid, and it is easy to find the walls and paths.  In a GridGraph the vertices are labeled with their coordinates as "x,y" and so we rewrite our list of paths in that form, so we can create the induced subgraph of the Grid that includes only those vertices.

    (walls,paths) := selectremove(e->rhs(e)="#", [entries(tgrid, 'pairs')]):
    paths := map(s->sprintf("%d,%d",lhs(s)[]), paths):
    H := SpecialGraphs:-GridGraph(m,n);
    G := InducedSubgraph(H, paths);

    We can use StyleVertex to highlight the start and finish.

    StyleVertex(G, sprintf("%d,%d",start[]), color="LimeGreen");
    StyleVertex(G, sprintf("%d,%d",finish[]), color="Red");
    
    plots:-display(<
    DrawGraph(H, stylesheet=[vertexshape="square", vertexborder=false, vertexcolor="Black"], showlabels=false) | 
    DrawGraph(G, stylesheet=[vertexshape="square", vertexborder=false, vertexcolor="Black"], showlabels=false)>);
    

    (I omitted a step where I set the vertex locations of the maze grid, you can see that in the attached worksheet)

    Now finding a path through the maze is as easy as calling GraphTheory:-ShortestPath

    sp := ShortestPath(G, sprintf("%d,%d",start[]), sprintf("%d,%d",finish[]) ):
    
    StyleVertex(G, sp[2..-2], color="Orange");
    StyleEdge(G, [seq({sp[i],sp[i+1]}, i=1..nops(sp)-1)], color="Orange");
    DrawGraph(G, stylesheet=[vertexshape="square", vertexpadding=10, vertexborder=false,
                 vertexcolor="Black"],  showlabels=false, size=[800,800]);
    

    Now, Advent of Code seldom gives you a completely simple maze like this, often these is a twist like having to calculate the costs of turns seperately from the cost of steps, or each direction or position has a seperate cost associated with it.

    For example, Day 16 has us starting facing east, and then turns cost 1000, while moving forward costs 1. That sort of problem is no longer exactly a maze, instead of the vertices being representing an "x,y" position, instead you increase the number of vertices by a factor of 4, so that you have a vertex for every position and orientation "x,y,o" with edges of weight 1 between adjacent vertices with the same orientation and edges of wieght 1000 to connect "x,y,N" to "x,y,E" and "x,y,W" e.g.  In that sort of weighted graph, we can use GraphTheory:-DijkstrasAlgorithm to find the shortest path and it's weighted cost.

    In this code, we expand our list of maze locations with directions, and the use the grid table to generate a list of weighted edges:

    dtable := table([0=[0,1], 1=[1,0], 2=[0,-1], 3=[-1,0]]):
    dname := table([0="N",1="E",2="S",3="W"]):
    dpaths := map(s->local d;seq(cat(s,",",d), d in ["N","E","S","W"]), paths):
    
    edges := NULL:
    for i from 1 to m do for j from 1 to n do
        if tgrid[[i,j]] = "#" then next; end if;
        for d from 0 to 3 do
            dir := dtable[d];
            if tgrid[[i,j]+dir] <> "#" then
                edges := edges, [{cat("",i,",",j,",",dname[d]), cat("",i+dir[1],",",j+dir[2],",",dname[d])},1];
            end if;
            edges := edges, [{cat("",i,",",j,",",dname[d]), cat("",i,",",j,",",dname[d+1 mod 4])}, 1000],
                     [{cat("",i,",",j,",",dname[d]), cat("",i,",",j,",",dname[d-1 mod 4])}, 1000];
        end do;
    end do; end do:
    
    Gd := Graph(dpaths,weighted,{edges});

    Once that is done, it's a simple matter of calling Dijkstra's Algorithm on the graph, but notice that we can reach the finsh while traveling north or east, so we need to find the sortest path to both (you can pass a list of vertices to Dijkstra, and it will efficiently calculate paths to all of them), and select the smaller of the two:

    spds := DijkstrasAlgorithm(Gd, cat("",start[1],",",start[2],",E"), 
        [cat("",finish[1],",",finish[2],",N"), cat("",finish[1],",",finish[2],",E")] , 
        distance):
    i := min[index](map2(op,2,spds)):
    spd := spds[i];
    
    spd := [["2,2,E", "3,2,E", "4,2,E", "4,2,N", "4,3,N", "4,4,N", "4,5,N", "4,6,N", "4,6,E", "5,6,E",
     "6,6,E", "7,6,E", "8,6,E", "8,6,N", "8,7,N", "8,8,N", "8,9,N", "8,10,N", "8,11,N", "8,12,N", 
    "8,12,W", "7,12,W", "6,12,W", "5,12,W", "4,12,W", "3,12,W", "2,12,W", "2,12,N", "2,13,N", 
    "2,14,N", "2,14,E", "3,14,E", "4,14,E", "5,14,E", "6,14,E", "7,14,E", "8,14,E", "9,14,E", 
    "10,14,E", "11,14,E", "12,14,E", "13,14,E", "14,14,E"], 6036]

    We can then plot to compare this to the unweighted shortest path:

    dsp := ListTools:-MakeUnique( map(s->s[1..-3], spd[1]) );
    StyleVertex(G, dsp[2..-2], color="DarkBlue");
    StyleEdge(G, [seq({dsp[i],dsp[i+1]}, i=1..nops(dsp)-1)], color="DarkBlue");
    
    DrawGraph(G, stylesheet=[vertexshape="square", vertexpadding=10,
                 vertexborder=false, vertexcolor="Black"],  showlabels=false,
              size=[800,800]);

    And you can see it's a path that requires more steps, but definitely uses fewer turns if we start facing east/right (6 vs. 9):

    I hope this has given you a little bit of a flavor of how to use GraphTheory commands to solve path finding problems.  Like with the second part here, usually the biggest challenge is figuring out how to encode and construct a graph that represents your problem.  Then the actual commands to solve it, are easy. You can see all the code, and a couple steps I left out from above in this worksheet: Mazeblog.mw

    And just for fun, here's a Maple workbook that imports a maze from an image and solves it: MazeFromImage.maple

    with(ImageTools): with(GraphTheory):

    opic := Read("this://DrawnMaze.png"):
    Embed(opic);

    bwpic := RGBtoGray(opic):
    pic := Flip(Transpose(Scale(bwpic, 0.1, 0.1, method = nearest)),horizontal ):

    m,n := upperbound(pic);
    start := [2,31];
    finish := [30,1];

    31, 31

     

    [2, 31]

     

    [30, 1]

    (1)

    (paths,walls) := selectremove(e->round(rhs(e))=1, [entries(pic, 'pairs')]):
    walls := map(s->sprintf("%d,%d",lhs(s)), walls):
    paths := map(s->sprintf("%d,%d",lhs(s)), paths):

    H := SpecialGraphs:-GridGraph(m,n);
    G := InducedSubgraph(H, paths);

    GRAPHLN(undirected, unweighted, ["1,1", "1,2", "1,3", "1,4", "1,5", "1,6", "1,7", "1,8", "1,9", "1,10", "1,11", "1,12", "1,13", "1,14", "1,15", "1,16", "1,17", "1,18", "1,19", "1,20", "1,21", "1,22", "1,23", "1,24", "1,25", "1,26", "1,27", "1,28", "1,29", "1,30", "1,31", "2,1", "2,2", "2,3", "2,4", "2,5", "2,6", "2,7", "2,8", "2,9", "2,10", "2,11", "2,12", "2,13", "2,14", "2,15", "2,16", "2,17", "2,18", "2,19", "2,20", "2,21", "2,22", "2,23", "2,24", "2,25", "2,26", "2,27", "2,28", "2,29", "2,30", "2,31", "3,1", "3,2", "3,3", "3,4", "3,5", "3,6", "3,7", "3,8", "3,9", "3,10", "3,11", "3,12", "3,13", "3,14", "3,15", "3,16", "3,17", "3,18", "3,19", "3,20", "3,21", "3,22", "3,23", "3,24", "3,25", "3,26", "3,27", "3,28", "3,29", "3,30", "3,31", "4,1", "4,2", "4,3", "4,4", "4,5", "4,6", "4,7", "4,8", "4,9", "4,10", "4,11", "4,12", "4,13", "4,14", "4,15", "4,16", "4,17", "4,18", "4,19", "4,20", "4,21", "4,22", "4,23", "4,24", "4,25", "4,26", "4,27", "4,28", "4,29", "4,30", "4,31", "5,1", "5,2", "5,3", "5,4", "5,5", "5,6", "5,7", "5,8", "5,9", "5,10", "5,11", "5,12", "5,13", "5,14", "5,15", "5,16", "5,17", "5,18", "5,19", "5,20", "5,21", "5,22", "5,23", "5,24", "5,25", "5,26", "5,27", "5,28", "5,29", "5,30", "5,31", "6,1", "6,2", "6,3", "6,4", "6,5", "6,6", "6,7", "6,8", "6,9", "6,10", "6,11", "6,12", "6,13", "6,14", "6,15", "6,16", "6,17", "6,18", "6,19", "6,20", "6,21", "6,22", "6,23", "6,24", "6,25", "6,26", "6,27", "6,28", "6,29", "6,30", "6,31", "7,1", "7,2", "7,3", "7,4", "7,5", "7,6", "7,7", "7,8", "7,9", "7,10", "7,11", "7,12", "7,13", "7,14", "7,15", "7,16", "7,17", "7,18", "7,19", "7,20", "7,21", "7,22", "7,23", "7,24", "7,25", "7,26", "7,27", "7,28", "7,29", "7,30", "7,31", "8,1", "8,2", "8,3", "8,4", "8,5", "8,6", "8,7", "8,8", "8,9", "8,10", "8,11", "8,12", "8,13", "8,14", "8,15", "8,16", "8,17", "8,18", "8,19", "8,20", "8,21", "8,22", "8,23", "8,24", "8,25", "8,26", "8,27", "8,28", "8,29", "8,30", "8,31", "9,1", "9,2", "9,3", "9,4", "9,5", "9,6", "9,7", "9,8", "9,9", "9,10", "9,11", "9,12", "9,13", "9,14", "9,15", "9,16", "9,17", "9,18", "9,19", "9,20", "9,21", "9,22", "9,23", "9,24", "9,25", "9,26", "9,27", "9,28", "9,29", "9,30", "9,31", "10,1", "10,2", "10,3", "10,4", "10,5", "10,6", "10,7", "10,8", "10,9", "10,10", "10,11", "10,12", "10,13", "10,14", "10,15", "10,16", "10,17", "10,18", "10,19", "10,20", "10,21", "10,22", "10,23", "10,24", "10,25", "10,26", "10,27", "10,28", "10,29", "10,30", "10,31", "11,1", "11,2", "11,3", "11,4", "11,5", "11,6", "11,7", "11,8", "11,9", "11,10", "11,11", "11,12", "11,13", "11,14", "11,15", "11,16", "11,17", "11,18", "11,19", "11,20", "11,21", "11,22", "11,23", "11,24", "11,25", "11,26", "11,27", "11,28", "11,29", "11,30", "11,31", "12,1", "12,2", "12,3", "12,4", "12,5", "12,6", "12,7", "12,8", "12,9", "12,10", "12,11", "12,12", "12,13", "12,14", "12,15", "12,16", "12,17", "12,18", "12,19", "12,20", "12,21", "12,22", "12,23", "12,24", "12,25", "12,26", "12,27", "12,28", "12,29", "12,30", "12,31", "13,1", "13,2", "13,3", "13,4", "13,5", "13,6", "13,7", "13,8", "13,9", "13,10", "13,11", "13,12", "13,13", "13,14", "13,15", "13,16", "13,17", "13,18", "13,19", "13,20", "13,21", "13,22", "13,23", "13,24", "13,25", "13,26", "13,27", "13,28", "13,29", "13,30", "13,31", "14,1", "14,2", "14,3", "14,4", "14,5", "14,6", "14,7", "14,8", "14,9", "14,10", "14,11", "14,12", "14,13", "14,14", "14,15", "14,16", "14,17", "14,18", "14,19", "14,20", "14,21", "14,22", "14,23", "14,24", "14,25", "14,26", "14,27", "14,28", "14,29", "14,30", "14,31", "15,1", "15,2", "15,3", "15,4", "15,5", "15,6", "15,7", "15,8", "15,9", "15,10", "15,11", "15,12", "15,13", "15,14", "15,15", "15,16", "15,17", "15,18", "15,19", "15,20", "15,21", "15,22", "15,23", "15,24", "15,25", "15,26", "15,27", "15,28", "15,29", "15,30", "15,31", "16,1", "16,2", "16,3", "16,4", "16,5", "16,6", "16,7", "16,8", "16,9", "16,10", "16,11", "16,12", "16,13", "16,14", "16,15", "16,16", "16,17", "16,18", "16,19", "16,20", "16,21", "16,22", "16,23", "16,24", "16,25", "16,26", "16,27", "16,28", "16,29", "16,30", "16,31", "17,1", "17,2", "17,3", "17,4", "17,5", "17,6", "17,7", "17,8", "17,9", "17,10", "17,11", "17,12", "17,13", "17,14", "17,15", "17,16", "17,17", "17,18", "17,19", "17,20", "17,21", "17,22", "17,23", "17,24", "17,25", "17,26", "17,27", "17,28", "17,29", "17,30", "17,31", "18,1", "18,2", "18,3", "18,4", "18,5", "18,6", "18,7", "18,8", "18,9", "18,10", "18,11", "18,12", "18,13", "18,14", "18,15", "18,16", "18,17", "18,18", "18,19", "18,20", "18,21", "18,22", "18,23", "18,24", "18,25", "18,26", "18,27", "18,28", "18,29", "18,30", "18,31", "19,1", "19,2", "19,3", "19,4", "19,5", "19,6", "19,7", "19,8", "19,9", "19,10", "19,11", "19,12", "19,13", "19,14", "19,15", "19,16", "19,17", "19,18", "19,19", "19,20", "19,21", "19,22", "19,23", "19,24", "19,25", "19,26", "19,27", "19,28", "19,29", "19,30", "19,31", "20,1", "20,2", "20,3", "20,4", "20,5", "20,6", "20,7", "20,8", "20,9", "20,10", "20,11", "20,12", "20,13", "20,14", "20,15", "20,16", "20,17", "20,18", "20,19", "20,20", "20,21", "20,22", "20,23", "20,24", "20,25", "20,26", "20,27", "20,28", "20,29", "20,30", "20,31", "21,1", "21,2", "21,3", "21,4", "21,5", "21,6", "21,7", "21,8", "21,9", "21,10", "21,11", "21,12", "21,13", "21,14", "21,15", "21,16", "21,17", "21,18", "21,19", "21,20", "21,21", "21,22", "21,23", "21,24", "21,25", "21,26", "21,27", "21,28", "21,29", "21,30", "21,31", "22,1", "22,2", "22,3", "22,4", "22,5", "22,6", "22,7", "22,8", "22,9", "22,10", "22,11", "22,12", "22,13", "22,14", "22,15", "22,16", "22,17", "22,18", "22,19", "22,20", "22,21", "22,22", "22,23", "22,24", "22,25", "22,26", "22,27", "22,28", "22,29", "22,30", "22,31", "23,1", "23,2", "23,3", "23,4", "23,5", "23,6", "23,7", "23,8", "23,9", "23,10", "23,11", "23,12", "23,13", "23,14", "23,15", "23,16", "23,17", "23,18", "23,19", "23,20", "23,21", "23,22", "23,23", "23,24", "23,25", "23,26", "23,27", "23,28", "23,29", "23,30", "23,31", "24,1", "24,2", "24,3", "24,4", "24,5", "24,6", "24,7", "24,8", "24,9", "24,10", "24,11", "24,12", "24,13", "24,14", "24,15", "24,16", "24,17", "24,18", "24,19", "24,20", "24,21", "24,22", "24,23", "24,24", "24,25", "24,26", "24,27", "24,28", "24,29", "24,30", "24,31", "25,1", "25,2", "25,3", "25,4", "25,5", "25,6", "25,7", "25,8", "25,9", "25,10", "25,11", "25,12", "25,13", "25,14", "25,15", "25,16", "25,17", "25,18", "25,19", "25,20", "25,21", "25,22", "25,23", "25,24", "25,25", "25,26", "25,27", "25,28", "25,29", "25,30", "25,31", "26,1", "26,2", "26,3", "26,4", "26,5", "26,6", "26,7", "26,8", "26,9", "26,10", "26,11", "26,12", "26,13", "26,14", "26,15", "26,16", "26,17", "26,18", "26,19", "26,20", "26,21", "26,22", "26,23", "26,24", "26,25", "26,26", "26,27", "26,28", "26,29", "26,30", "26,31", "27,1", "27,2", "27,3", "27,4", "27,5", "27,6", "27,7", "27,8", "27,9", "27,10", "27,11", "27,12", "27,13", "27,14", "27,15", "27,16", "27,17", "27,18", "27,19", "27,20", "27,21", "27,22", "27,23", "27,24", "27,25", "27,26", "27,27", "27,28", "27,29", "27,30", "27,31", "28,1", "28,2", "28,3", "28,4", "28,5", "28,6", "28,7", "28,8", "28,9", "28,10", "28,11", "28,12", "28,13", "28,14", "28,15", "28,16", "28,17", "28,18", "28,19", "28,20", "28,21", "28,22", "28,23", "28,24", "28,25", "28,26", "28,27", "28,28", "28,29", "28,30", "28,31", "29,1", "29,2", "29,3", "29,4", "29,5", "29,6", "29,7", "29,8", "29,9", "29,10", "29,11", "29,12", "29,13", "29,14", "29,15", "29,16", "29,17", "29,18", "29,19", "29,20", "29,21", "29,22", "29,23", "29,24", "29,25", "29,26", "29,27", "29,28", "29,29", "29,30", "29,31", "30,1", "30,2", "30,3", "30,4", "30,5", "30,6", "30,7", "30,8", "30,9", "30,10", "30,11", "30,12", "30,13", "30,14", "30,15", "30,16", "30,17", "30,18", "30,19", "30,20", "30,21", "30,22", "30,23", "30,24", "30,25", "30,26", "30,27", "30,28", "30,29", "30,30", "30,31", "31,1", "31,2", "31,3", "31,4", "31,5", "31,6", "31,7", "31,8", "31,9", "31,10", "31,11", "31,12", "31,13", "31,14", "31,15", "31,16", "31,17", "31,18", "31,19", "31,20", "31,21", "31,22", "31,23", "31,24", "31,25", "31,26", "31,27", "31,28", "31,29", "31,30", "31,31"], Array(1..961, {(1) = {2, 32}, (2) = {1, 3, 33}, (3) = {2, 4, 34}, (4) = {3, 5, 35}, (5) = {4, 6, 36}, (6) = {5, 7, 37}, (7) = {6, 8, 38}, (8) = {7, 9, 39}, (9) = {8, 10, 40}, (10) = {9, 11, 41}, (11) = {10, 12, 42}, (12) = {11, 13, 43}, (13) = {12, 14, 44}, (14) = {13, 15, 45}, (15) = {14, 16, 46}, (16) = {15, 17, 47}, (17) = {16, 18, 48}, (18) = {17, 19, 49}, (19) = {18, 20, 50}, (20) = {19, 21, 51}, (21) = {20, 22, 52}, (22) = {21, 23, 53}, (23) = {22, 24, 54}, (24) = {23, 25, 55}, (25) = {24, 26, 56}, (26) = {25, 27, 57}, (27) = {26, 28, 58}, (28) = {27, 29, 59}, (29) = {28, 30, 60}, (30) = {29, 31, 61}, (31) = {30, 62}, (32) = {1, 33, 63}, (33) = {2, 32, 34, 64}, (34) = {3, 33, 35, 65}, (35) = {4, 34, 36, 66}, (36) = {5, 35, 37, 67}, (37) = {6, 36, 38, 68}, (38) = {7, 37, 39, 69}, (39) = {8, 38, 40, 70}, (40) = {9, 39, 41, 71}, (41) = {10, 40, 42, 72}, (42) = {11, 41, 43, 73}, (43) = {12, 42, 44, 74}, (44) = {13, 43, 45, 75}, (45) = {14, 44, 46, 76}, (46) = {15, 45, 47, 77}, (47) = {16, 46, 48, 78}, (48) = {17, 47, 49, 79}, (49) = {18, 48, 50, 80}, (50) = {19, 49, 51, 81}, (51) = {20, 50, 52, 82}, (52) = {21, 51, 53, 83}, (53) = {22, 52, 54, 84}, (54) = {23, 53, 55, 85}, (55) = {24, 54, 56, 86}, (56) = {25, 55, 57, 87}, (57) = {26, 56, 58, 88}, (58) = {27, 57, 59, 89}, (59) = {28, 58, 60, 90}, (60) = {29, 59, 61, 91}, (61) = {30, 60, 62, 92}, (62) = {31, 61, 93}, (63) = {32, 64, 94}, (64) = {33, 63, 65, 95}, (65) = {34, 64, 66, 96}, (66) = {35, 65, 67, 97}, (67) = {36, 66, 68, 98}, (68) = {37, 67, 69, 99}, (69) = {38, 68, 70, 100}, (70) = {39, 69, 71, 101}, (71) = {40, 70, 72, 102}, (72) = {41, 71, 73, 103}, (73) = {42, 72, 74, 104}, (74) = {43, 73, 75, 105}, (75) = {44, 74, 76, 106}, (76) = {45, 75, 77, 107}, (77) = {46, 76, 78, 108}, (78) = {47, 77, 79, 109}, (79) = {48, 78, 80, 110}, (80) = {49, 79, 81, 111}, (81) = {50, 80, 82, 112}, (82) = {51, 81, 83, 113}, (83) = {52, 82, 84, 114}, (84) = {53, 83, 85, 115}, (85) = {54, 84, 86, 116}, (86) = {55, 85, 87, 117}, (87) = {56, 86, 88, 118}, (88) = {57, 87, 89, 119}, (89) = {58, 88, 90, 120}, (90) = {59, 89, 91, 121}, (91) = {60, 90, 92, 122}, (92) = {61, 91, 93, 123}, (93) = {62, 92, 124}, (94) = {63, 95, 125}, (95) = {64, 94, 96, 126}, (96) = {65, 95, 97, 127}, (97) = {66, 96, 98, 128}, (98) = {67, 97, 99, 129}, (99) = {68, 98, 100, 130}, (100) = {69, 99, 101, 131}, (101) = {70, 100, 102, 132}, (102) = {71, 101, 103, 133}, (103) = {72, 102, 104, 134}, (104) = {73, 103, 105, 135}, (105) = {74, 104, 106, 136}, (106) = {75, 105, 107, 137}, (107) = {76, 106, 108, 138}, (108) = {77, 107, 109, 139}, (109) = {78, 108, 110, 140}, (110) = {79, 109, 111, 141}, (111) = {80, 110, 112, 142}, (112) = {81, 111, 113, 143}, (113) = {82, 112, 114, 144}, (114) = {83, 113, 115, 145}, (115) = {84, 114, 116, 146}, (116) = {85, 115, 117, 147}, (117) = {86, 116, 118, 148}, (118) = {87, 117, 119, 149}, (119) = {88, 118, 120, 150}, (120) = {89, 119, 121, 151}, (121) = {90, 120, 122, 152}, (122) = {91, 121, 123, 153}, (123) = {92, 122, 124, 154}, (124) = {93, 123, 155}, (125) = {94, 126, 156}, (126) = {95, 125, 127, 157}, (127) = {96, 126, 128, 158}, (128) = {97, 127, 129, 159}, (129) = {98, 128, 130, 160}, (130) = {99, 129, 131, 161}, (131) = {100, 130, 132, 162}, (132) = {101, 131, 133, 163}, (133) = {102, 132, 134, 164}, (134) = {103, 133, 135, 165}, (135) = {104, 134, 136, 166}, (136) = {105, 135, 137, 167}, (137) = {106, 136, 138, 168}, (138) = {107, 137, 139, 169}, (139) = {108, 138, 140, 170}, (140) = {109, 139, 141, 171}, (141) = {110, 140, 142, 172}, (142) = {111, 141, 143, 173}, (143) = {112, 142, 144, 174}, (144) = {113, 143, 145, 175}, (145) = {114, 144, 146, 176}, (146) = {115, 145, 147, 177}, (147) = {116, 146, 148, 178}, (148) = {117, 147, 149, 179}, (149) = {118, 148, 150, 180}, (150) = {119, 149, 151, 181}, (151) = {120, 150, 152, 182}, (152) = {121, 151, 153, 183}, (153) = {122, 152, 154, 184}, (154) = {123, 153, 155, 185}, (155) = {124, 154, 186}, (156) = {125, 157, 187}, (157) = {126, 156, 158, 188}, (158) = {127, 157, 159, 189}, (159) = {128, 158, 160, 190}, (160) = {129, 159, 161, 191}, (161) = {130, 160, 162, 192}, (162) = {131, 161, 163, 193}, (163) = {132, 162, 164, 194}, (164) = {133, 163, 165, 195}, (165) = {134, 164, 166, 196}, (166) = {135, 165, 167, 197}, (167) = {136, 166, 168, 198}, (168) = {137, 167, 169, 199}, (169) = {138, 168, 170, 200}, (170) = {139, 169, 171, 201}, (171) = {140, 170, 172, 202}, (172) = {141, 171, 173, 203}, (173) = {142, 172, 174, 204}, (174) = {143, 173, 175, 205}, (175) = {144, 174, 176, 206}, (176) = {145, 175, 177, 207}, (177) = {146, 176, 178, 208}, (178) = {147, 177, 179, 209}, (179) = {148, 178, 180, 210}, (180) = {149, 179, 181, 211}, (181) = {150, 180, 182, 212}, (182) = {151, 181, 183, 213}, (183) = {152, 182, 184, 214}, (184) = {153, 183, 185, 215}, (185) = {154, 184, 186, 216}, (186) = {155, 185, 217}, (187) = {156, 188, 218}, (188) = {157, 187, 189, 219}, (189) = {158, 188, 190, 220}, (190) = {159, 189, 191, 221}, (191) = {160, 190, 192, 222}, (192) = {161, 191, 193, 223}, (193) = {162, 192, 194, 224}, (194) = {163, 193, 195, 225}, (195) = {164, 194, 196, 226}, (196) = {165, 195, 197, 227}, (197) = {166, 196, 198, 228}, (198) = {167, 197, 199, 229}, (199) = {168, 198, 200, 230}, (200) = {169, 199, 201, 231}, (201) = {170, 200, 202, 232}, (202) = {171, 201, 203, 233}, (203) = {172, 202, 204, 234}, (204) = {173, 203, 205, 235}, (205) = {174, 204, 206, 236}, (206) = {175, 205, 207, 237}, (207) = {176, 206, 208, 238}, (208) = {177, 207, 209, 239}, (209) = {178, 208, 210, 240}, (210) = {179, 209, 211, 241}, (211) = {180, 210, 212, 242}, (212) = {181, 211, 213, 243}, (213) = {182, 212, 214, 244}, (214) = {183, 213, 215, 245}, (215) = {184, 214, 216, 246}, (216) = {185, 215, 217, 247}, (217) = {186, 216, 248}, (218) = {187, 219, 249}, (219) = {188, 218, 220, 250}, (220) = {189, 219, 221, 251}, (221) = {190, 220, 222, 252}, (222) = {191, 221, 223, 253}, (223) = {192, 222, 224, 254}, (224) = {193, 223, 225, 255}, (225) = {194, 224, 226, 256}, (226) = {195, 225, 227, 257}, (227) = {196, 226, 228, 258}, (228) = {197, 227, 229, 259}, (229) = {198, 228, 230, 260}, (230) = {199, 229, 231, 261}, (231) = {200, 230, 232, 262}, (232) = {201, 231, 233, 263}, (233) = {202, 232, 234, 264}, (234) = {203, 233, 235, 265}, (235) = {204, 234, 236, 266}, (236) = {205, 235, 237, 267}, (237) = {206, 236, 238, 268}, (238) = {207, 237, 239, 269}, (239) = {208, 238, 240, 270}, (240) = {209, 239, 241, 271}, (241) = {210, 240, 242, 272}, (242) = {211, 241, 243, 273}, (243) = {212, 242, 244, 274}, (244) = {213, 243, 245, 275}, (245) = {214, 244, 246, 276}, (246) = {215, 245, 247, 277}, (247) = {216, 246, 248, 278}, (248) = {217, 247, 279}, (249) = {218, 250, 280}, (250) = {219, 249, 251, 281}, (251) = {220, 250, 252, 282}, (252) = {221, 251, 253, 283}, (253) = {222, 252, 254, 284}, (254) = {223, 253, 255, 285}, (255) = {224, 254, 256, 286}, (256) = {225, 255, 257, 287}, (257) = {226, 256, 258, 288}, (258) = {227, 257, 259, 289}, (259) = {228, 258, 260, 290}, (260) = {229, 259, 261, 291}, (261) = {230, 260, 262, 292}, (262) = {231, 261, 263, 293}, (263) = {232, 262, 264, 294}, (264) = {233, 263, 265, 295}, (265) = {234, 264, 266, 296}, (266) = {235, 265, 267, 297}, (267) = {236, 266, 268, 298}, (268) = {237, 267, 269, 299}, (269) = {238, 268, 270, 300}, (270) = {239, 269, 271, 301}, (271) = {240, 270, 272, 302}, (272) = {241, 271, 273, 303}, (273) = {242, 272, 274, 304}, (274) = {243, 273, 275, 305}, (275) = {244, 274, 276, 306}, (276) = {245, 275, 277, 307}, (277) = {246, 276, 278, 308}, (278) = {247, 277, 279, 309}, (279) = {248, 278, 310}, (280) = {249, 281, 311}, (281) = {250, 280, 282, 312}, (282) = {251, 281, 283, 313}, (283) = {252, 282, 284, 314}, (284) = {253, 283, 285, 315}, (285) = {254, 284, 286, 316}, (286) = {255, 285, 287, 317}, (287) = {256, 286, 288, 318}, (288) = {257, 287, 289, 319}, (289) = {258, 288, 290, 320}, (290) = {259, 289, 291, 321}, (291) = {260, 290, 292, 322}, (292) = {261, 291, 293, 323}, (293) = {262, 292, 294, 324}, (294) = {263, 293, 295, 325}, (295) = {264, 294, 296, 326}, (296) = {265, 295, 297, 327}, (297) = {266, 296, 298, 328}, (298) = {267, 297, 299, 329}, (299) = {268, 298, 300, 330}, (300) = {269, 299, 301, 331}, (301) = {270, 300, 302, 332}, (302) = {271, 301, 303, 333}, (303) = {272, 302, 304, 334}, (304) = {273, 303, 305, 335}, (305) = {274, 304, 306, 336}, (306) = {275, 305, 307, 337}, (307) = {276, 306, 308, 338}, (308) = {277, 307, 309, 339}, (309) = {278, 308, 310, 340}, (310) = {279, 309, 341}, (311) = {280, 312, 342}, (312) = {281, 311, 313, 343}, (313) = {282, 312, 314, 344}, (314) = {283, 313, 315, 345}, (315) = {284, 314, 316, 346}, (316) = {285, 315, 317, 347}, (317) = {286, 316, 318, 348}, (318) = {287, 317, 319, 349}, (319) = {288, 318, 320, 350}, (320) = {289, 319, 321, 351}, (321) = {290, 320, 322, 352}, (322) = {291, 321, 323, 353}, (323) = {292, 322, 324, 354}, (324) = {293, 323, 325, 355}, (325) = {294, 324, 326, 356}, (326) = {295, 325, 327, 357}, (327) = {296, 326, 328, 358}, (328) = {297, 327, 329, 359}, (329) = {298, 328, 330, 360}, (330) = {299, 329, 331, 361}, (331) = {300, 330, 332, 362}, (332) = {301, 331, 333, 363}, (333) = {302, 332, 334, 364}, (334) = {303, 333, 335, 365}, (335) = {304, 334, 336, 366}, (336) = {305, 335, 337, 367}, (337) = {306, 336, 338, 368}, (338) = {307, 337, 339, 369}, (339) = {308, 338, 340, 370}, (340) = {309, 339, 341, 371}, (341) = {310, 340, 372}, (342) = {311, 343, 373}, (343) = {312, 342, 344, 374}, (344) = {313, 343, 345, 375}, (345) = {314, 344, 346, 376}, (346) = {315, 345, 347, 377}, (347) = {316, 346, 348, 378}, (348) = {317, 347, 349, 379}, (349) = {318, 348, 350, 380}, (350) = {319, 349, 351, 381}, (351) = {320, 350, 352, 382}, (352) = {321, 351, 353, 383}, (353) = {322, 352, 354, 384}, (354) = {323, 353, 355, 385}, (355) = {324, 354, 356, 386}, (356) = {325, 355, 357, 387}, (357) = {326, 356, 358, 388}, (358) = {327, 357, 359, 389}, (359) = {328, 358, 360, 390}, (360) = {329, 359, 361, 391}, (361) = {330, 360, 362, 392}, (362) = {331, 361, 363, 393}, (363) = {332, 362, 364, 394}, (364) = {333, 363, 365, 395}, (365) = {334, 364, 366, 396}, (366) = {335, 365, 367, 397}, (367) = {336, 366, 368, 398}, (368) = {337, 367, 369, 399}, (369) = {338, 368, 370, 400}, (370) = {339, 369, 371, 401}, (371) = {340, 370, 372, 402}, (372) = {341, 371, 403}, (373) = {342, 374, 404}, (374) = {343, 373, 375, 405}, (375) = {344, 374, 376, 406}, (376) = {345, 375, 377, 407}, (377) = {346, 376, 378, 408}, (378) = {347, 377, 379, 409}, (379) = {348, 378, 380, 410}, (380) = {349, 379, 381, 411}, (381) = {350, 380, 382, 412}, (382) = {351, 381, 383, 413}, (383) = {352, 382, 384, 414}, (384) = {353, 383, 385, 415}, (385) = {354, 384, 386, 416}, (386) = {355, 385, 387, 417}, (387) = {356, 386, 388, 418}, (388) = {357, 387, 389, 419}, (389) = {358, 388, 390, 420}, (390) = {359, 389, 391, 421}, (391) = {360, 390, 392, 422}, (392) = {361, 391, 393, 423}, (393) = {362, 392, 394, 424}, (394) = {363, 393, 395, 425}, (395) = {364, 394, 396, 426}, (396) = {365, 395, 397, 427}, (397) = {366, 396, 398, 428}, (398) = {367, 397, 399, 429}, (399) = {368, 398, 400, 430}, (400) = {369, 399, 401, 431}, (401) = {370, 400, 402, 432}, (402) = {371, 401, 403, 433}, (403) = {372, 402, 434}, (404) = {373, 405, 435}, (405) = {374, 404, 406, 436}, (406) = {375, 405, 407, 437}, (407) = {376, 406, 408, 438}, (408) = {377, 407, 409, 439}, (409) = {378, 408, 410, 440}, (410) = {379, 409, 411, 441}, (411) = {380, 410, 412, 442}, (412) = {381, 411, 413, 443}, (413) = {382, 412, 414, 444}, (414) = {383, 413, 415, 445}, (415) = {384, 414, 416, 446}, (416) = {385, 415, 417, 447}, (417) = {386, 416, 418, 448}, (418) = {387, 417, 419, 449}, (419) = {388, 418, 420, 450}, (420) = {389, 419, 421, 451}, (421) = {390, 420, 422, 452}, (422) = {391, 421, 423, 453}, (423) = {392, 422, 424, 454}, (424) = {393, 423, 425, 455}, (425) = {394, 424, 426, 456}, (426) = {395, 425, 427, 457}, (427) = {396, 426, 428, 458}, (428) = {397, 427, 429, 459}, (429) = {398, 428, 430, 460}, (430) = {399, 429, 431, 461}, (431) = {400, 430, 432, 462}, (432) = {401, 431, 433, 463}, (433) = {402, 432, 434, 464}, (434) = {403, 433, 465}, (435) = {404, 436, 466}, (436) = {405, 435, 437, 467}, (437) = {406, 436, 438, 468}, (438) = {407, 437, 439, 469}, (439) = {408, 438, 440, 470}, (440) = {409, 439, 441, 471}, (441) = {410, 440, 442, 472}, (442) = {411, 441, 443, 473}, (443) = {412, 442, 444, 474}, (444) = {413, 443, 445, 475}, (445) = {414, 444, 446, 476}, (446) = {415, 445, 447, 477}, (447) = {416, 446, 448, 478}, (448) = {417, 447, 449, 479}, (449) = {418, 448, 450, 480}, (450) = {419, 449, 451, 481}, (451) = {420, 450, 452, 482}, (452) = {421, 451, 453, 483}, (453) = {422, 452, 454, 484}, (454) = {423, 453, 455, 485}, (455) = {424, 454, 456, 486}, (456) = {425, 455, 457, 487}, (457) = {426, 456, 458, 488}, (458) = {427, 457, 459, 489}, (459) = {428, 458, 460, 490}, (460) = {429, 459, 461, 491}, (461) = {430, 460, 462, 492}, (462) = {431, 461, 463, 493}, (463) = {432, 462, 464, 494}, (464) = {433, 463, 465, 495}, (465) = {434, 464, 496}, (466) = {435, 467, 497}, (467) = {436, 466, 468, 498}, (468) = {437, 467, 469, 499}, (469) = {438, 468, 470, 500}, (470) = {439, 469, 471, 501}, (471) = {440, 470, 472, 502}, (472) = {441, 471, 473, 503}, (473) = {442, 472, 474, 504}, (474) = {443, 473, 475, 505}, (475) = {444, 474, 476, 506}, (476) = {445, 475, 477, 507}, (477) = {446, 476, 478, 508}, (478) = {447, 477, 479, 509}, (479) = {448, 478, 480, 510}, (480) = {449, 479, 481, 511}, (481) = {450, 480, 482, 512}, (482) = {451, 481, 483, 513}, (483) = {452, 482, 484, 514}, (484) = {453, 483, 485, 515}, (485) = {454, 484, 486, 516}, (486) = {455, 485, 487, 517}, (487) = {456, 486, 488, 518}, (488) = {457, 487, 489, 519}, (489) = {458, 488, 490, 520}, (490) = {459, 489, 491, 521}, (491) = {460, 490, 492, 522}, (492) = {461, 491, 493, 523}, (493) = {462, 492, 494, 524}, (494) = {463, 493, 495, 525}, (495) = {464, 494, 496, 526}, (496) = {465, 495, 527}, (497) = {466, 498, 528}, (498) = {467, 497, 499, 529}, (499) = {468, 498, 500, 530}, (500) = {469, 499, 501, 531}, (501) = {470, 500, 502, 532}, (502) = {471, 501, 503, 533}, (503) = {472, 502, 504, 534}, (504) = {473, 503, 505, 535}, (505) = {474, 504, 506, 536}, (506) = {475, 505, 507, 537}, (507) = {476, 506, 508, 538}, (508) = {477, 507, 509, 539}, (509) = {478, 508, 510, 540}, (510) = {479, 509, 511, 541}, (511) = {480, 510, 512, 542}, (512) = {481, 511, 513, 543}, (513) = {482, 512, 514, 544}, (514) = {483, 513, 515, 545}, (515) = {484, 514, 516, 546}, (516) = {485, 515, 517, 547}, (517) = {486, 516, 518, 548}, (518) = {487, 517, 519, 549}, (519) = {488, 518, 520, 550}, (520) = {489, 519, 521, 551}, (521) = {490, 520, 522, 552}, (522) = {491, 521, 523, 553}, (523) = {492, 522, 524, 554}, (524) = {493, 523, 525, 555}, (525) = {494, 524, 526, 556}, (526) = {495, 525, 527, 557}, (527) = {496, 526, 558}, (528) = {497, 529, 559}, (529) = {498, 528, 530, 560}, (530) = {499, 529, 531, 561}, (531) = {500, 530, 532, 562}, (532) = {501, 531, 533, 563}, (533) = {502, 532, 534, 564}, (534) = {503, 533, 535, 565}, (535) = {504, 534, 536, 566}, (536) = {505, 535, 537, 567}, (537) = {506, 536, 538, 568}, (538) = {507, 537, 539, 569}, (539) = {508, 538, 540, 570}, (540) = {509, 539, 541, 571}, (541) = {510, 540, 542, 572}, (542) = {511, 541, 543, 573}, (543) = {512, 542, 544, 574}, (544) = {513, 543, 545, 575}, (545) = {514, 544, 546, 576}, (546) = {515, 545, 547, 577}, (547) = {516, 546, 548, 578}, (548) = {517, 547, 549, 579}, (549) = {518, 548, 550, 580}, (550) = {519, 549, 551, 581}, (551) = {520, 550, 552, 582}, (552) = {521, 551, 553, 583}, (553) = {522, 552, 554, 584}, (554) = {523, 553, 555, 585}, (555) = {524, 554, 556, 586}, (556) = {525, 555, 557, 587}, (557) = {526, 556, 558, 588}, (558) = {527, 557, 589}, (559) = {528, 560, 590}, (560) = {529, 559, 561, 591}, (561) = {530, 560, 562, 592}, (562) = {531, 561, 563, 593}, (563) = {532, 562, 564, 594}, (564) = {533, 563, 565, 595}, (565) = {534, 564, 566, 596}, (566) = {535, 565, 567, 597}, (567) = {536, 566, 568, 598}, (568) = {537, 567, 569, 599}, (569) = {538, 568, 570, 600}, (570) = {539, 569, 571, 601}, (571) = {540, 570, 572, 602}, (572) = {541, 571, 573, 603}, (573) = {542, 572, 574, 604}, (574) = {543, 573, 575, 605}, (575) = {544, 574, 576, 606}, (576) = {545, 575, 577, 607}, (577) = {546, 576, 578, 608}, (578) = {547, 577, 579, 609}, (579) = {548, 578, 580, 610}, (580) = {549, 579, 581, 611}, (581) = {550, 580, 582, 612}, (582) = {551, 581, 583, 613}, (583) = {552, 582, 584, 614}, (584) = {553, 583, 585, 615}, (585) = {554, 584, 586, 616}, (586) = {555, 585, 587, 617}, (587) = {556, 586, 588, 618}, (588) = {557, 587, 589, 619}, (589) = {558, 588, 620}, (590) = {559, 591, 621}, (591) = {560, 590, 592, 622}, (592) = {561, 591, 593, 623}, (593) = {562, 592, 594, 624}, (594) = {563, 593, 595, 625}, (595) = {564, 594, 596, 626}, (596) = {565, 595, 597, 627}, (597) = {566, 596, 598, 628}, (598) = {567, 597, 599, 629}, (599) = {568, 598, 600, 630}, (600) = {569, 599, 601, 631}, (601) = {570, 600, 602, 632}, (602) = {571, 601, 603, 633}, (603) = {572, 602, 604, 634}, (604) = {573, 603, 605, 635}, (605) = {574, 604, 606, 636}, (606) = {575, 605, 607, 637}, (607) = {576, 606, 608, 638}, (608) = {577, 607, 609, 639}, (609) = {578, 608, 610, 640}, (610) = {579, 609, 611, 641}, (611) = {580, 610, 612, 642}, (612) = {581, 611, 613, 643}, (613) = {582, 612, 614, 644}, (614) = {583, 613, 615, 645}, (615) = {584, 614, 616, 646}, (616) = {585, 615, 617, 647}, (617) = {586, 616, 618, 648}, (618) = {587, 617, 619, 649}, (619) = {588, 618, 620, 650}, (620) = {589, 619, 651}, (621) = {590, 622, 652}, (622) = {591, 621, 623, 653}, (623) = {592, 622, 624, 654}, (624) = {593, 623, 625, 655}, (625) = {594, 624, 626, 656}, (626) = {595, 625, 627, 657}, (627) = {596, 626, 628, 658}, (628) = {597, 627, 629, 659}, (629) = {598, 628, 630, 660}, (630) = {599, 629, 631, 661}, (631) = {600, 630, 632, 662}, (632) = {601, 631, 633, 663}, (633) = {602, 632, 634, 664}, (634) = {603, 633, 635, 665}, (635) = {604, 634, 636, 666}, (636) = {605, 635, 637, 667}, (637) = {606, 636, 638, 668}, (638) = {607, 637, 639, 669}, (639) = {608, 638, 640, 670}, (640) = {609, 639, 641, 671}, (641) = {610, 640, 642, 672}, (642) = {611, 641, 643, 673}, (643) = {612, 642, 644, 674}, (644) = {613, 643, 645, 675}, (645) = {614, 644, 646, 676}, (646) = {615, 645, 647, 677}, (647) = {616, 646, 648, 678}, (648) = {617, 647, 649, 679}, (649) = {618, 648, 650, 680}, (650) = {619, 649, 651, 681}, (651) = {620, 650, 682}, (652) = {621, 653, 683}, (653) = {622, 652, 654, 684}, (654) = {623, 653, 655, 685}, (655) = {624, 654, 656, 686}, (656) = {625, 655, 657, 687}, (657) = {626, 656, 658, 688}, (658) = {627, 657, 659, 689}, (659) = {628, 658, 660, 690}, (660) = {629, 659, 661, 691}, (661) = {630, 660, 662, 692}, (662) = {631, 661, 663, 693}, (663) = {632, 662, 664, 694}, (664) = {633, 663, 665, 695}, (665) = {634, 664, 666, 696}, (666) = {635, 665, 667, 697}, (667) = {636, 666, 668, 698}, (668) = {637, 667, 669, 699}, (669) = {638, 668, 670, 700}, (670) = {639, 669, 671, 701}, (671) = {640, 670, 672, 702}, (672) = {641, 671, 673, 703}, (673) = {642, 672, 674, 704}, (674) = {643, 673, 675, 705}, (675) = {644, 674, 676, 706}, (676) = {645, 675, 677, 707}, (677) = {646, 676, 678, 708}, (678) = {647, 677, 679, 709}, (679) = {648, 678, 680, 710}, (680) = {649, 679, 681, 711}, (681) = {650, 680, 682, 712}, (682) = {651, 681, 713}, (683) = {652, 684, 714}, (684) = {653, 683, 685, 715}, (685) = {654, 684, 686, 716}, (686) = {655, 685, 687, 717}, (687) = {656, 686, 688, 718}, (688) = {657, 687, 689, 719}, (689) = {658, 688, 690, 720}, (690) = {659, 689, 691, 721}, (691) = {660, 690, 692, 722}, (692) = {661, 691, 693, 723}, (693) = {662, 692, 694, 724}, (694) = {663, 693, 695, 725}, (695) = {664, 694, 696, 726}, (696) = {665, 695, 697, 727}, (697) = {666, 696, 698, 728}, (698) = {667, 697, 699, 729}, (699) = {668, 698, 700, 730}, (700) = {669, 699, 701, 731}, (701) = {670, 700, 702, 732}, (702) = {671, 701, 703, 733}, (703) = {672, 702, 704, 734}, (704) = {673, 703, 705, 735}, (705) = {674, 704, 706, 736}, (706) = {675, 705, 707, 737}, (707) = {676, 706, 708, 738}, (708) = {677, 707, 709, 739}, (709) = {678, 708, 710, 740}, (710) = {679, 709, 711, 741}, (711) = {680, 710, 712, 742}, (712) = {681, 711, 713, 743}, (713) = {682, 712, 744}, (714) = {683, 715, 745}, (715) = {684, 714, 716, 746}, (716) = {685, 715, 717, 747}, (717) = {686, 716, 718, 748}, (718) = {687, 717, 719, 749}, (719) = {688, 718, 720, 750}, (720) = {689, 719, 721, 751}, (721) = {690, 720, 722, 752}, (722) = {691, 721, 723, 753}, (723) = {692, 722, 724, 754}, (724) = {693, 723, 725, 755}, (725) = {694, 724, 726, 756}, (726) = {695, 725, 727, 757}, (727) = {696, 726, 728, 758}, (728) = {697, 727, 729, 759}, (729) = {698, 728, 730, 760}, (730) = {699, 729, 731, 761}, (731) = {700, 730, 732, 762}, (732) = {701, 731, 733, 763}, (733) = {702, 732, 734, 764}, (734) = {703, 733, 735, 765}, (735) = {704, 734, 736, 766}, (736) = {705, 735, 737, 767}, (737) = {706, 736, 738, 768}, (738) = {707, 737, 739, 769}, (739) = {708, 738, 740, 770}, (740) = {709, 739, 741, 771}, (741) = {710, 740, 742, 772}, (742) = {711, 741, 743, 773}, (743) = {712, 742, 744, 774}, (744) = {713, 743, 775}, (745) = {714, 746, 776}, (746) = {715, 745, 747, 777}, (747) = {716, 746, 748, 778}, (748) = {717, 747, 749, 779}, (749) = {718, 748, 750, 780}, (750) = {719, 749, 751, 781}, (751) = {720, 750, 752, 782}, (752) = {721, 751, 753, 783}, (753) = {722, 752, 754, 784}, (754) = {723, 753, 755, 785}, (755) = {724, 754, 756, 786}, (756) = {725, 755, 757, 787}, (757) = {726, 756, 758, 788}, (758) = {727, 757, 759, 789}, (759) = {728, 758, 760, 790}, (760) = {729, 759, 761, 791}, (761) = {730, 760, 762, 792}, (762) = {731, 761, 763, 793}, (763) = {732, 762, 764, 794}, (764) = {733, 763, 765, 795}, (765) = {734, 764, 766, 796}, (766) = {735, 765, 767, 797}, (767) = {736, 766, 768, 798}, (768) = {737, 767, 769, 799}, (769) = {738, 768, 770, 800}, (770) = {739, 769, 771, 801}, (771) = {740, 770, 772, 802}, (772) = {741, 771, 773, 803}, (773) = {742, 772, 774, 804}, (774) = {743, 773, 775, 805}, (775) = {744, 774, 806}, (776) = {745, 777, 807}, (777) = {746, 776, 778, 808}, (778) = {747, 777, 779, 809}, (779) = {748, 778, 780, 810}, (780) = {749, 779, 781, 811}, (781) = {750, 780, 782, 812}, (782) = {751, 781, 783, 813}, (783) = {752, 782, 784, 814}, (784) = {753, 783, 785, 815}, (785) = {754, 784, 786, 816}, (786) = {755, 785, 787, 817}, (787) = {756, 786, 788, 818}, (788) = {757, 787, 789, 819}, (789) = {758, 788, 790, 820}, (790) = {759, 789, 791, 821}, (791) = {760, 790, 792, 822}, (792) = {761, 791, 793, 823}, (793) = {762, 792, 794, 824}, (794) = {763, 793, 795, 825}, (795) = {764, 794, 796, 826}, (796) = {765, 795, 797, 827}, (797) = {766, 796, 798, 828}, (798) = {767, 797, 799, 829}, (799) = {768, 798, 800, 830}, (800) = {769, 799, 801, 831}, (801) = {770, 800, 802, 832}, (802) = {771, 801, 803, 833}, (803) = {772, 802, 804, 834}, (804) = {773, 803, 805, 835}, (805) = {774, 804, 806, 836}, (806) = {775, 805, 837}, (807) = {776, 808, 838}, (808) = {777, 807, 809, 839}, (809) = {778, 808, 810, 840}, (810) = {779, 809, 811, 841}, (811) = {780, 810, 812, 842}, (812) = {781, 811, 813, 843}, (813) = {782, 812, 814, 844}, (814) = {783, 813, 815, 845}, (815) = {784, 814, 816, 846}, (816) = {785, 815, 817, 847}, (817) = {786, 816, 818, 848}, (818) = {787, 817, 819, 849}, (819) = {788, 818, 820, 850}, (820) = {789, 819, 821, 851}, (821) = {790, 820, 822, 852}, (822) = {791, 821, 823, 853}, (823) = {792, 822, 824, 854}, (824) = {793, 823, 825, 855}, (825) = {794, 824, 826, 856}, (826) = {795, 825, 827, 857}, (827) = {796, 826, 828, 858}, (828) = {797, 827, 829, 859}, (829) = {798, 828, 830, 860}, (830) = {799, 829, 831, 861}, (831) = {800, 830, 832, 862}, (832) = {801, 831, 833, 863}, (833) = {802, 832, 834, 864}, (834) = {803, 833, 835, 865}, (835) = {804, 834, 836, 866}, (836) = {805, 835, 837, 867}, (837) = {806, 836, 868}, (838) = {807, 839, 869}, (839) = {808, 838, 840, 870}, (840) = {809, 839, 841, 871}, (841) = {810, 840, 842, 872}, (842) = {811, 841, 843, 873}, (843) = {812, 842, 844, 874}, (844) = {813, 843, 845, 875}, (845) = {814, 844, 846, 876}, (846) = {815, 845, 847, 877}, (847) = {816, 846, 848, 878}, (848) = {817, 847, 849, 879}, (849) = {818, 848, 850, 880}, (850) = {819, 849, 851, 881}, (851) = {820, 850, 852, 882}, (852) = {821, 851, 853, 883}, (853) = {822, 852, 854, 884}, (854) = {823, 853, 855, 885}, (855) = {824, 854, 856, 886}, (856) = {825, 855, 857, 887}, (857) = {826, 856, 858, 888}, (858) = {827, 857, 859, 889}, (859) = {828, 858, 860, 890}, (860) = {829, 859, 861, 891}, (861) = {830, 860, 862, 892}, (862) = {831, 861, 863, 893}, (863) = {832, 862, 864, 894}, (864) = {833, 863, 865, 895}, (865) = {834, 864, 866, 896}, (866) = {835, 865, 867, 897}, (867) = {836, 866, 868, 898}, (868) = {837, 867, 899}, (869) = {838, 870, 900}, (870) = {839, 869, 871, 901}, (871) = {840, 870, 872, 902}, (872) = {841, 871, 873, 903}, (873) = {842, 872, 874, 904}, (874) = {843, 873, 875, 905}, (875) = {844, 874, 876, 906}, (876) = {845, 875, 877, 907}, (877) = {846, 876, 878, 908}, (878) = {847, 877, 879, 909}, (879) = {848, 878, 880, 910}, (880) = {849, 879, 881, 911}, (881) = {850, 880, 882, 912}, (882) = {851, 881, 883, 913}, (883) = {852, 882, 884, 914}, (884) = {853, 883, 885, 915}, (885) = {854, 884, 886, 916}, (886) = {855, 885, 887, 917}, (887) = {856, 886, 888, 918}, (888) = {857, 887, 889, 919}, (889) = {858, 888, 890, 920}, (890) = {859, 889, 891, 921}, (891) = {860, 890, 892, 922}, (892) = {861, 891, 893, 923}, (893) = {862, 892, 894, 924}, (894) = {863, 893, 895, 925}, (895) = {864, 894, 896, 926}, (896) = {865, 895, 897, 927}, (897) = {866, 896, 898, 928}, (898) = {867, 897, 899, 929}, (899) = {868, 898, 930}, (900) = {869, 901, 931}, (901) = {870, 900, 902, 932}, (902) = {871, 901, 903, 933}, (903) = {872, 902, 904, 934}, (904) = {873, 903, 905, 935}, (905) = {874, 904, 906, 936}, (906) = {875, 905, 907, 937}, (907) = {876, 906, 908, 938}, (908) = {877, 907, 909, 939}, (909) = {878, 908, 910, 940}, (910) = {879, 909, 911, 941}, (911) = {880, 910, 912, 942}, (912) = {881, 911, 913, 943}, (913) = {882, 912, 914, 944}, (914) = {883, 913, 915, 945}, (915) = {884, 914, 916, 946}, (916) = {885, 915, 917, 947}, (917) = {886, 916, 918, 948}, (918) = {887, 917, 919, 949}, (919) = {888, 918, 920, 950}, (920) = {889, 919, 921, 951}, (921) = {890, 920, 922, 952}, (922) = {891, 921, 923, 953}, (923) = {892, 922, 924, 954}, (924) = {893, 923, 925, 955}, (925) = {894, 924, 926, 956}, (926) = {895, 925, 927, 957}, (927) = {896, 926, 928, 958}, (928) = {897, 927, 929, 959}, (929) = {898, 928, 930, 960}, (930) = {899, 929, 961}, (931) = {900, 932}, (932) = {901, 931, 933}, (933) = {902, 932, 934}, (934) = {903, 933, 935}, (935) = {904, 934, 936}, (936) = {905, 935, 937}, (937) = {906, 936, 938}, (938) = {907, 937, 939}, (939) = {908, 938, 940}, (940) = {909, 939, 941}, (941) = {910, 940, 942}, (942) = {911, 941, 943}, (943) = {912, 942, 944}, (944) = {913, 943, 945}, (945) = {914, 944, 946}, (946) = {915, 945, 947}, (947) = {916, 946, 948}, (948) = {917, 947, 949}, (949) = {918, 948, 950}, (950) = {919, 949, 951}, (951) = {920, 950, 952}, (952) = {921, 951, 953}, (953) = {922, 952, 954}, (954) = {923, 953, 955}, (955) = {924, 954, 956}, (956) = {925, 955, 957}, (957) = {926, 956, 958}, (958) = {927, 957, 959}, (959) = {928, 958, 960}, (960) = {929, 959, 961}, (961) = {930, 960}}), `GRAPHLN/table/1`, 0)

     

    GRAPHLN(undirected, unweighted, ["2,2", "2,3", "2,4", "2,5", "2,6", "2,7", "2,8", "2,9", "2,10", "2,11", "2,12", "2,13", "2,14", "2,15", "2,16", "2,18", "2,19", "2,20", "2,21", "2,22", "2,23", "2,24", "2,25", "2,26", "2,27", "2,28", "2,29", "2,30", "2,31", "3,2", "3,16", "3,18", "3,26", "4,2", "4,3", "4,4", "4,5", "4,6", "4,7", "4,8", "4,9", "4,10", "4,11", "4,12", "4,13", "4,14", "4,16", "4,18", "4,19", "4,20", "4,21", "4,22", "4,23", "4,24", "4,26", "4,27", "4,28", "4,29", "4,30", "5,2", "5,14", "5,16", "5,24", "5,30", "6,2", "6,3", "6,4", "6,5", "6,6", "6,7", "6,8", "6,9", "6,10", "6,11", "6,12", "6,14", "6,16", "6,17", "6,18", "6,19", "6,20", "6,21", "6,22", "6,23", "6,24", "6,26", "6,27", "6,28", "6,30", "7,12", "7,14", "7,24", "7,26", "7,28", "7,30", "8,2", "8,3", "8,4", "8,5", "8,6", "8,7", "8,8", "8,9", "8,10", "8,11", "8,12", "8,14", "8,15", "8,16", "8,17", "8,18", "8,19", "8,20", "8,21", "8,22", "8,24", "8,26", "8,28", "8,30", "9,2", "9,22", "9,24", "9,26", "9,28", "9,30", "10,2", "10,4", "10,5", "10,6", "10,7", "10,8", "10,9", "10,10", "10,11", "10,12", "10,13", "10,14", "10,15", "10,16", "10,17", "10,18", "10,20", "10,22", "10,24", "10,26", "10,28", "10,30", "11,2", "11,4", "11,18", "11,20", "11,22", "11,24", "11,26", "11,28", "11,30", "12,2", "12,4", "12,6", "12,7", "12,8", "12,9", "12,10", "12,11", "12,12", "12,13", "12,14", "12,15", "12,16", "12,17", "12,18", "12,20", "12,22", "12,24", "12,26", "12,28", "12,29", "12,30", "13,2", "13,4", "13,6", "13,18", "13,20", "13,22", "13,24", "14,2", "14,4", "14,6", "14,8", "14,9", "14,10", "14,12", "14,13", "14,14", "14,15", "14,16", "14,18", "14,20", "14,22", "14,24", "14,25", "14,26", "14,27", "14,28", "14,29", "14,30", "15,2", "15,4", "15,6", "15,8", "15,10", "15,12", "15,14", "15,16", "15,18", "15,20", "15,22", "15,30", "16,2", "16,3", "16,4", "16,6", "16,8", "16,10", "16,12", "16,14", "16,16", "16,18", "16,20", "16,22", "16,23", "16,24", "16,26", "16,27", "16,28", "16,30", "17,6", "17,8", "17,10", "17,12", "17,14", "17,16", "17,18", "17,20", "17,24", "17,26", "17,28", "17,30", "18,2", "18,3", "18,4", "18,5", "18,6", "18,8", "18,10", "18,12", "18,14", "18,16", "18,18", "18,20", "18,21", "18,22", "18,24", "18,26", "18,28", "18,30", "19,2", "19,8", "19,10", "19,12", "19,14", "19,16", "19,18", "19,20", "19,22", "19,24", "19,26", "19,28", "19,30", "20,2", "20,3", "20,4", "20,5", "20,6", "20,7", "20,8", "20,10", "20,12", "20,14", "20,16", "20,18", "20,20", "20,22", "20,24", "20,26", "20,28", "20,30", "21,10", "21,12", "21,14", "21,16", "21,18", "21,20", "21,22", "21,24", "21,26", "21,28", "21,30", "22,2", "22,3", "22,4", "22,5", "22,6", "22,7", "22,8", "22,9", "22,10", "22,12", "22,14", "22,16", "22,18", "22,20", "22,22", "22,24", "22,26", "22,28", "22,29", "22,30", "23,2", "23,12", "23,14", "23,16", "23,18", "23,20", "23,22", "23,24", "23,26", "24,2", "24,4", "24,5", "24,6", "24,7", "24,8", "24,9", "24,10", "24,11", "24,12", "24,14", "24,16", "24,18", "24,20", "24,22", "24,24", "24,26", "24,27", "24,28", "24,29", "24,30", "25,2", "25,14", "25,16", "25,18", "25,20", "25,22", "25,24", "26,2", "26,4", "26,5", "26,6", "26,7", "26,8", "26,9", "26,10", "26,11", "26,12", "26,14", "26,16", "26,18", "26,20", "26,22", "26,24", "26,25", "26,26", "26,27", "26,28", "26,29", "26,30", "27,2", "27,4", "27,12", "27,14", "27,16", "27,18", "27,20", "27,22", "27,30", "28,2", "28,4", "28,6", "28,7", "28,8", "28,9", "28,10", "28,11", "28,12", "28,14", "28,16", "28,18", "28,20", "28,22", "28,23", "28,24", "28,26", "28,27", "28,28", "28,30", "29,4", "29,6", "29,14", "29,16", "29,18", "29,20", "29,24", "29,26", "29,28", "29,30", "30,1", "30,2", "30,3", "30,4", "30,6", "30,7", "30,8", "30,9", "30,10", "30,11", "30,12", "30,13", "30,14", "30,16", "30,17", "30,18", "30,20", "30,21", "30,22", "30,24", "30,25", "30,26", "30,28", "30,29", "30,30"], Array(1..451, {(1) = {2, 30}, (2) = {1, 3}, (3) = {2, 4}, (4) = {3, 5}, (5) = {4, 6}, (6) = {5, 7}, (7) = {6, 8}, (8) = {7, 9}, (9) = {8, 10}, (10) = {9, 11}, (11) = {10, 12}, (12) = {11, 13}, (13) = {12, 14}, (14) = {13, 15}, (15) = {14, 31}, (16) = {17, 32}, (17) = {16, 18}, (18) = {17, 19}, (19) = {18, 20}, (20) = {19, 21}, (21) = {20, 22}, (22) = {21, 23}, (23) = {22, 24}, (24) = {23, 25, 33}, (25) = {24, 26}, (26) = {25, 27}, (27) = {26, 28}, (28) = {27, 29}, (29) = {28}, (30) = {1, 34}, (31) = {15, 47}, (32) = {16, 48}, (33) = {24, 55}, (34) = {30, 35, 60}, (35) = {34, 36}, (36) = {35, 37}, (37) = {36, 38}, (38) = {37, 39}, (39) = {38, 40}, (40) = {39, 41}, (41) = {40, 42}, (42) = {41, 43}, (43) = {42, 44}, (44) = {43, 45}, (45) = {44, 46}, (46) = {45, 61}, (47) = {31, 62}, (48) = {32, 49}, (49) = {48, 50}, (50) = {49, 51}, (51) = {50, 52}, (52) = {51, 53}, (53) = {52, 54}, (54) = {53, 63}, (55) = {33, 56}, (56) = {55, 57}, (57) = {56, 58}, (58) = {57, 59}, (59) = {58, 64}, (60) = {34, 65}, (61) = {46, 76}, (62) = {47, 77}, (63) = {54, 85}, (64) = {59, 89}, (65) = {60, 66}, (66) = {65, 67}, (67) = {66, 68}, (68) = {67, 69}, (69) = {68, 70}, (70) = {69, 71}, (71) = {70, 72}, (72) = {71, 73}, (73) = {72, 74}, (74) = {73, 75}, (75) = {74, 90}, (76) = {61, 91}, (77) = {62, 78}, (78) = {77, 79}, (79) = {78, 80}, (80) = {79, 81}, (81) = {80, 82}, (82) = {81, 83}, (83) = {82, 84}, (84) = {83, 85}, (85) = {63, 84, 92}, (86) = {87, 93}, (87) = {86, 88}, (88) = {87, 94}, (89) = {64, 95}, (90) = {75, 106}, (91) = {76, 107}, (92) = {85, 116}, (93) = {86, 117}, (94) = {88, 118}, (95) = {89, 119}, (96) = {97, 120}, (97) = {96, 98}, (98) = {97, 99}, (99) = {98, 100}, (100) = {99, 101}, (101) = {100, 102}, (102) = {101, 103}, (103) = {102, 104}, (104) = {103, 105}, (105) = {104, 106}, (106) = {90, 105}, (107) = {91, 108}, (108) = {107, 109}, (109) = {108, 110}, (110) = {109, 111}, (111) = {110, 112}, (112) = {111, 113}, (113) = {112, 114}, (114) = {113, 115}, (115) = {114, 121}, (116) = {92, 122}, (117) = {93, 123}, (118) = {94, 124}, (119) = {95, 125}, (120) = {96, 126}, (121) = {115, 143}, (122) = {116, 144}, (123) = {117, 145}, (124) = {118, 146}, (125) = {119, 147}, (126) = {120, 148}, (127) = {128, 149}, (128) = {127, 129}, (129) = {128, 130}, (130) = {129, 131}, (131) = {130, 132}, (132) = {131, 133}, (133) = {132, 134}, (134) = {133, 135}, (135) = {134, 136}, (136) = {135, 137}, (137) = {136, 138}, (138) = {137, 139}, (139) = {138, 140}, (140) = {139, 141}, (141) = {140, 150}, (142) = {151}, (143) = {121, 152}, (144) = {122, 153}, (145) = {123, 154}, (146) = {124, 155}, (147) = {125, 156}, (148) = {126, 157}, (149) = {127, 158}, (150) = {141, 171}, (151) = {142, 172}, (152) = {143, 173}, (153) = {144, 174}, (154) = {145, 175}, (155) = {146, 176}, (156) = {147, 178}, (157) = {148, 179}, (158) = {149, 180}, (159) = {160, 181}, (160) = {159, 161}, (161) = {160, 162}, (162) = {161, 163}, (163) = {162, 164}, (164) = {163, 165}, (165) = {164, 166}, (166) = {165, 167}, (167) = {166, 168}, (168) = {167, 169}, (169) = {168, 170}, (170) = {169, 171}, (171) = {150, 170, 182}, (172) = {151, 183}, (173) = {152, 184}, (174) = {153, 185}, (175) = {154}, (176) = {155, 177}, (177) = {176, 178}, (178) = {156, 177}, (179) = {157, 186}, (180) = {158, 187}, (181) = {159, 188}, (182) = {171, 197}, (183) = {172, 198}, (184) = {173, 199}, (185) = {174, 200}, (186) = {179, 207}, (187) = {180, 208}, (188) = {181, 209}, (189) = {190, 210}, (190) = {189, 191}, (191) = {190, 211}, (192) = {193, 212}, (193) = {192, 194}, (194) = {193, 195, 213}, (195) = {194, 196}, (196) = {195, 214}, (197) = {182, 215}, (198) = {183, 216}, (199) = {184, 217}, (200) = {185, 201}, (201) = {200, 202}, (202) = {201, 203}, (203) = {202, 204}, (204) = {203, 205}, (205) = {204, 206}, (206) = {205, 218}, (207) = {186, 219}, (208) = {187, 221}, (209) = {188, 222}, (210) = {189, 223}, (211) = {191, 224}, (212) = {192, 225}, (213) = {194, 226}, (214) = {196, 227}, (215) = {197, 228}, (216) = {198, 229}, (217) = {199, 230}, (218) = {206, 236}, (219) = {207, 220}, (220) = {219, 221}, (221) = {208, 220}, (222) = {209, 237}, (223) = {210, 238}, (224) = {211, 239}, (225) = {212, 240}, (226) = {213, 241}, (227) = {214, 242}, (228) = {215, 243}, (229) = {216, 244}, (230) = {217, 231}, (231) = {230, 232}, (232) = {231, 245}, (233) = {234, 246}, (234) = {233, 235}, (235) = {234, 247}, (236) = {218, 248}, (237) = {222, 253}, (238) = {223, 254}, (239) = {224, 255}, (240) = {225, 256}, (241) = {226, 257}, (242) = {227, 258}, (243) = {228, 259}, (244) = {229, 260}, (245) = {232, 263}, (246) = {233, 264}, (247) = {235, 265}, (248) = {236, 266}, (249) = {250, 267}, (250) = {249, 251}, (251) = {250, 252}, (252) = {251, 253}, (253) = {237, 252}, (254) = {238, 268}, (255) = {239, 269}, (256) = {240, 270}, (257) = {241, 271}, (258) = {242, 272}, (259) = {243, 273}, (260) = {244, 261, 274}, (261) = {260, 262}, (262) = {261, 275}, (263) = {245, 276}, (264) = {246, 277}, (265) = {247, 278}, (266) = {248, 279}, (267) = {249, 280}, (268) = {254, 286}, (269) = {255, 287}, (270) = {256, 288}, (271) = {257, 289}, (272) = {258, 290}, (273) = {259, 291}, (274) = {260, 292}, (275) = {262, 293}, (276) = {263, 294}, (277) = {264, 295}, (278) = {265, 296}, (279) = {266, 297}, (280) = {267, 281}, (281) = {280, 282}, (282) = {281, 283}, (283) = {282, 284}, (284) = {283, 285}, (285) = {284, 286}, (286) = {268, 285}, (287) = {269, 298}, (288) = {270, 299}, (289) = {271, 300}, (290) = {272, 301}, (291) = {273, 302}, (292) = {274, 303}, (293) = {275, 304}, (294) = {276, 305}, (295) = {277, 306}, (296) = {278, 307}, (297) = {279, 308}, (298) = {287, 317}, (299) = {288, 318}, (300) = {289, 319}, (301) = {290, 320}, (302) = {291, 321}, (303) = {292, 322}, (304) = {293, 323}, (305) = {294, 324}, (306) = {295, 325}, (307) = {296, 326}, (308) = {297, 328}, (309) = {310, 329}, (310) = {309, 311}, (311) = {310, 312}, (312) = {311, 313}, (313) = {312, 314}, (314) = {313, 315}, (315) = {314, 316}, (316) = {315, 317}, (317) = {298, 316}, (318) = {299, 330}, (319) = {300, 331}, (320) = {301, 332}, (321) = {302, 333}, (322) = {303, 334}, (323) = {304, 335}, (324) = {305, 336}, (325) = {306, 337}, (326) = {307, 327}, (327) = {326, 328}, (328) = {308, 327}, (329) = {309, 338}, (330) = {318, 347}, (331) = {319, 348}, (332) = {320, 349}, (333) = {321, 350}, (334) = {322, 351}, (335) = {323, 352}, (336) = {324, 353}, (337) = {325, 354}, (338) = {329, 359}, (339) = {340}, (340) = {339, 341}, (341) = {340, 342}, (342) = {341, 343}, (343) = {342, 344}, (344) = {343, 345}, (345) = {344, 346}, (346) = {345, 347}, (347) = {330, 346}, (348) = {331, 360}, (349) = {332, 361}, (350) = {333, 362}, (351) = {334, 363}, (352) = {335, 364}, (353) = {336, 365}, (354) = {337, 355}, (355) = {354, 356}, (356) = {355, 357}, (357) = {356, 358}, (358) = {357}, (359) = {338, 366}, (360) = {348, 376}, (361) = {349, 377}, (362) = {350, 378}, (363) = {351, 379}, (364) = {352, 380}, (365) = {353, 381}, (366) = {359, 388}, (367) = {368, 389}, (368) = {367, 369}, (369) = {368, 370}, (370) = {369, 371}, (371) = {370, 372}, (372) = {371, 373}, (373) = {372, 374}, (374) = {373, 375}, (375) = {374, 390}, (376) = {360, 391}, (377) = {361, 392}, (378) = {362, 393}, (379) = {363, 394}, (380) = {364, 395}, (381) = {365, 382}, (382) = {381, 383}, (383) = {382, 384}, (384) = {383, 385}, (385) = {384, 386}, (386) = {385, 387}, (387) = {386, 396}, (388) = {366, 397}, (389) = {367, 398}, (390) = {375, 405}, (391) = {376, 406}, (392) = {377, 407}, (393) = {378, 408}, (394) = {379, 409}, (395) = {380, 410}, (396) = {387, 416}, (397) = {388}, (398) = {389, 417}, (399) = {400, 418}, (400) = {399, 401}, (401) = {400, 402}, (402) = {401, 403}, (403) = {402, 404}, (404) = {403, 405}, (405) = {390, 404}, (406) = {391, 419}, (407) = {392, 420}, (408) = {393, 421}, (409) = {394, 422}, (410) = {395, 411}, (411) = {410, 412}, (412) = {411, 423}, (413) = {414, 424}, (414) = {413, 415}, (415) = {414, 425}, (416) = {396, 426}, (417) = {398, 430}, (418) = {399, 431}, (419) = {406, 439}, (420) = {407, 440}, (421) = {408, 442}, (422) = {409, 443}, (423) = {412, 446}, (424) = {413, 448}, (425) = {415, 449}, (426) = {416, 451}, (427) = {428}, (428) = {427, 429}, (429) = {428, 430}, (430) = {417, 429}, (431) = {418, 432}, (432) = {431, 433}, (433) = {432, 434}, (434) = {433, 435}, (435) = {434, 436}, (436) = {435, 437}, (437) = {436, 438}, (438) = {437, 439}, (439) = {419, 438}, (440) = {420, 441}, (441) = {440, 442}, (442) = {421, 441}, (443) = {422, 444}, (444) = {443, 445}, (445) = {444}, (446) = {423, 447}, (447) = {446, 448}, (448) = {424, 447}, (449) = {425, 450}, (450) = {449, 451}, (451) = {426, 450}}), `GRAPHLN/table/2`, 0)

    (2)

    G := Graph(Edges(G));

    GRAPHLN(undirected, unweighted, ["10,10", "10,11", "10,12", "10,13", "10,14", "10,15", "10,16", "10,17", "10,18", "10,2", "10,20", "10,22", "10,24", "10,26", "10,28", "10,30", "10,4", "10,5", "10,6", "10,7", "10,8", "10,9", "11,18", "11,2", "11,20", "11,22", "11,24", "11,26", "11,28", "11,30", "11,4", "12,10", "12,11", "12,12", "12,13", "12,14", "12,15", "12,16", "12,17", "12,18", "12,2", "12,20", "12,22", "12,24", "12,26", "12,28", "12,29", "12,30", "12,4", "12,6", "12,7", "12,8", "12,9", "13,18", "13,2", "13,20", "13,22", "13,24", "13,4", "13,6", "14,10", "14,12", "14,13", "14,14", "14,15", "14,16", "14,18", "14,2", "14,20", "14,22", "14,24", "14,25", "14,26", "14,27", "14,28", "14,29", "14,30", "14,4", "14,6", "14,8", "14,9", "15,10", "15,12", "15,14", "15,16", "15,18", "15,2", "15,20", "15,22", "15,30", "15,4", "15,6", "15,8", "16,10", "16,12", "16,14", "16,16", "16,18", "16,2", "16,20", "16,22", "16,23", "16,24", "16,26", "16,27", "16,28", "16,3", "16,30", "16,4", "16,6", "16,8", "17,10", "17,12", "17,14", "17,16", "17,18", "17,20", "17,24", "17,26", "17,28", "17,30", "17,6", "17,8", "18,10", "18,12", "18,14", "18,16", "18,18", "18,2", "18,20", "18,21", "18,22", "18,24", "18,26", "18,28", "18,3", "18,30", "18,4", "18,5", "18,6", "18,8", "19,10", "19,12", "19,14", "19,16", "19,18", "19,2", "19,20", "19,22", "19,24", "19,26", "19,28", "19,30", "19,8", "2,10", "2,11", "2,12", "2,13", "2,14", "2,15", "2,16", "2,18", "2,19", "2,2", "2,20", "2,21", "2,22", "2,23", "2,24", "2,25", "2,26", "2,27", "2,28", "2,29", "2,3", "2,30", "2,31", "2,4", "2,5", "2,6", "2,7", "2,8", "2,9", "20,10", "20,12", "20,14", "20,16", "20,18", "20,2", "20,20", "20,22", "20,24", "20,26", "20,28", "20,3", "20,30", "20,4", "20,5", "20,6", "20,7", "20,8", "21,10", "21,12", "21,14", "21,16", "21,18", "21,20", "21,22", "21,24", "21,26", "21,28", "21,30", "22,10", "22,12", "22,14", "22,16", "22,18", "22,2", "22,20", "22,22", "22,24", "22,26", "22,28", "22,29", "22,3", "22,30", "22,4", "22,5", "22,6", "22,7", "22,8", "22,9", "23,12", "23,14", "23,16", "23,18", "23,2", "23,20", "23,22", "23,24", "23,26", "24,10", "24,11", "24,12", "24,14", "24,16", "24,18", "24,2", "24,20", "24,22", "24,24", "24,26", "24,27", "24,28", "24,29", "24,30", "24,4", "24,5", "24,6", "24,7", "24,8", "24,9", "25,14", "25,16", "25,18", "25,2", "25,20", "25,22", "25,24", "26,10", "26,11", "26,12", "26,14", "26,16", "26,18", "26,2", "26,20", "26,22", "26,24", "26,25", "26,26", "26,27", "26,28", "26,29", "26,30", "26,4", "26,5", "26,6", "26,7", "26,8", "26,9", "27,12", "27,14", "27,16", "27,18", "27,2", "27,20", "27,22", "27,30", "27,4", "28,10", "28,11", "28,12", "28,14", "28,16", "28,18", "28,2", "28,20", "28,22", "28,23", "28,24", "28,26", "28,27", "28,28", "28,30", "28,4", "28,6", "28,7", "28,8", "28,9", "29,14", "29,16", "29,18", "29,20", "29,24", "29,26", "29,28", "29,30", "29,4", "29,6", "3,16", "3,18", "3,2", "3,26", "30,1", "30,10", "30,11", "30,12", "30,13", "30,14", "30,16", "30,17", "30,18", "30,2", "30,20", "30,21", "30,22", "30,24", "30,25", "30,26", "30,28", "30,29", "30,3", "30,30", "30,4", "30,6", "30,7", "30,8", "30,9", "4,10", "4,11", "4,12", "4,13", "4,14", "4,16", "4,18", "4,19", "4,2", "4,20", "4,21", "4,22", "4,23", "4,24", "4,26", "4,27", "4,28", "4,29", "4,3", "4,30", "4,4", "4,5", "4,6", "4,7", "4,8", "4,9", "5,14", "5,16", "5,2", "5,24", "5,30", "6,10", "6,11", "6,12", "6,14", "6,16", "6,17", "6,18", "6,19", "6,2", "6,20", "6,21", "6,22", "6,23", "6,24", "6,26", "6,27", "6,28", "6,3", "6,30", "6,4", "6,5", "6,6", "6,7", "6,8", "6,9", "7,12", "7,14", "7,24", "7,26", "7,28", "7,30", "8,10", "8,11", "8,12", "8,14", "8,15", "8,16", "8,17", "8,18", "8,19", "8,2", "8,20", "8,21", "8,22", "8,24", "8,26", "8,28", "8,3", "8,30", "8,4", "8,5", "8,6", "8,7", "8,8", "8,9", "9,2", "9,22", "9,24", "9,26", "9,28", "9,30"], Array(1..451, {(1) = {2, 22}, (2) = {1, 3}, (3) = {2, 4}, (4) = {3, 5}, (5) = {4, 6}, (6) = {5, 7}, (7) = {6, 8}, (8) = {7, 9}, (9) = {8, 23}, (10) = {24, 446}, (11) = {25}, (12) = {26, 447}, (13) = {27, 448}, (14) = {28, 449}, (15) = {29, 450}, (16) = {30, 451}, (17) = {18, 31}, (18) = {17, 19}, (19) = {18, 20}, (20) = {19, 21}, (21) = {20, 22}, (22) = {1, 21}, (23) = {9, 40}, (24) = {10, 41}, (25) = {11, 42}, (26) = {12, 43}, (27) = {13, 44}, (28) = {14, 45}, (29) = {15, 46}, (30) = {16, 48}, (31) = {17, 49}, (32) = {33, 53}, (33) = {32, 34}, (34) = {33, 35}, (35) = {34, 36}, (36) = {35, 37}, (37) = {36, 38}, (38) = {37, 39}, (39) = {38, 40}, (40) = {23, 39, 54}, (41) = {24, 55}, (42) = {25, 56}, (43) = {26, 57}, (44) = {27, 58}, (45) = {28}, (46) = {29, 47}, (47) = {46, 48}, (48) = {30, 47}, (49) = {31, 59}, (50) = {51, 60}, (51) = {50, 52}, (52) = {51, 53}, (53) = {32, 52}, (54) = {40, 67}, (55) = {41, 68}, (56) = {42, 69}, (57) = {43, 70}, (58) = {44, 71}, (59) = {49, 78}, (60) = {50, 79}, (61) = {81, 82}, (62) = {63, 83}, (63) = {62, 64}, (64) = {63, 65, 84}, (65) = {64, 66}, (66) = {65, 85}, (67) = {54, 86}, (68) = {55, 87}, (69) = {56, 88}, (70) = {57, 89}, (71) = {58, 72}, (72) = {71, 73}, (73) = {72, 74}, (74) = {73, 75}, (75) = {74, 76}, (76) = {75, 77}, (77) = {76, 90}, (78) = {59, 91}, (79) = {60, 92}, (80) = {81, 93}, (81) = {61, 80}, (82) = {61, 94}, (83) = {62, 95}, (84) = {64, 96}, (85) = {66, 97}, (86) = {67, 98}, (87) = {68, 99}, (88) = {69, 100}, (89) = {70, 101}, (90) = {77, 108}, (91) = {78, 109}, (92) = {79, 110}, (93) = {80, 111}, (94) = {82, 112}, (95) = {83, 113}, (96) = {84, 114}, (97) = {85, 115}, (98) = {86, 116}, (99) = {87, 107}, (100) = {88, 117}, (101) = {89, 102}, (102) = {101, 103}, (103) = {102, 118}, (104) = {105, 119}, (105) = {104, 106}, (106) = {105, 120}, (107) = {99, 109}, (108) = {90, 121}, (109) = {91, 107}, (110) = {92, 122}, (111) = {93, 123}, (112) = {94, 124}, (113) = {95, 125}, (114) = {96, 126}, (115) = {97, 127}, (116) = {98, 128}, (117) = {100, 130}, (118) = {103, 133}, (119) = {104, 134}, (120) = {106, 135}, (121) = {108, 137}, (122) = {110, 140}, (123) = {111, 141}, (124) = {112, 142}, (125) = {113, 143}, (126) = {114, 144}, (127) = {115, 145}, (128) = {116, 146}, (129) = {136, 147}, (130) = {117, 131, 148}, (131) = {130, 132}, (132) = {131, 149}, (133) = {118, 150}, (134) = {119, 151}, (135) = {120, 152}, (136) = {129, 138}, (137) = {121, 153}, (138) = {136, 139}, (139) = {138, 140}, (140) = {122, 139}, (141) = {123, 154}, (142) = {124, 184}, (143) = {125, 185}, (144) = {126, 186}, (145) = {127, 187}, (146) = {128, 188}, (147) = {129, 189}, (148) = {130, 190}, (149) = {132, 191}, (150) = {133, 192}, (151) = {134, 193}, (152) = {135, 194}, (153) = {137, 196}, (154) = {141, 201}, (155) = {156, 183}, (156) = {155, 157}, (157) = {156, 158}, (158) = {157, 159}, (159) = {158, 160}, (160) = {159, 161}, (161) = {160, 331}, (162) = {163, 332}, (163) = {162, 165}, (164) = {175, 333}, (165) = {163, 166}, (166) = {165, 167}, (167) = {166, 168}, (168) = {167, 169}, (169) = {168, 170}, (170) = {169, 171}, (171) = {170, 172, 334}, (172) = {171, 173}, (173) = {172, 174}, (174) = {173, 176}, (175) = {164, 178}, (176) = {174, 177}, (177) = {176}, (178) = {175, 179}, (179) = {178, 180}, (180) = {179, 181}, (181) = {180, 182}, (182) = {181, 183}, (183) = {155, 182}, (184) = {142, 202}, (185) = {143, 203}, (186) = {144, 204}, (187) = {145, 205}, (188) = {146, 206}, (189) = {147, 195}, (190) = {148, 207}, (191) = {149, 208}, (192) = {150, 209}, (193) = {151, 210}, (194) = {152, 211}, (195) = {189, 197}, (196) = {153, 212}, (197) = {195, 198}, (198) = {197, 199}, (199) = {198, 200}, (200) = {199, 201}, (201) = {154, 200}, (202) = {184, 213}, (203) = {185, 214}, (204) = {186, 215}, (205) = {187, 216}, (206) = {188, 217}, (207) = {190, 219}, (208) = {191, 220}, (209) = {192, 221}, (210) = {193, 222}, (211) = {194, 223}, (212) = {196, 226}, (213) = {202, 232}, (214) = {203, 233}, (215) = {204, 234}, (216) = {205, 235}, (217) = {206, 236}, (218) = {225, 237}, (219) = {207, 238}, (220) = {208, 239}, (221) = {209, 240}, (222) = {210, 241}, (223) = {211, 224}, (224) = {223, 226}, (225) = {218, 227}, (226) = {212, 224}, (227) = {225, 228}, (228) = {227, 229}, (229) = {228, 230}, (230) = {229, 231}, (231) = {230, 232}, (232) = {213, 231}, (233) = {214, 244}, (234) = {215, 245}, (235) = {216, 246}, (236) = {217, 247}, (237) = {218, 248}, (238) = {219, 249}, (239) = {220, 250}, (240) = {221, 251}, (241) = {222, 252}, (242) = {243, 262}, (243) = {242, 244}, (244) = {233, 243}, (245) = {234, 263}, (246) = {235, 264}, (247) = {236, 265}, (248) = {237, 266}, (249) = {238, 267}, (250) = {239, 268}, (251) = {240, 269}, (252) = {241, 253}, (253) = {252, 254}, (254) = {253, 255}, (255) = {254, 256}, (256) = {255}, (257) = {258}, (258) = {257, 259}, (259) = {258, 260}, (260) = {259, 261}, (261) = {260, 262}, (262) = {242, 261}, (263) = {245, 273}, (264) = {246, 274}, (265) = {247, 275}, (266) = {248, 276}, (267) = {249, 277}, (268) = {250, 278}, (269) = {251, 279}, (270) = {271, 291}, (271) = {270, 272}, (272) = {271, 292}, (273) = {263, 293}, (274) = {264, 294}, (275) = {265, 295}, (276) = {266, 296}, (277) = {267, 297}, (278) = {268, 298}, (279) = {269, 280}, (280) = {279, 281}, (281) = {280, 282}, (282) = {281, 283}, (283) = {282, 284}, (284) = {283, 285}, (285) = {284, 299}, (286) = {287, 300}, (287) = {286, 288}, (288) = {287, 289}, (289) = {288, 290}, (290) = {289, 291}, (291) = {270, 290}, (292) = {272, 303}, (293) = {273, 304}, (294) = {274, 305}, (295) = {275, 306}, (296) = {276, 307}, (297) = {277, 308}, (298) = {278, 309}, (299) = {285, 315}, (300) = {286, 316}, (301) = {302, 320}, (302) = {301, 303}, (303) = {292, 302}, (304) = {293, 321}, (305) = {294, 322}, (306) = {295, 323}, (307) = {296}, (308) = {297, 324}, (309) = {298, 310}, (310) = {309, 311}, (311) = {310, 325}, (312) = {313, 326}, (313) = {312, 314}, (314) = {313, 327}, (315) = {299, 328}, (316) = {300, 329}, (317) = {318, 330}, (318) = {317, 319}, (319) = {318, 320}, (320) = {301, 319}, (321) = {304, 340}, (322) = {305, 341}, (323) = {306, 343}, (324) = {308, 345}, (325) = {311, 348}, (326) = {312, 350}, (327) = {314, 351}, (328) = {315, 354}, (329) = {316, 355}, (330) = {317, 356}, (331) = {161, 365}, (332) = {162, 366}, (333) = {164, 368}, (334) = {171, 374}, (335) = {344}, (336) = {337, 359}, (337) = {336, 338}, (338) = {337, 339}, (339) = {338, 340}, (340) = {321, 339}, (341) = {322, 342}, (342) = {341, 343}, (343) = {323, 342}, (344) = {335, 353}, (345) = {324, 346}, (346) = {345, 347}, (347) = {346}, (348) = {325, 349}, (349) = {348, 350}, (350) = {326, 349}, (351) = {327, 352}, (352) = {351, 354}, (353) = {344, 355}, (354) = {328, 352}, (355) = {329, 353}, (356) = {330, 357}, (357) = {356, 358}, (358) = {357, 359}, (359) = {336, 358}, (360) = {361, 385}, (361) = {360, 362}, (362) = {361, 363}, (363) = {362, 364}, (364) = {363, 386}, (365) = {331, 387}, (366) = {332, 367}, (367) = {366, 369}, (368) = {333, 378, 388}, (369) = {367, 370}, (370) = {369, 371}, (371) = {370, 372}, (372) = {371, 373}, (373) = {372, 389}, (374) = {334, 375}, (375) = {374, 376}, (376) = {375, 377}, (377) = {376, 379}, (378) = {368, 380}, (379) = {377, 390}, (380) = {378, 381}, (381) = {380, 382}, (382) = {381, 383}, (383) = {382, 384}, (384) = {383, 385}, (385) = {360, 384}, (386) = {364, 394}, (387) = {365, 395}, (388) = {368, 399}, (389) = {373, 404}, (390) = {379, 409}, (391) = {392, 415}, (392) = {391, 393}, (393) = {392, 416}, (394) = {386, 417}, (395) = {387, 396}, (396) = {395, 397}, (397) = {396, 398}, (398) = {397, 400}, (399) = {388, 408}, (400) = {398, 401}, (401) = {400, 402}, (402) = {401, 403}, (403) = {402, 404}, (404) = {389, 403, 418}, (405) = {406, 419}, (406) = {405, 407}, (407) = {406, 420}, (408) = {399, 410}, (409) = {390, 421}, (410) = {408, 411}, (411) = {410, 412}, (412) = {411, 413}, (413) = {412, 414}, (414) = {413, 415}, (415) = {391, 414}, (416) = {393, 424}, (417) = {394, 425}, (418) = {404, 435}, (419) = {405, 436}, (420) = {407, 437}, (421) = {409, 439}, (422) = {423, 445}, (423) = {422, 424}, (424) = {416, 423}, (425) = {417, 426}, (426) = {425, 427}, (427) = {426, 428}, (428) = {427, 429}, (429) = {428, 430}, (430) = {429, 432}, (431) = {438, 446}, (432) = {430, 433}, (433) = {432, 434}, (434) = {433, 447}, (435) = {418, 448}, (436) = {419, 449}, (437) = {420, 450}, (438) = {431, 440}, (439) = {421, 451}, (440) = {438, 441}, (441) = {440, 442}, (442) = {441, 443}, (443) = {442, 444}, (444) = {443, 445}, (445) = {422, 444}, (446) = {10, 431}, (447) = {12, 434}, (448) = {13, 435}, (449) = {14, 436}, (450) = {15, 437}, (451) = {16, 439}}), `GRAPHLN/table/3`, 0)

    (3)

    StyleVertex(G, sprintf("%d,%d",start[]), color="LimeGreen");

    StyleVertex(G, sprintf("%d,%d",finish[]), color="Red");

    for v in Vertices(G) do
        SetVertexAttribute(G, v,"draw-pos-fixed"=GetVertexAttribute(H,v,"draw-pos-fixed"));
    end do;

    DrawGraph(G, stylesheet=[vertexshape="square", vertexpadding=10, vertexborder=false, vertexcolor="Black"],  showlabels=false, size=[800,800]);

     

    sp := ShortestPath(G, sprintf("%d,%d",start[]), sprintf("%d,%d",finish[]) ):

    StyleVertex(G, sp[2..-2], color="Orange");
    StyleEdge(G, [seq({sp[i],sp[i+1]}, i=1..nops(sp)-1)], color="Orange");

    DrawGraph(G, stylesheet=[vertexshape="square", vertexpadding=10, vertexborder=false, vertexcolor="Black"],  showlabels=false, size=[800,800]);

     

     

     

     

    About once a year Advent of Code give you a problem that is a gift if you are using a computer algebra system. This year that day was Day 13. The day 13 problem was one of crazy claw machines.  Each machine has two buttons that can be pressed to move the claw a given number of X and Y positions and a prize at a given position. A buttons cost 3 tokens to press, and B buttons cost 1 token to press, and we are asked to find the minimum number of tokens needed, IF it is possible to reach the prize. The data presented like so:

    Button A: X+94, Y+34
    Button B: X+22, Y+67
    Prize: X=8400, Y=5400
    
    Button A: X+26, Y+66
    Button B: X+67, Y+21
    Prize: X=12748, Y=12176
    
    ...

    Some times the input is harder to parse than the problem is so solve, and this might be one of those cases.  I tend to reach for StringTools to take the input apart, but today the right tool is the old school C-style sscanf (after using StringSplit to split at every double linebreak).

    machinesL := StringTools:-StringSplit(Trim(input), "\n\n");
    machines := map(m->sscanf(m,"Button A: X+%d, Y+%d\nButton B: X+%d, Y+%d\nPrize: X=%d, Y=%d"), machinesL):
    

    Now we have a list of claw machine parameters in the form [A_x, A_y, B_x, B_y, P_x, P_y] and we need to turn those into equations that we can solve. We want the number of A presses a, and B presses b to get the claw to the P_x, P_y position of the claw, it is simple to just write them down:

    for m in machines do
       eqn := ({m[1]*a+m[3]*b=m[5], m[2]*a+m[4]*b=m[6]});
    end do;
    

    Now because of the discrete nature of this problem, we need our variables a and b to be non-negative integers.  When solving this, I first reached for isolve like this:

    tokens := 0;
    for m in machines do
       eqn := ({m[1]*a+m[3]*b=m[5], m[2]*a+m[4]*b=m[6]});
       sol := isolve(eqn);
       if sol <> NULL then
          tokens := tokens + eval(3*a+b, sol);
       end if;
    end do;
    

    Now, sometimes Advent of Code inputs contain a lot of hidden structure.  I wrote the code above, it worked on the sample input, so I tried it immediately on my real input (about 300 claw machines like the above) and IT WORKED.  But, you might notice that this code does not deal with a couple cases that could have appeared.  In particular, it doesn't check that the solutions are positive.  It also doesn't handle cases where there is more than one possible solution.  The former is easy to check

    if sol <> NULL and eval(a,sol) >= 0 and eval(b,sol) >= 0 then
    

    Unfortunately isolve does not handle inequalities, but you could try with solve, but it doesn't save us any checking, because we'd still have to check if the solutions are integers, so we might as well have just solved the equation and then checked if it were a nonnegative integer.

    tokens := 0;
    for m in machines do
       eqn := {m[1]*a+m[3]*b=m[5], m[2]*a+m[4]*b=m[6], a>=0, b>=0};
       sol := solve(eqn);
       if type(eval(a,sol), integer) and type(eval(b,sol),integer) then
          tokens := tokens + eval(3*a+b, sol);
       end if;
    end do;
    ans1 = tokens;

    In the multiple solution case we get something like {a = 3 - 2*b, 0 <= b, b <= 3/2} which has some great information in it but might be hard to handle programmatically, so let's see what isolve does with those cases to see if it's easier to deal with

    > eqn := { 17*a + 84*b = 7870, 34*a + 168*b = 15740 }:
    > constr := { a >= 0, b>= 0 }:
    > sol := isolve(eqn);
                   sol := {a = 458 - 84 _Z1, b = 1 + 17 _Z1}
    
    > constr := eval({ a >= 0, b>= 0 }, sol):
                const := {0 <= 1 + 17 _Z1, 0 <= 458 - 84 _Z1}
    
    > obj := eval(3*a+b, sol);
                             obj := 1375 - 235 _Z1

    You can see it's easy to tell if these show up in your input, since your "token" total will have the _Zn variables in it.  Now, since everything is simple and linear here, it seems like you could use solve to find the rational value of _Z1 that makes obj=0 and then take the closest integer but it's not so simple, we actually have to deal with the contraints that a and b be positive too. So, it really just makes sense to bring out the big hammer of Optimization:-Minimize which allows us to directly optimize over just the integers.  So a full solution looks like this:

    tokens := 0:
    for m in machines do
       eqn := ({m[1]*a+m[3]*b=m[5], m[2]*a+m[4]*b=m[6]});
       sol := isolve(eqn);
       if sol = NULL then
          next;
       end if;
       constr := eval({ a >= 0, b>= 0 }, sol);
       obj := eval(3*a+b, sol);
       if not type(obj, constant) then
          tokens := tokens + Optimization:-Minimize( obj, constr, assume=integer )[1];
       elif andmap(evalb, constr) then
          tokens := tokens + obj; 
       end if;
    end do;

    But since we're bringing out the big hammer, why not just use Optimization in the first place.  The main reason is that Minimize doesn't simply return NULL when it doesn't work, instead it throws an exception, so we need to find all the exceptions that can occur and handle then with a try-catch, thus:

    tokens := 0;
    for m in machines do
       eqn := ({m[1]*a+m[3]*b=m[5], m[2]*a+m[4]*b=m[6]});
       try 
           sol := Optimization:-Minimize(3*a+b, eqn, 'assume'='nonnegint')[1];
           tokens := tokens + sol;
       catch "no feasible":
       end try; 
    end do;
    tokens;
    

    (you can in fact omit the string in the catch: statement, but I can tell you from long experience that that is an excellent way to make your code much much harder to debug)

    Alright, so how did people not using Maple solve this problem?  The easiest way to solve it, and the one used by all the cheaters scraping the website and using LLM-based code generators that auto-submit solutions to get into the Top 100, was to just check all possible a, b values in 0..100 and take the values than minimize 3*a+b when reaching the prize coordinates.  That's only feasible because the problem states the 100 is an upperbound for a and b, but it's also very fast (about 1/10 second in Maple):

    tokens := 0:
    for m in machines do;
    sol := infinity;
    for i from 0 to 100 do for j from 0 to 100 do
        if i*m[1]+j*m[3]=m[5] and i*m[2]+j*m[4]=m[6] and 3*i+j < sol then
            sol := 3*i+j;
        end if;
    end do; end do;
    tokens := tokens + ifelse(sol=infinity,0,sol);
    end do;
    

    It does not scale at all to part 2 (which modified everything to be bigger by about 10 trillion), and it seems that foiled all the LLM solvers. So, what solutions scaled in languages without integer equation solvers?  Well, the easiest solution is just to solve the general equation using paper and pencil


    And you can just hard code that formula in, check that it gives integer values and compute the tokens. As long as you get unique solutions, that looks something like this

    solveit := proc(m)
    local asol := m[4]*m[5] - m[3]*m[6];
    local bsol := m[1]*m[6] - m[2]*m[5];
    local deno := m[1]*m[4] - m[2]*m[3];
    if deno = 0 then return -2^63; end if; # multiple solution case - not handled
    if asol mod deno = 0 and bsol mod deno = 0
       and (   ( deno>=0 and asol>=0 and bsol>=0 ) 
            or ( deno<=0 and asol<=0 and bsol<=0 ) )
    then
    
        return 3*asol/deno+bsol/deno;
    else
        return 0;
    end if;
    end proc:
    

    Which if you have this in Maple, you can impress your friends by auto generating solutions in other languages. Here, for your FORTRAN friends

    > CodeGeneration:-Fortran(solveit);
    
    Warning, the following variable name replacements were made: solveit -> cg
           integer function cg (m)
            doubleprecision m(*)
            integer asol
            integer bsol
            integer deno
            asol = int(-m(3) * m(6) + m(4) * m(5))
            bsol = int(m(1) * m(6) - m(2) * m(5))
            deno = int(m(1) * m(4) - m(2) * m(3))
            if (deno .eq. 0) then
              cg = -9223372036854775808
              return
            end if
            if (mod(asol, deno) .eq. 0 .and. mod(bsol, deno) .eq. 0 .and. (0
         # .le. deno .and. 0 .le. asol .and. 0 .le. bsol .or. deno .le. 0 .a
         #nd. asol .le. 0 .and. bsol .le. 0)) then
              cg = 3 * asol / deno + bsol / deno
              return
            else
              cg = 0
              return
            end if
          end
    
    

    Another way that you might solve this without solve is to use a linear algebra library to solve the linear system.  It works even if you only have a numeric solver, but you have to be careful about checking for integers:

    tokens := 0:
    for m in machines do
        sol := LinearAlgebra:-LinearSolve(
                   Matrix(1..2,1..2,[m[[1,3]],m[[2,4]]], datatype=float), 
                   Vector(m[5..6], datatype=float));
        if abs(sol[1]-round(sol[1])) < 10^(-8) and abs(sol[2]-round(sol[2])) < 10^(-8)
           and sol[1] >= 0 and sol[2] >= 0
        then
           tokens := tokens + 3*sol[1]+sol[2];
        end if;
    end do;
    

    Finally, a lot of people solved this sort of thing with the Z3 Theorem prover from Microsoft research which is also way more than you need, but it mostly just uses SMTLIB, which we also have in a library for in Maple, and it can just be used in place of solve

    tokens := 0;
    for m in machines do
       eqn := {m[1]*a+m[3]*b=m[5], m[2]*a+m[4]*b=m[6], a>=0, b>=0};
       sol := SMTLIB:-Satisfy(eqn) assuming a::nonnegint, b::nonnegint;
       if sol <> NULL and type(eval(a,sol), integer) and type(eval(b,sol),integer) then
          tokens := tokens + eval(3*a+b, sol);
       end if;
    end do;
    

    Notice that Satisfy handled the multiple solution case just by choosing one of the many solutions. It is possible to get SMTLib to optimize but it is slightly more involved, and this post is already too long. This time, I've put all this work in worksheet: Day13-Primes.mw

    Major deficiency in Physics[Vectors]; Distinct sets of basis vectors are not recognized!

    You can't define vectors in alternative bases like: {\hat{i}',\hat{j}',\hat{k}'} or {\hat{i}_{1},\hat{j}_{2},\hat{k}_{3}}.

    This deficiency has been around for a while. I have found other posts regarding this problem.

    The deficiency greatly reduces the allowable calculations with Physics[Vector].

    Are there any plans to fix this?

    Here is my example which shows this deficiency in more detail.

    physics_vectors_and_multiple_unit_vectors.mw
     

    restart

    NULL

    NULL

    with(Physics[Vectors])

    [`&x`, `+`, `.`, Assume, ChangeBasis, ChangeCoordinates, CompactDisplay, Component, Curl, DirectionalDiff, Divergence, Gradient, Identify, Laplacian, Nabla, Norm, ParametrizeCurve, ParametrizeSurface, ParametrizeVolume, Setup, Simplify, `^`, diff, int]

    (1)

    NULL

    Crucial Deficiency in Physics[Vectors]

     

    NULL

    I can only guess the purpose of the Physics[Vectors] package from reviewing it's corresponding help documentation. My interpretation of the documentation leads me to believe that the package is best used for generating vector equation formulas in different coordinate bases of a SINGLE coordinate system.

     

    This means one can easily generate position vector expressions such as:

     

    r_ = _i*x+_j*y+_k*z

    r_ = _i*x+_j*y+_k*z

    (1.1)

    Cylindrical Position Vector

     

    The position vector in a cylindrical basis is given by:

     

    r_ = ChangeBasis(rhs(r_ = _i*x+_j*y+_k*z), 2)

    r_ = (x*cos(phi)+y*sin(phi))*_rho+(cos(phi)*y-sin(phi)*x)*_phi+z*_k

    (1.1.1)

    r_ = ChangeBasis(rhs(r_ = _i*x+_j*y+_k*z), 2, alsocomponents)

    r_ = _k*z+_rho*rho

    (1.1.2)

    NULL

    NULLNULLNULL

    Spherical Position Vector

     

    NULL

    r_ = ChangeBasis(rhs(r_ = _i*x+_j*y+_k*z), 3)

    r_ = (y*sin(phi)*sin(theta)+x*sin(theta)*cos(phi)+z*cos(theta))*_r+(y*sin(phi)*cos(theta)+x*cos(phi)*cos(theta)-z*sin(theta))*_theta+(cos(phi)*y-sin(phi)*x)*_phi

    (1.2.1)

    r_ = ChangeBasis(rhs(r_ = _i*x+_j*y+_k*z), 3, alsocomponents)

    r_ = r*_r

    (1.2.2)

    NULL

    NULL

    As is known from the vector analysis of curvilinear coordinate systems the basis vectors can depend on the coordinates in question.

     

    In cylindrical, the basis vectors are

     

    _rho = ChangeBasis(_rho, 1)

    _rho = _i*cos(phi)+sin(phi)*_j

    (1.2)

    _phi = ChangeBasis(_phi, 1)

    _phi = -sin(phi)*_i+cos(phi)*_j

    (1.3)

    and in spherical, the basis vectors are

     

    _r = ChangeBasis(_r, 1)

    _r = sin(theta)*cos(phi)*_i+sin(theta)*sin(phi)*_j+cos(theta)*_k

    (1.4)

    _theta = ChangeBasis(_theta, 1)

    _theta = cos(theta)*cos(phi)*_i+cos(theta)*sin(phi)*_j-sin(theta)*_k

    (1.5)

    _phi = ChangeBasis(_phi, 1)

    _phi = -sin(phi)*_i+cos(phi)*_j

    (1.6)

    NULL

    NULL

    NULL

    Example of this Deficiency using Biot-Savart Law

     

    NULL

    Biot-Savart law can be used to calculate a magnetic field due to a current carrying wire. The deficiency in question can be observed by explicity constructing the integrand in the Biot-Savart integral defined below.

    NULL

    NULL

    NULL

    In electrodynamics, quantum mechanics and applied mathematics, it is common practice to define a position of observation by a vector `#mover(mi("r"),mo("&rarr;"))` and a position of the source responsible for generating the field by a vector diff(`#mover(mi("r"),mo("&rarr;"))`(x), x).

     

    It is just as common to define the difference in these vectors as

     

    l_ = r_-(diff(r(x), x))*_

    l_ = r_-`r'_`

    (1.3.1)

    and thus

     

    dl_ = dr_-(diff(dr(x), x))*_

    dl_ = dr_-`dr'_`

    (1.3.2)

    as found in the integrand of the Biot-Savart integral.

    NULL

    It suffices to consider `#mover(mi("l"),mo("&rarr;"))` = `#mover(mi("r"),mo("&rarr;"))`-`#mover(mi("r'"),mo("&rarr;"))` in a cylindrical basis for this argument.

     

    The observation position is:

     

    `#mover(mi("r"),mo("&rarr;"))` = rho*`#mover(mi("&rho;",fontstyle = "normal"),mo("&and;"))`+z*`#mover(mi("k"),mo("&and;"))`

    NULL

    The source position is:

     

    diff(`#mover(mi("r"),mo("&rarr;"))`(x), x) = (diff(z(x), x))*(diff(`#mover(mi("k"),mo("&and;"))`(x), x))+(diff(rho(x), x))*(diff(`#mover(mi("&rho;",fontstyle = "normal"),mo("&and;"))`(x), x))

    NULL

    `#mover(mi("l"),mo("&rarr;"))` = `#mover(mi("r"),mo("&rarr;"))`-(diff(`#mover(mi("r"),mo("&rarr;"))`(x), x)) and `#mover(mi("r"),mo("&rarr;"))`-(diff(`#mover(mi("r"),mo("&rarr;"))`(x), x)) = z(x)*`#mover(mi("k"),mo("&and;"))`-(diff(z(x), x))*(diff(`#mover(mi("k"),mo("&and;"))`(x), x))+rho*`#mover(mi("&rho;",fontstyle = "normal"),mo("&and;"))`-(diff(rho(x), x))*(diff(`#mover(mi("&rho;",fontstyle = "normal"),mo("&and;"))`(x), x))

    NULL

    The deficiency in question arises because MAPLE cannot define multiple unit vectors in distinct bases such as {`#mover(mi("&rho;",fontstyle = "normal"),mo("&and;"))`, diff(`#mover(mi("&rho;",fontstyle = "normal"),mo("&and;"))`(x), x)} or {`#mscripts(mi("&rho;",fontstyle = "normal"),mn("1"),none(),none(),mo("&and;"),none(),none())`, `#mscripts(mi("&rho;",fontstyle = "normal"),mn("2"),none(),none(),mo("&and;"),none(),none())`}.  These pairs of unit vectors arise naturally, as shown above in Biot-Savart law.

    NULL

    If we look at `#mover(mi("&rho;",fontstyle = "normal"),mo("&circ;"))` and  diff(`#mover(mi("&rho;",fontstyle = "normal"),mo("&circ;"))`(x), x) generally, they look like:

    NULL

    `#mover(mi("&rho;",fontstyle = "normal"),mo("&and;"))` = `#mover(mi("i"),mo("&and;"))`*cos(phi)+sin(phi)*`#mover(mi("j"),mo("&and;"))`

    NULL

    diff(`#mover(mi("&rho;",fontstyle = "normal"),mo("&and;"))`(x), x) = (diff(`#mover(mi("i"),mo("&and;"))`(x), x))*cos(diff(phi(x), x))+sin(diff(phi(x), x))*(diff(`#mover(mi("j"),mo("&and;"))`(x), x))

    NULL

    If the bases vectors {`#mover(mi("i"),mo("&and;"))`, `#mover(mi("j"),mo("&and;"))`, `#mover(mi("k"),mo("&and;"))`} and {diff(`#mover(mi("i"),mo("&and;"))`(x), x), diff(`#mover(mi("j"),mo("&and;"))`(x), x), diff(`#mover(mi("k"),mo("&and;"))`(x), x)} are Cartesian and are not related related through rotations so that

    NULL

    "(i)*i' =(|i|)*|i'|*cos(0)=1"``NULL

    NULL

    "(j)*(j)' =(|j|)*|(j)'|*cos(0)=1"NULL

    NULL

    "(k)*(k)' =(|k|)*|(k)'|*cos(0)=1 "

    NULL

    and so,NULL

     

    `#mover(mi("i"),mo("&circ;"))` = diff(`#mover(mi("i"),mo("&circ;"))`(x), x)

    NULL

    `#mover(mi("j"),mo("&circ;"))` = diff(`#mover(mi("j"),mo("&circ;"))`(x), x)

    NULL

    `#mover(mi("k"),mo("&circ;"))` = diff(`#mover(mi("k"),mo("&circ;"))`(x), x)

    NULL

    the radial unit vectors in cylindrical are then,

     

    `#mover(mi("&rho;",fontstyle = "normal"),mo("&and;"))` = `#mover(mi("i"),mo("&and;"))`*cos(phi)+sin(phi)*`#mover(mi("j"),mo("&and;"))`

    NULL

    diff(`#mover(mi("&rho;",fontstyle = "normal"),mo("&and;"))`(x), x) = `#mover(mi("i"),mo("&and;"))`*cos(diff(phi(x), x))+sin(diff(phi(x), x))*`#mover(mi("j"),mo("&and;"))`

    NULL

    In typical problems, the anglular location of the observation point, φ, is distinct from the angular location of the source, diff(phi(x), x) and so under this condition, `#mover(mi("&rho;",fontstyle = "normal"),mo("&and;"))` <> diff(`#mover(mi("&rho;",fontstyle = "normal"),mo("&and;"))`(x), x).

     

    Consider the classic problem of the magnetic field due to a circular current carrying wire. Surely, the angular coordinate of one location of the current carrying wire  is different from the angular coordinate  of an observation point hovering above and off-axis on the other side of the current carrying wire. See figure below.

    NULL

    NULL

    NULL

    NULL

    Therefore,

     

    `#mover(mi("&rho;",fontstyle = "normal"),mo("&and;"))` <> diff(`#mover(mi("&rho;",fontstyle = "normal"),mo("&and;"))`(x), x)

    NULL

    NULL

    What happens in MAPLE when you try to define a second distinct unit vector diff(`#mover(mi("&rho;",fontstyle = "normal"),mo("&and;"))`(x), x)?

    NULL

    One can easily find `#mover(mi("&rho;",fontstyle = "normal"),mo("&and;"))`.

    NULL

    _rho

    _rho

    (1.3.3)

    NULL

    NULLIf you try to define diff(`#mover(mi("&rho;",fontstyle = "normal"),mo("&and;"))`(x), x) ...

     

     

    diff(_rho(x), x)

    `_rho'`

    (1.3.4)

    So using a prime doesn't work.

    NULL

    You could try a numbered subscript...

    `_&rho;__2`

    _rho__2

    (1.3.5)

    but that doesn't work.

     

    You could try an indexed unit vector...

    NULL

    _rho[2]

    _rho[2]

    (1.3.6)

    which can be define but is not recognized by Physics[Vectors] since...

     

    NULL

    ChangeBasis(_rho[2], 1)

    Error, (in Physics:-Vectors:-Identify) incorrect indexed use of a unit vector: _rho[2]

     

    NULL

    And so it's just not possible with the current implementation.

    ``

    ``

    NULL

    NULL


     

    Download physics_vectors_and_multiple_unit_vectors.mw

     

     

    The Advent of Code 2024 Day 11 problem featured labeled rocks which duplicate according to simple rules:

    • Rocks labeled 0 turn into 1's
    • Rocks with a even number of digits in the label split into two rocks with the first and last half of the digits
    • Other rocks have their labels multiplied by 2024

    Your puzzle task is to count the number of rocks after 25, then 75 iterations of these rules.

    For 25 iterations, a very simple recursive count suffices

    count := proc(n, s)
    local f, l;
        if n = 0 then return 1;
        elif s=0 then return count(n-1,1);
        end if;
        l := length(s);
        if l mod 2 = 0 then
             f := floor( s/10^(l/2) );
             return count(n-1,f) + count(n-1,s-f*10^(l/2));
        else return count(n-1, 2024*s);
        end if;
    end proc:
    

    For the puzzle input, a collection of 8 numbers (the stone labels) the largest with 7 digits, you can call count(25,s) on each s in the input and add them together in about 1 second, but trying that for 75 "hangs" and clearly will not work.

    Generally for something like this, the first trick in my puzzle solving toolbox is memoization, so that the results of recursive calls are stored so they don't have to be recomputed.  In Maple, there are two main ways to add memoization to recursive procedures: option cache and option remember.  The remember option is older and uses a simple table that gets populated with (input,return) pairs whenever the procedure returns. The cache option is newer and uses size limited LRU tables that are more memory friendly.  Typically in the Maple math library we use cache tables since they won't fill up your working memory with cached results, and will remove old cached elements in a smart way (the double option option remember, system also limits table growth by allowing entries to be garbage collected, but it is not as flexible as a cache).

    So this preable is to say, that the first memoization option I tend to reach for is option cache but best practice for Maple math library development is not always the thing that solves a code puzzle.  In this case, adding option cache to our procedure count also "hangs".  If you are smart, you will immediately try again with option remember, and you'll find that works easily:

    count := proc(n, s)
    option remember;
        if n = 0 then return 1;
        elif s=0 then return count(n-1,1);
        end if;
        local l := length(s);
        if l mod 2 = 0 then
             local f := floor( s/10^(l/2) );
             return count(n-1,f) + count(n-1,s-f*10^(l/2));
        else return count(n-1, 2024*s);
        end if;
    end proc:
    ans1 := CodeTools:-Usage( add( map2(count, 25, input) ) ); # 17ms
    ans2 := CodeTools:-Usage( add( map2(count, 75, input) ) ); # 825ms
    

    So why does remember work, when cache fails so spectacularly? Well, you can create a function with a cache, call it once create it and the examine the Cache object with op:

    > cacheFunc := proc() option cache; args; end proc:
    > cacheFunc(1): op( 4, eval(cacheFunc) );
    
                           Cache(512, 'temporary' = [1 = 1])
    

    You can see here that the default cache is 512 entries which is a pretty good default for general use, but way way too small for this ridiculous puzzle problem.  Fortunately, the cache option allows you to specify a size to create a much bigger cache for a highly recursive procedure like this one.  I tested caches of various sizes (cache always rounds up the next power of 2) and compared to option remember and remember, system.

    1. option remember  - 707ms
    2. option remember, system - 4.22s
    3. option cache  - too slow, killed after hours
    4. option cache(1024) - 30.21s
    5. option cache(16384) - 5.60s
    6. option cache(131072)- 726ms
    7. option cache(1048576)- 806ms

    So, for this problem, it looks like a 2^17=~100,000 entry cache (#6) gives about the same performance as a remember table, so it's not surpring a larger cache does no better. 

    In fact, since results are not removed from an option remember table, you can actually check exactly how many results were cached and see it is just less than 2^17.

    > add( map2(count, 75, input) ): numelems( op(4, eval(count) ) );
                                        120076

    And the take away is, for this sort of puzzle solving you should try option remember even if option cache is usually a better choice when implementing a more serious mathematical algorithmn that wants to occasionally needs to reuse results.

    Every December since 2015, software engineer and puzzle enthusiast Eric Wastl has created an Advent Calender of code challenges called Advent of Code. These puzzles can be solved in any programming language, since you are only required to submit a string or integer solution, and tend to increase in difficulty over the course of the 25 days. Each puzzle has two parts each using the same input (which is different for each user), the second part being revealed only after the first part is solved.

    I started participating in this puzzle challenge in 2021 and I like to solve them using Maple right when they are unlocked at 12am EST each day. I post my my solutions to my github as Maple worksheets, and (usually) later as cleaned up Maple text files: https://github.com/johnpmay/AdventOfCode2024

    I typically work in a Maple worksheet since I find the worksheet interface ideal to quickly play with an evolving piece of code to solve a puzzle (it is kind of a race if you want it to be, Advent of Code tells you your place every day and gives you "points" if you are one of the first 100). Also I find the nature of the Maple language and its variety of libraries pretty ideal for approaching these problems.

    Today, I am writing about this because 2025 Day 5 was a cool puzzle that really asked to be analyzed further in Maple. (Note, if you are participating in Advent of Code and haven't solved Day 5, there are heavy spoilers ahead).

    Once you decypher the silly story about the elves, the problem comes down to a set of pairwise ordering rules, and a collection of lists (called updates) that need to be checked if they are sorted according to the rule. This seems straightforward, but as always you have a (big!) input file to handle.  In this case the input looks like this (the actual input not included here, but it's much much longer)

    75|13
    53|13
    [...elided...]
    
    
    75,47,61,53,29
    97,61,53,29,13
    [...elided...]
    
    

    For this step, StringTools is your best friend (I typically read in the whole input as a string using FileTools:-Text:-ReadFile).  I first use StringSplit on the double line break "\n\n" to seperate the rules from the updates.  Then I map an ordinary Split over those to make everything into nested lists of integer.

    (rules, updates) := StringSplit(Trim(input), "\n\n")[]:
    rules := map(s->map(s2i,Split(s,"|")), Split(rules,"\n")): 
    
            rules := [[75, 13], [53, 13], ...]
    
    updates := map(s->(map(s2i,Split(s,","))), Split(updates, "\n")):
    
            updates := [[75, 47, 61, 53, 29], [97, 61, 53, 29, 13], ...]
    

    (the function s2i is a "string to integer" helper function since it's considered bad practice to just call parse on input handed to you by a stranger on the internet.  In older version of maple I used: s2i := s->sscanf(s,"%d")[1] in newever versions you can use the way less cryptic s2i := s->convert(s,'integer') )

    Okay, now that we have two nice lists, it's easy to check which of the updates is sorted according to the rules with a simple nested loop.

    goodups := DEQueue():
    
    for u in updates do
        for r in rules do
            if member(r[1],u,'i') and member(r[2],u,'j') then
               if j < i then next 2; end if;
            end if;
         end do;
         push_back(goodups, u);
    end do:
    

    For each update, check that if a rule applies to it then that rule is obeyed. If the rule r is violated, advance the outer loop with the relatively new and useful next 2; syntax (it also works with break #) and if not check the next rule. If no rules were violated then push u into our stack of Good Updates.  This is a perfectly fine solution to part 1 of the puzzle, but if you thing about it a little why not just use sort with a custom comparision function built from the rules?

    V := ListTools:-MakeUnique(map2(op,1,rules)): # all the numbers that can appear
    N := [seq(map2(op,2,select(n->m=n[1], rules)), m in V)]: # all their neighbors in the graph induced by rules
    T := table([seq(V[i]={N[i][]}, i=1..nops(V))]): # table of neighbors
    comp := (x,y)->evalb(y in T[x]): # "less than" according the rules
    

    Now with that comp function we can just do

    goodups := select(u->sort(u, comp)=u, updates);

    to find all the correctly sorted updates, this will seem like a better idea when you get the [SPOILER] part 2 of the problem which is to sort all the incorrectly sorted updates.

    NOW WAIT A MINUTE.  If you look at the fine help page for ?sort you'll see it very clearly says about the comp function F (emphasis added):

    custom boolean procedure

     When F does not match one of the symbols listed above, it must be a Boolean-
     valued function of two arguments.  Specifically, F(a,b) returns false if and  
     only if b must precede a in the sorted output.  That is F(a,b) is a non-
     strict less than comparison function.  In addition, F(a,b) must be defined  
     for all pairs a for a and b in the input structure and F(a,b) must be  
     transitive
    , that is, if F(a,b) = true and F(b,c) = true then F(a,c) = true.

    Dear reader, I guess we should check if our rules from the puzzle create a relation that is transitive.  The good news is that the sample input given in the problem description is indeed transitive. The easiest way I could think to check that was to use GraphTheory and see if there were any cycles in the directed graph given by the rules. So, let's make a graph with an edge for every comparison rule a<b, b<c, etc.  If there is a cycle in the graph, that will be a case where a < b < c < a in our rules and therefore non-transitivity in the comparison.  When we do that, we see it's cycle-free.

    with(GraphTheory):
    G := Graph({rules[]});
    FindCycle(G); # returns []

    That graph is really nice, it looks like this:

    If you count the in-degree of each vertex, you can see it actually induced a total order on the numbers going linearly from smallest to largest numbers.

    So, is that also true of the actual input you are given? Of course not. When you create the graph of your actual puzzle input you find there is a 3-cycle.

    with(GraphTheory):
    G := Graph({rules[]});
    FindCycle(G); # returns a 3-cycle
    seq(FindCycle(G,v),v in Vertices(V)); # returns a 3-cycle for every v!

    In fact, there is a 3-cycle from every single vertex.  But at least the graph is pleasing to contemplate. Let it calm you:

    So, does this mean sort with out comp function doesn't work? Is all lost? In fact, I solved both parts of the puzzle using a custom comparision for sort before stopping to consider that maybe the comparison wasn't transitive. And... it just works! So, WHY does it work? (the comparison is very very non-transitive). The answer is of course that the lists you need to sort don't contain all of the numbers covered by the rules.  In fact, your clever/cruel puzzlemaster has in fact constructed each of those (200 or so) lists so that it misses every one of the 3-cycles in the above graph. You can carefully check that by restricting the relation graph to the subset of numbers in each list and check for cycles:

    G := Graph({rules[]});
    H := InducedSubgraph(G, updates[i]); # try for i=1..nops(updates)
    FindCycles(H); # returns [] for every element of update

    In fact, each of those induced subgraphs looks like this

    and you can maybe observe that this induced a total order on the numbers in the problem. Or if you are not careful, and you didn't bother to check, you would get the right answer anyway. Because it's only Day 5, and Eric Wastl hasn't decided to make thing really challenging yet.

    I hope you've enjoyed my deep dive into this problem. And I hope it's inspired you to go try out Advent of Code. It's a fun challenge. Let me know in a comment if you're participating! Maybe we can start a leaderboard for MaplePrimes folks working on the puzzles.

    With Maple Flow, we’re regularly rolling out exciting updates. Each offers new features, as well as resolving many user-reported issues.

    Flow 2024.2 lives up to that track record. Two major new features - drop-down menus and phasors - make their debut. We've also made many other quality-of-life enhancements.

    Drop-down list boxes make your worksheets more tactile and interactive. The menu items can be defined in a matrix or vector, or in a table. You can return the index of the selected item, or return an entire row or column of a matrix.

    An important use case is populating the contents of a drop-down menu with data from an external file. In movie below, we

    • import a database of steel shapes and their associated properties
    • populate the drop-down menu with the steel shapes in the first column of the imported data
    • based upon the selected shape, use ArrayTools:-Lookup to return a property
    • and finally perform a design analysis.

    If you look carefully, you'll see that you can hide commands on a per-container basis to make your worksheets cleaner.

    We have a large number of power system engineers who want to model electrical systems in phasor notation.

    Entering a phasor is easy - just enter the magnitude, the angle character and then the angle. Phasors evaluate to rectangular complex numbers but can be recast to phasor format with the Context Panel.

    You can also associate a unit with the magnitude and angle. On output, you can change units inline or via the Context Panel.

    You can also prevent floating point approximation of phasors using the symbolic toggle on each container.

    We've also made a raft of other improvements. Extracting slices of matrices is faster, and you can now enter units in 2d notation in the Context Panel (particularly useful when you want to change the units of everything inside a matrix).

    As ever, the new features are driven by you. The only way you can point us the right direction is by telling us what you want. Don't be shy!

    I was working in my living room.  My computer was upstairs, but I had my phone and tablet.  I'm working on The Book ("Perturbation methods using backward error", with Nic Fillion, which will be published by SIAM next year some time).

    I've discovered something quite cool, historically, about the WKB method and George Green's original invention of the idea (that bears other people's names, or, well, initials, anyway).  (As usual.)  Green had written down a PDE modelling waves in a long narrow canal of slowly varying breadth 2*beta(x) and slowly varying depth 2*gamma(x).  Turns out his "approximate" solution is actually an exact solution to an equation of a very similar kind, with an extra term E(x)*phi(x,t).  The extra term depends in a funny way on beta(x) and gamma(x), and only on those.  So a natural kind of question is, "is there a canal shape for which Green's solution is the exact solution with E(x)==0?"  Can we find beta(x) and gamma(x) for which this works?

    Yes.  Lots of cases.  In particular, if the breadth beta(x) is constant, you can write down a differential equation for gamma(x).  I wrote it in my notebook using y and not gamma.  I wrote it pretty neatly.  Then I fired up the Maple Calculator on my little tablet, opened the camera, and pow!  Solved.

    I wrote the solution down underneath the equation.  It checks out, too.  See the attached image.

    Now, after the fact, I figured out how to solve it myself (using Ricatti's trick: put y' = v, then y'' = v*dv/dy, and the resulting first order equation is separable).  But that whole "take a picture of the equation and write down the solution" thing is pretty impressive.

     

    So: kudos to the designers and implementers of the Maple Calculator.  Three cheers!

     

    As an enthusiast and frequent user of unit functionalities, I would like to suggest some improvements.

    Example 1: 

    Assume a quantity equation w = f(z) where we substitute z = 100*`&mu;m` (and probably other parameters with units) to obtain a numerical result.
    After some simplifications the result is

    w = 0.3365290139e-4*Unit('m')

    w = 0.3365290139e-4*Units:-Unit(m)

    (1)

     

    A result in this form is the most frequent physical quantity equation with units in use:

    A physical quantity denoted by the name w that is equal to a numerical value times a physical unit.

    In this form it is also the shortest way to define/name scientific constants, scientific and engineering parameters, and results for variables/unknowns.  


    To better interpret the above result a conversion to micron is desirable. This unfortunately does not work with the context panel. Alternatively one could think of mapping a command onto the equation.
    (Mapping a command is a good practice to threat the left-hand side and the right-hand side of an equation equally.)

    map(convert, w = 0.3365290139e-4*Units:-Unit(m), units, micron)

    Error, (in convert/units) unable to convert `1` to `micron`

     

    This however does not work, since the left-hand side does not contain the dimension length, but only the name w of the physical quantity.  

    A way to convert is:

    lhs(w = 0.3365290139e-4*Units:-Unit(m)) = convert(rhs(w = 0.3365290139e-4*Units:-Unit(m)), units, micron)

    w = 33.65290139*Units:-Unit(micron)

    (2)

    For a single result this might be acceptable, but for a list of results this not practical.

    In any case not being capable to apply to an equation the same operation to both sides bares the risks of introducing errors.

    NULL

    Example 2: 

    More complicated are results of this kind

    NULL

    w((1/10000)*Unit('m')) = 0.3365290139e-4*Unit('m')

    w((1/10000)*Units:-Unit(m)) = 0.3365290139e-4*Units:-Unit(m)

    (3)

    A way to convert this to w(100*`&mu;m`) = 33.65290139*`&mu;m`:

    w(convert(op(lhs(w((1/10000)*Units:-Unit(m)) = 0.3365290139e-4*Units:-Unit(m))), units, micron)) = convert(rhs(w((1/10000)*Units:-Unit(m)) = 0.3365290139e-4*Units:-Unit(m)), units, micron)

    w(100*Units:-Unit(micron)) = 33.65290139*Units:-Unit(micron)

    (4)

    This is too complicated.

    Instead, eval with a manually entered conversion can be used for this

    eval(w(100*Units:-Unit(micron)) = 33.65290139*Units:-Unit(micron), Unit('m') = 10^6*Unit('`&mu;m`'))

    w(100*Units:-Unit(micron)) = 33.65290139*Units:-Unit(micron)

    (5)

    However, this is old style: The way we had to work before the introduction of the unit package.

     

    In other areas Maples unit conversion functionalities are more advanced.

    Plotting with units for example has been improved to the point where unit conversion errors of quantity expressions are almost impossible (in contrast to numerical-value expressions): The user can specify the units to display and the numerical values of the physical quantities are converted accordingly.

     

    S1: To catch up with that improvement, conversion of the results as in Example 1 in the form of quantity equations would be desirable as well.

     

    Other desirable unit conversions of quantity expressions are

     

    • 

    S2: Right click (or select and right click) a unit in Maple output and conversion to a new unit with the context panel (try it with one of the above outputs: nothing happens).

    • 

    S3: Replacement of a unit by a desired unit of the same dimension (Example 2).

    • 

    S4: Replacement of a unit by conversion to a new equivalent unit (e.g.: "&lobrk;(m kg)/(s^3 A)&robrk; to V/(m)") matching the pattern of the unit but not necessarily the pattern of the underlying Unit commands (for this subs can be used already).

     

    For all suggestions, it is important that the physical quantity to be converted does not change, i.e. if a unit is changed, the numerical value of the physical quantity is changed accordingly.

     

    Download Unit_conversion_in_quantity_expressions.mw

    An example of solving a system of nonlinear equations, when all (real) solutions are found for one initial approximation. To make it easier to understand the program text, a description of the solution method is provided separately in PDF format.

    Draghilev’s_method_pdf.pdf

    3_EQUATIONS.mw

    Using the curve, the projection of which from the space R^4 to R^3 we see in the figure, we find good approximations to the solution. For each solution, the program prints out the norm of the discrepancy of the entire system of equations and shows a simple graph when the additional variable intersects R^3 . At this moment of intersection, the solution of our system is fixed.
    System of equations and initial approximation.

     

    f1 := x1^2+x2^2-x3^2; 
    f2 := (x1-1)^4+x2^4+(x3-2)^4-81; 
    f3 := x3-3*tan(.4*x2); 
    x01, x02, x03 := 1, 1, 1




    Old link to a similar example, where the dimension of the system of equations is 2, and we can see the auxiliary curve completely in R^3.

    Hello Maple enthusiasts,

    I am excited to share a sample worksheet on Ordinary Differential Equations (ODEs), created as part of my ongoing project—a book I am writing for undergraduate students. This book is designed to teach ODEs using Maple, offering an interactive and intuitive approach to solving differential equations.

    As far as I know, there aren’t many books available in the Greek language that combine ODEs with Maple. In fact, I believe there’s only one other such resource, which highlights the lack of materials in this niche. My goal is to fill this gap by providing students and educators with a resource that is both practical and accessible, leveraging Maple's powerful capabilities to deepen understanding and simplify complex concepts.

    The worksheet I’m sharing includes:

    • Step-by-step solutions to ODEs using Maple.
    • Graphical representations to visualize solutions, which I believe are invaluable for fostering comprehension.

    I hope this preview sparks your interest and provides insight into the teaching style and structure of the upcoming book. I would love to hear your thoughts, feedback, or suggestions for topics you think should be included.

    Solve the following differential equation

    diff(y(x), x) = x*y(x)
    with initial condition y(0) = 1

    restart; with(plots); with(DEtools)

    ode := diff(y(x), x) = x*y(x)

    diff(y(x), x) = x*y(x)

    (1)

    ic := y(0) = 1

    y(0) = 1

    (2)

    general_solution := dsolve(ode, y(x))

    y(x) = c__1*exp((1/2)*x^2)

    (3)

    particular_solution := dsolve({ic, ode}, y(x))

    y(x) = exp((1/2)*x^2)

    (4)

    soln := dsolve({ic, ode}, y(x), numeric)

    ``

    (5)

    p1 := odeplot(soln, [x, y(x)], x = -5 .. 5, labels = ["x", "y(x)"], color = green)

    directionfield := dfieldplot(ode, [y(x)], x = -5 .. 5, y = -5 .. 5, color = blue, arrows = slim, scaling = constrained, axes = boxed)

    display([p1, directionfield], view = [-5 .. 5, -5 .. 5])

     

    NULL

    Solve the following differential equation

    diff(y(x), x) = x/y(x)
    with initial condition y(0) = 2

    restart; with(plots); with(DEtools)

    ode1 := diff(y(x), x) = x/y(x)

    diff(y(x), x) = x/y(x)

    (6)

    ic := y(0) = 2

    y(0) = 2

    (7)

    dsolve(ode1, y(x))

    y(x) = (x^2+c__1)^(1/2), y(x) = -(x^2+c__1)^(1/2)

    (8)

    NULL

    soln := dsolve({ic, ode1}, y(x), numeric)

    p1 := odeplot(soln, [x, y(x)], x = -5 .. 5, labels = ["x", "y(x)"], color = green)

    directionfield := dfieldplot(ode1, [y(x)], x = -5 .. 5, y = -5 .. 5, color = blue, arrows = slim, scaling = constrained, axes = boxed)

    display([p1, directionfield], view = [-5 .. 5, -5 .. 5])

     

    NULL

    Solve the following differential equation

    dy/dx = e^y/(x^2+1)
    with initial condition y(0) = -1

    restart; with(plots); with(DEtools)

    ode2 := diff(y(x), x) = exp(y(x))/(x^2+1)

    diff(y(x), x) = exp(y(x))/(x^2+1)

    (9)

    ic := y(0) = -1

    y(0) = -1

    (10)

    dsolve(ode2, y(x))

    y(x) = ln(-1/(arctan(x)+c__1))

    (11)

    soln := dsolve({ic, ode2}, y(x), numeric)

    p1 := odeplot(soln, [x, y(x)], x = -5 .. 5, labels = ["x", "y(x)"], color = green)

    directionfield := dfieldplot(ode2, [y(x)], x = -5 .. 5, y = -5 .. 5, color = blue, arrows = slim, scaling = constrained, axes = boxed)

    display([p1, directionfield], view = [-5 .. 5, -5 .. 5])

     

    NULL

    Solve the following differential equation

    dy/dx = y^2+y
    with initial condition y(1) = 2

    restart; with(plots); with(DEtools)

    ode3 := diff(y(x), x) = y(x)+y(x)^2

    diff(y(x), x) = y(x)+y(x)^2

    (12)

    ic := y(1) = 2

    y(1) = 2

    (13)

    dsolve(ode3, y(x))

    y(x) = 1/(-1+exp(-x)*c__1)

    (14)

    soln := dsolve({ic, ode3}, y(x))

    y(x) = 2/(-2+3*exp(-x)*exp(1))

    (15)

    DEplot(ode3, y(x), x = -5 .. 5, y = -5 .. 5, [[y(1) = 2]], color = blue, arrows = slim, scaling = constrained, axes = boxed)

     

    NULL

    Solve the following differential equation

    y*dy/dx-x = 0
    with initial condition y(0) = 4, y(1) = 2, y(-1) = -2and y(-2) = -4.

    restart; with(plots); with(DEtools)

    ode4 := y(x)*(diff(y(x), x))-x = 0

    y(x)*(diff(y(x), x))-x = 0

    (16)

    ic := y(0) = 4

    y(0) = 4

    (17)

    dsolve(ode4, y(x))

    y(x) = (x^2+c__1)^(1/2), y(x) = -(x^2+c__1)^(1/2)

    (18)

    DEplot(ode4, y(x), x = -5 .. 5, y = -5 .. 5, [[y(1) = 2], [y(0) = 4], [y(-1) = -2], [y(-2) = -4]], color = blue, arrows = slim, scaling = constrained, axes = boxed)

     

     

     

    NULL

    Solve the following differential equation

    dy/dx = 2*x+2*xy^2/y
    with initial condition y(0) = 2.

    restart; with(plots); with(DEtools)

    ode5 := diff(y(x), x) = (2*x+2*x*y(x)^2)/y(x)

    diff(y(x), x) = (2*x+2*x*y(x)^2)/y(x)

    (19)

    ic := y(0) = 2

    y(0) = 2

    (20)

    dsolve(ode5, y(x))

    y(x) = (exp(2*x^2)*c__1-1)^(1/2), y(x) = -(exp(2*x^2)*c__1-1)^(1/2)

    (21)

    psoln := dsolve({ic, ode5}, y(x))

    y(x) = (5*exp(2*x^2)-1)^(1/2)

    (22)

    soln := dsolve({ic, ode5}, y(x), numeric)

    p1 := odeplot(soln, [x, y(x)], x = -5 .. 5, labels = ["x", "y(x)"], color = green)

    directionfield := dfieldplot(ode5, [y(x)], x = -5 .. 5, y = -3 .. 10, color = blue, arrows = slim, scaling = constrained, axes = boxed)

    display([p1, directionfield], view = [-5 .. 5, -3 .. 10])

     

    NULL


     

    Download separable_diff_equations.mw

     

    Hi all,

    I successfully typed in some Maple code in the form of a simple minded procedure.

    pairs_of_prime_numbers_procedure_with_union_and_isprime.mw

    pairs_of_prime_numbers_procedure_with_union_and_isprime.pdf

    Hopefully this is useful to someone.

    Have a nice day

    big Matt

    Hello,

    I present the rolling of an ellipse along a spatial curve and along curves placed on a surface, also along a Mobius surface.

    Attached are the Maple source files.

    Best regards.

    Source_-_mw.zip






    2 3 4 5 6 7 8 Last Page 4 of 305