I recently discovered a minor variation on the technique of building a set using a table. The purpose for using a table rather than inserting new items directly into a set is that, in a loop, the latter technique is O(n2) rather than O(n). The way I would normally do this is to assign a counter and an empty table, and then, in a loop, compute the new element, increment the counter, and insert the element into the table at the counter index. For example,
A recent post asks how to create a Maple permutation iterator, that is, a procedure that, on successive calls, iterates through each permutation of a given input. I suggested a routine that solved the problem, however, I wasn't satisfied with it. It was slower than it should be. Later I suggested an improvement. Here is another improvement. It uses the same algorithm (algorithm L, from The Art of Computer Programming, vol. 4, fasicle 2, by Donald E. Knuth) if the input has repeated elements, but uses a different method, algorithm T, ibid., if the input consists of distinct elements. The sequences of permutations for the two algorithms differ, the second algorithm uses the initial order for the first element and consecutive outputs differ by one transposition.
John Fredsted suggested using the following procedure (slightly modified) to determine whether an expression was deeply algebraic.
isDeeplyAlgebraic := proc(x) if not type(x,'algebraic') then false elif type(x,'atomic') then true else andmap(procname,x) end if end proc:
Rather than using a procedure as a predicate, this seems more usefully expressed as a type. A nice way to do that is with Maple's TypeTools[AddType] procedure. For example
TypeTools:-AddType('DeeplyAlgebraic1'
, proc(x)
if not x :: 'algebraic' then false;
elif x :: 'atomic' then true;
else andmap(type,x,'DeeplyAlgebraic1');
end if;
end proc);
Maple's foldl and foldr procedures provide a convenient means to generate an n-ary function from a binary operator. For example, from another thread, one can use foldl to create an n-ary and procedure from Maple's binary `and` function:
A:={ { [1,2],[3,4] } , { [5,6],[7,8] } }:
map(x->map(y->map(f,y),x),A);
{{[f(1), f(2)], [f(3), f(4)]}, {[f(5), f(6)], [f(7), f(8)]}}
As has been discussed here
recently, this can be readily done using evalindets. For example,
evalindets(A, list, integer, f);
{{[f(3), f(4)], [f(1), f(2)]}, {[f(5), f(6)], [f(7), f(8)]}}
sort procedure,
that is, assigning a boolean-valued binary function and passing it to sort.
The second method that Robert provided is ingenious. Here it is, in full,
Ls:= map(convert,L,bytes): Ls:= sort(Ls, lexorder): map(convert,Ls,bytes);
It converts each list into a string, sorts the strings, then converts the strings back to lists. This method is significantly faster than the previous. It does, however, have a limitation; it can only operate on lists with positive integers in the range 1..255. While that limitation was suitable for the original poster's application, that will not always be the case.
overload command
provides a useful mechanism for splitting the implementation of a procedure
that operates on different types of arguments into separate procedures.
This article describes the mechanism that it uses to select the procedures, illustrates subtle issues, and shows how they can be resolved.
Occasionally it is necessary to temporarily assign a global flag to perform an action. Consider, for illustration, a procedure that returns the inert form of a procedure. We want it to be able to work with procedures that are local to modules. To do that, we need to temporarily assign the kernel flag opaquemodules to false.
GetInert1 := proc(p::uneval)
local opacity,inert;
opacity := kernelopts('opaquemodules'=false);
inert := ToInert(eval(p));
kernelopts('opaquemodules'=opacity);
inert;
end proc:
Here is a small module to test this on:
1 hour 10 min ago
7 hours 35 min ago
7 hours 39 min ago
7 hours 45 min ago
8 hours 49 min ago
9 hours 22 min ago
9 hours 23 min ago
9 hours 15 min ago
10 hours 15 min ago
10 hours 16 min ago