Carl Love

Carl Love

24805 Reputation

25 Badges

10 years, 113 days
Natick, Massachusetts, United States
My name was formerly Carl Devore.

MaplePrimes Activity

These are answers submitted by Carl Love

The type ?even is predefined, and ?select is a command. Putting them togther, letting L be your list above, the command is

select(type, L, even)


For those who like fewer words, the following does the same thing:

select(`::`, L, even)

There is a simple command to insert the backslashes! But I didn't find it until I had given up looking for such in the extremely bloated StringTools package (and I looked at every command there). The old original sprintf command has a format option, %a, that formats anything so that it can be reparsed.

p:= "Einstein said, \"Everyone's....\"....";
           p:=  "Einstein said, "Everyone's...."...."
sprintf("%a", p);
           ""Einstein said, \"Everyone's....\"....""

Of course, you see that it added the backslashes. But also note the extra quotes at beginning and end. These are so that it will parse as a string literal, rather than as a string containing other Maple code.

             "Einstein said, "Everyone's...."...."

I had thought about the issue of capping before I posted my previous answer. The capping is the most difficult part, and I thought that it would've been a waste to have spent time on it if if turned out that the whole tubeplot idea didn't meet your needs. I had considered plottools:-cylinder, but it is quite difficult (though not impossible) to use because it only generates cylinders with axes parallel to the z-axis. So they would have to be individually rotated at random. I also considered representing each cap as a parametric surface; it's a lot of analytic geometry to get the parameters right.

It turns out that the caps can be generated with tubeplot, if you're willing to accept caps that are not perfectly flat; rather, they are slightly conical, like cylinders of hard candy wrapped in paper which is twisted at the ends. The radius of the tube can vary (with the same parameter, t, that is used as the parameter of the tube's curve), and we simply need to make it go abruptly to 0 at both ends. I do this with a step function created with piecewise.

Npts:= 12:
Gen:= (N,R)-> RandomTools:-Generate(list(float(range= 1..R), N)):
x,x1,y,y1,z,z1:= seq(Gen(Npts,20), k= 1..6):
R:= Gen(Npts,3):  # random radius parameter
candy:= piecewise(t <= 0, 0, t < 1, 1, 0):
   [x+(x1-x)*t, y+(y1-y)*t, z+(z1-z)*t, radius= R*candy]
   plots:-tubeplot(P(x,x1,y,y1,z,z1,R), t= 0..1, tubepoints= 20)
plots:-display([seq](S(x[k],x1[k],y[k],y1[k],z[k],z1[k],R[k]), k= 1..Npts));

You misspelled init1 as inti1 in both DEplot commands. You also misspelled title in your display command.

T:= [seq](expand(cos(n*arccos(x))), n= 2..6);

 [    2           3             4       2              5        3        
 [2 x  - 1, 4 x  - 3 x, 8 x  - 8 x  + 1, 16 x  - 20 x  + 5 x,

         6         4         2     ]
   32 x  - 48 x  + 18 x  - 1]

plots:-display(Array([seq](plot(T[n], x= -1..1, title= sprintf("n=%d",n+1)), n= 1..nops(T))));

If you want to parse a string as a string literal, and that string literal contains quotes, then you'll need to backslash the quotes, just as you would if you'd entered it from the keyboard. Something like this:

p:= "assign(b,\"Einstein said, \\\"Everyone's....\\\"....\")";
         p:= "assign(b,"Einstein said, \"Everyone's....\"....")"
writeline("junk.mpl", p):
p:= readline("junk.mpl");
        p:= "assign(b,"Einstein said, \"Everyone's....\"....")"
parse(p, statement);
             "Einstein said, "Everyone's...."...."

It works for me. You'll need to post an example of it not working for you.

p:= "acat:= \"a cat\"";
                        p:= "acat:= "a cat""
writeline("junk.mpl", p);
p:= readline("junk.mpl");
                        p:= "acat:= "a cat""
parse(p, statement);
                           acat:= "a cat"
                            "a cat"
                            "a cat"

The two solutions need to be enclosed in square brackets so that they both can be plotted.

c:= x^2+(y-3)^2=25:
cplot:= [solve](c,y):

Notice the square brackets in the above command.

plot(cplot, x= -5..5, scaling= constrained);

How about this? I just made some modifications to your code. For each cylinder I pick two points and the radius at random. The points are the centers of the endcaps. Then I do a tubeplot of the line segment connecting the points.


x:=Generate(list(integer(range=0..20),100)): # random coordinate for x parameter
x1:= Generate(list(integer(range= 0..20), 100)):
y:=Generate(list(integer(range=0..20),100)): # random coordinate for y parameter
y1:= Generate(list(integer(range= 0..20), 100)):
z:=Generate(list(integer(range=0..20),100)): # random coordinate for z paramete
z1:= Generate(list(integer(range= 0..20), 100)):
R:=Generate(list(float(range=1..3),12)):  # random radius parameter

P:=(x,x1,y,y1,z,z1,R)-> [x+(x1-x)*t, y+(y1-y)*t, z+(z1-z)*t, radius= R]: # equation for one cylinder
S:=(x,x1,y,y1,z,z1,R)-> tubeplot(P(x,x1,y,y1,z,z1,R), t= 0..1, tubepoints= 20): # 3D plot in space


If you replace abs(x) with csgn(x)*x, then f(x) is analytic in a disk in the complex plane about x=1, and the taylor command (in M16) produces the expected result. This is equal to abs(x) for real x.

The fact that Maple (16) does not give a Taylor series expansion for sqrt(abs(x)) about x=1 shows that a bug has been corrected, not that a bug has been introduced.

Your original form [[1,2],[3,4]] is not a Vector, it is a list of lists. To get back to that form

