Iterator update available

January 09 2013 Joe Riel 6226

5

The latest version of the Iterator package is now available at the Maplesoft Application Center.  It provides a new export, MultiPartition, extensions to existing exports, and options to most exports for transforming the output to a more desirable form. The help pages have been improved, with some hopefully interesting examples.  Here is one, showing how it can be used to write a procedure for solving a generalized alphametic.

alphametic := module()

export ModuleApply;
local SymbolToAlg;

    ModuleApply := proc(eq :: string
                        , base :: posint := 10
                        , { compile :: truefalse := true }
                        , $
                       )
    local chars
        , ex,i,n,vars,x,pred,iter
        , p
        ;
    uses ST=StringTools;

        # Parse the string and convert an equation to an expression.
        ex := parse(eq);
        ex := `if`(ex :: equation
                   , (lhs-rhs)(ex)
                   , ex
                  );

        # Extract the symbols (names).
        vars := indets(ex,symbol);

        # Convert each symbol in ex to an algebraic equivalent
        # in terms of the characters in the the symbol.
        ex := subs([seq(x = SymbolToAlg(x,base), x=vars)],ex);

        # Assign vars the characters in ex
        vars := indets(ex,symbol);
        n := nops(vars);

        if n > base then
            error "too many characters (%1) for base %2", n, base;
        end if;

        # Convert characters to indexed names of V
        ex := subs([seq(vars[i]='V'[i],i=1..n)],ex);
        ex := expand(ex);

        # Assign a predicate that returns true if the permutation
        # evaluates ex to 0 (evalb does not work with Compiler:-Compile).
        pred := subs('_ex'=ex, proc(V :: Array(datatype=integer[4]))
                               local ex := _ex;
                                   if ex=0 then
                                       return true;
                                   else
                                       return false;
                                   end if;
                               end proc
                    );

        # Optionally compile the predicate
        if compile then
            pred := Compiler:-Compile(pred);
        end if;

        # Construct an iterator to iterate over all acceptable permutations.
        iter := Iterator:-Permute(0..(base-1),n, 'accept'=pred);

        # Find solutions and format as equations.
        vars := map(convert,vars,string);
        chars := ST:-Explode(eq);

        seq(ST:-Join(subs([seq(vars[i]=convert(p[i],string), i = 1..n)]
                          , chars)
                     ,"")
            , p=iter
           );

    end proc:

    # Procedure that converts a symbol into a multinomial
    # over the characters of the symbol.

    SymbolToAlg := proc(symb,base::posint:=10)
    local val,char;
        val := 0;
        for char in convert(symb,string) do
            val := base*val+cat(``,char);
        end do;
        val;
    end proc:

end module:

eq := "maple*sim = modelica + model":
alphametic(eq);
                    "16540*781 = 12904836 + 12904"


Please Wait...