convert(A1, listlist);

Addressing your other question, you simply need to take the transpose of A1 before converting:

convert(A1^+, listlist);

Here's another solution, which uses elementary number theory (in particular the Fundamental Theorem of Arithmetic) to substantially reduce the search space, and thus get the answer in under 0.1 seconds.

st:= time():

If we multiply each of a,b,c,d by 100, then the sum is 711, and the product is

N:= 711*100^3:

and now the problem is strictly about positive integers. Henceforth, a,b,c,d will only refer to these integerized values.

Each of a,b,c,d must be a divisor of N, so let's look at the prime factorization of N:

                           6    2    6     
                      (2)  (3)  (5)  (79)

There is a prime factor that only appears to the first power. That will speed this up a lot. Let's get the divisors of N, which will be our search space.

divs:= numtheory:-divisors(N):

Since the sum is 711, we restrict the search to divisors less than 711.

divs:= select(`\<`, divs, 711)

(Ignore the backslash in the above line. Maple ignores it, and the MaplePrimes editor in my web browser won't display the rest of the line without it.)

Exactly one of a,b,c,d must be a multiple of 79---we'll make it a---so we partition the remaining divisors based on that.

d79, divs:= selectremove(x-> x mod 79 = 0, divs):

Now loop through these sets. After each x is chosen, the remaining solutions must divide N/x, so we reduce the search space accordingly in each inner loop.

     local Na, divsa, divsb, Nb, a, b, c, d, sol;
     for a in d79 do
          Na:= N/a;
          divsa:= divs intersect numtheory:-divisors(Na);
          for b in divsa do
               Nb:= Na/b;
               divsb:= divsa intersect numtheory:-divisors(Nb);
               for c in divsb do
                   if a+b+c+Nb/c = 711 then sol[a,b,c]:= {a,b,c,Nb/c} fi
     convert(sol, set)

end proc
                          { {120, 125, 150, 316} }

Finally, divide each of those by 100 to get the desired answers. I put each solution in a set so that permutations would be condensed. If there was a solution with repeated values, it would appear as a set with fewer than four members, and we'd have to do a little work to figure out which values were repeated. But, there is no such solution.



In a separate run, I counted the number of executions of the innermost loop. It was 8520. I also tried the above without separating the multiple-of-79 divisors as special. Then I got 58,938 iterations in 0.109 seconds, so maybe it wasn't worth it to separate them.

A note on coding style: I use an anonymous procedure above, i.e. a procdeure with no name. I invoke the procedure immediately by placing () after its definition.

I changed your example procedure to one where the order of the arguments matters so that the example is more generally applicable.

myproc:= (a,b,c)-> a/b-c:


The `~` command below applies the procedure in "batch" form.

(myproc@op) ~ ([[d,e,f], [g,h,i]]);

Because of operator precedences, all the parentheses in the above command are necessary, unfortunately. Also, the arguments must be in lists [] rather than sets {} because the order matters. I think this command is fairly close to your desired syntax.

The above command is equivalent to the more traditional form

map(myproc@op, [[d,e,f], [g,h,i]]);


The op is used to convert lists, such as [d,e,f], to sequences, such as d, e, f; since myproc expects a sequence of arguments.

Example 1: Factor the first 29 odd 27-bit integers. First, the "old" way:

N:= 2^(2^7-1)+1:
B:= [seq](N+k, k= 0..2^9-1, 2):
CodeTools:-Usage(map(ifactor, B)):

memory used=1.12GiB, alloc change=212.68MiB, cpu time=18.76s, real time=21.10s

...and now using package Threads:

N:= 2^(2^7-1)+1:
B:= [seq](N+k, k= 0..2^9-1, 2):
CodeTools:-Usage(Threads:-Map(ifactor, B)):

memory used=1.23GiB, alloc change=0.53GiB, cpu time=33.50s, real time=8.97s


Example 2: Generate 214 random 27-bit primes. The old way:

N:= 2^(2^7-1):
Gen:= RandomTools:-MersenneTwister:-NewGenerator(range= N..2*N):
seeds:= [seq](Gen(), k= 1..2^14):
Primes:= CodeTools:-Usage(map(nextprime, seeds)):

memory used=2.76GiB, alloc change=327.83MiB, cpu time=27.50s, real time=27.50s

Primes[-1];  #Inspect last prime in list...


...and using Threads:

N:= 2^(2^7-1):
Gen:= RandomTools:-MersenneTwister:-NewGenerator(range= N..2*N):
seeds:= [seq](Gen(), k= 1..2^14):
Primes:= CodeTools:-Usage(Threads:-Map(nextprime, seeds)):

memory used=3.74GiB, alloc change=1.56GiB, cpu time=77.12s, real time=11.00s

Primes[-1];  #...just to verify that the two methods are doing the same computation.


Records are mutable, as the following shows:

A:= Record(a=1):
B:= Record(a=1):
T[A]:= 1: T[B]:= 2:

   table([B = 2, A = 1])

Compare that with what happens with an immutable structure, in this case an unevaluated function call (named `record`, just for fun):

A:= record(a=1):
B:= record(a=1):
T[A]:= 1: T[B]:= 2:

   table([record(a = 1) = 2])

But that doesn't mean that they absolutely can't be used with remember tables. If the records being compared are address identical, not just copies which "just happen to be" equal, then the remember table will recognize them. If just a few cases slip through unrecognized because they just happen to be equal, it won't ruin your recursion. On the other hand, if your algorithm relies on making copies of records (not just copying the address, or pointer), the remember table won't work.

Cache tables, remember tables, and just-plain tables all function like the tables in the examples above. The only difference that cache tables have is that the amount of memory that they use can be easily controlled.

First 359 360 361 362 363 Page 361 of 363