New Problems from Old-A Case Study

One of the best ways to develop new problem contexts is to take old, familiar problems and look at them in new ways. Developing alternate perspectives is as much art as science. However there are some general techniques. One of the simplest is taking an old war horse of a problem and producing a visual representation it and/or its solution. One almost always finds that this leads to new, interesting problems. Here is an example:

The lawn mowing problem

Problem: Sam can mow the lawn in 2 hours and Bill can mow it in 3. How fast can they mow it together?

Solution : The problem implicitly assumes that Sam and Bill can work independently. When this holds their rates add. Sam can mow one lawn in 2 hours so his rate is [Maple Math] lawn per hour. Similarly Bill has a rate of [Maple Math] lawn per hour. Together their rate is [Maple Math] lawn per hour so together they can mow one lawn in [Maple Math] hour. Similar problems with essentially the same solution can be stated for such things as two pipes filling a tank, two boys eating a pizza, etc. and of course the extension to more than two is no problem, with the assumption of independence of action any number of rates add. Traditional extensions don't go much further than considering more than two mowers, pipes, etc.

Visual problems arising from the lawn mowing problem.

There any number of ways in which we might create a visual representation of this problem. We could do something as simple as making three bricks whose lengths represent the time Sam, Bill, and the two together could mow the lawn. This would be a straightforward application of what we have already done but it wouldn't be very interesting. For instance, it would not reflect the visual image engendered by the original question. It would apply equally well to two pipes that could individually drain a tank in 2 and 3 hours. Moreover a static image would not convey the sense of time or the feeling of motion conveyed by the mowing of a lawn.

Problem: Let us start by trying to convey the notion of one individual mowing one lawn

Although our work has been in three dimensions up to now the two dimensional case of this problem is simpler and less consumptive of computing resources so we start there. First we need a lawn:

> v1:=[0,0]: v2:=[1,0]:
v3:=[1,1]: v4:=[0,1]:
lawn:=[v1,v2,v3,v4]:

>

> plots[polygonplot ](lawn,color=green, style=patch);

[Maple Plot]

>

A better lawn might have border or a more interesting shape but a simple, square lawn is a good place to start.

> [Maple OLE 2.0 Object]

ch6yard

We can vary the meaning of v1,v2,v3,v4 and have different lawns. We will want to use different colors to represent "unmown" and "mown" grass. Following what now a standard procedure we produce a word which produces a quadrilateral with specified vertices and color.

> lawn := proc (v1,v2,v3,v4, clr )
plots[polygonplot]([v1,v2,v3,v4],color=clr,style=patch,scaling=constrained )
end:

>

Now lets make a lawn that is 10 by 10 with the lower left corner at the origin and with "grass" 1 unit thick.

> L1:=lawn([0,0],[10,0],[10,10],[0,10], green):

> L1;

[Maple Plot]

>

If we want to shift this lawn so that its lower left corner is at [11,5] we can do it by brute force.

> L2:=lawn([0,0]+[11,5],[10,0]+[11,5],[10,10]+[11,5],[0,10]+[11,5], green):

>

Now display both lawns together.

> plots[display]([L1,L2]);

[Maple Plot]

>

If we decide that "unmown" grass is aquamarine and "mown" grass is green then we can indicate a partially mown lawn by laying a "mown" green plot on top of an "unmown" aquamarine one. We could just as easily have adjoining plots of different colors but our there will be less calculating further on if we do it this way.

> L1:=lawn([0,0],[10,0],[10,10],[0,10], aquamarine):
L2:=lawn([0,0] ,[4,0] ,[4,4] ,[0,4] , green):
plots[display]([L2,L1]);

[Maple Plot]

>

Note in the plots[display]([L2,L1]) the "L2,L1" order. This tells the computer to lay L1 down first and L2 on top of it. If we do things in the opposite order there will be a difference. Change the order and note the difference.

Now we have all we need to animate mowing a lawn - all we need to do is successively enlarge the "mown" portion until it covers the lawn. We "mow" it a strip at a time, combining the strips we have done into a single rectangle. First lets mow a strip.

Suppose we have a strip which is 2 units wide and 30 long and wish to animate mowing it with a lawnmower 2 units wide over the course of 10 units of time. We can draw this sketch. Letting "t" vary from 0 to 10 we note that the middle line in our sketch varies from the left edge to the right of the larger rectangle. Thinking of this as the boundary of our mown and unmown grass we can, for any value of t between 0 and 10 delineate the two.

[Maple OLE 2.0 Object]

ch6yard2

For instance if "t" were equal to "7" then we should be able to represent 70% of the strip as having been mowed. While we are at it lets use different colors for "mown" and "unmown" grass.

> t:=7;
L1:=lawn([0,0],[30 ,0],[30 ,2 ],[0,2 ], aquamarine):
L2:=lawn( [0,0], [30 *(t/10),0],[30 *(t/10),2 ],[0,2], green ):
plots[display]([L2,L1]);

[Maple Math]

[Maple Plot]

>

To animate mowing this strip all we need to do is run t from 0 to 10.

> movie:=NULL:
L1:=lawn([0,0],[30 ,0],[30 ,2 ],[0,2 ], aquamarine):
for t from 0 to 10 do
movie:=movie,plots[display]([lawn( [0,0], [30 *(t/10),0],[30 *(t/10),2 ],[0,2], green ),L1]):
od:

> plots[display]([movie],insequence=true,axes=none);

[Maple Plot]

Not overly spectacular but it does work. This strip is being mown from left to right but we will need also to mow from right to left. This simply means that we have to shift the mown portion to the right side of the rectangle rather than the left.

> movie:=NULL:
L1:=lawn([0,0],[30 ,0],[30 ,2 ],[0,2 ], aquamarine):
for t from 0 to 10 do
movie:=movie,plots[display]([lawn( [30 *(1-(t/10)),0], [30,0], [30,2], [30 *(1-(t/10)),2 ] , green ),L1]):
od:
plots[display]([movie],insequence=true,axes=none);

[Maple Plot]

>

The reader should note the simple changes which reversed the direction and make sure that he/she understands them.

A specific problem.

Now we have all of the tools we need to animate the mowing of a simple lawn.

Lets consider the problem of a 10 foot by 30 foot lawn which is to be mown in 20 minutes with a mower that cuts a path two feet wide. We have in mind a person mowing the lawn who starts in the lower, left corner and proceeds in the normal manner, reversersing direction each time he or she reaches the opposite edge. We want to make a picture of the lawn at each integer value of t from 0 to 20, a total of 21 frames, and to display them as a movie. We have already seen that there is no problem in keeping track of the mown and unmown portion of the strip the mower happens to be on. The only real problem is in how to know which direction the mower is moving at any particular time and how to represent that idea geometrically. Here is a statement of what we need to know as an elementary arithmetic problem. It is typical of the types of elementary problems we must solve in order to represent processes of this type.

Arithmetic Problem : A person is mowing a lawn which is Wdth units wide by Lngth units long . Starting at a corner and mowing along an edge of length Lngth she heads due east. Upon reaching the opposite side she reverses direction and mows another strip of length Lngth which is contiguous to the previous one. It takes TOTALTIME minutes to mow the lawn in " n " strips. At each time t between 0 and TOTALTIME, on which strip is she mowing, what direction is she headed, and what fraction of the strip she is on remains to be done?

[Maple OLE 2.0 Object]

ch6yard3

Solution: For a time t between 0 and TOTALTIME write [Maple Math] , a decimal number. Then "a" is an integer between 0 and n-1. At time "t" the mower is on the (a+1)st strip and the portion remaining to be done is "1 - 0.b". Since she is going east on the first strip (when a=0) and alternates directions after that she is going east when "a" is even and west when it is odd.

The Maple command for the integer part of a number, the greatest integer function, is called floor.

The remainder of an integer "m" upon division by two is m mod 2

> floor(3.2);
floor(3.2) mod 2;

[Maple Math]

[Maple Math]

>

With the notation of the Arithmetic Problem our original problem has Wdth=10, Lngth=30, n=5, TOTALTIME=20. Ultimately we will make a 21 frame animation but the cardinal rule is always develop an individual frame first. We start with, say, t=9. then for this frame

> t:=9; n:=5; TOTALTIME:=20;Wdth:=10; Lngth:=30;
a:= floor(t*n/TOTALTIME);
b:=t*n/TOTALTIME - a;
a;

[Maple Math]

[Maple Math]

[Maple Math]

[Maple Math]

[Maple Math]

[Maple Math]

[Maple Math]

[Maple Math]

>

This tells us that the third strip is being mown, moving east (since "a" is even). One forth of the strip has been mown and 3/4 remains to be mown. Now we can animate the lawn being mown. Each frame correesponds to a value of t from 0 to TOTALTIME. For the frame at time t we need to:

1. Calculate which strip we are mowing, the direction and what portion of the strip has been mown.

2. Make a rectangle green MOWN consisting of all complete strips mown.

3. Make a green rectangle STRIPMOWN consisting of the portion of the current strip that has been mown then the frame is [STRIPMOWN, MOWN, UUNMOWN] where UNMOWN is the complete lawn colored aquamarine.

Here is a first try at the code

> TIME:=9; NUMSTRIPS:=5; TOTALTIME:=20;Wdth:=10; Lngth:=30;movie:=NULL:

[Maple Math]

[Maple Math]

[Maple Math]

[Maple Math]

[Maple Math]

>

> YARD:=lawn([0,0],[30 , 0],[30 ,10 ],[ 0,10 ],aquamarine):
for TIME from 0 to TOTALTIME do
WHICHSTRIP:= floor(NUMSTRIPS*TIME/TOTALTIME);
FRACSTRIP:=TIME*(NUMSTRIPS/TOTALTIME) - WHICHSTRIP;
MOWN:=lawn( [0,0],[30,0],[30,2*WHICHSTRIP],
[0,2*WHICHSTRIP] , green):
if WHICHSTRIP mod 2 = 0 then
frame:=plots[display]([MOWN, lawn( [0,2*(WHICHSTRIP )] ,
[30 *FRACSTRIP,2*(WHICHSTRIP )], [30*FRACSTRIP,
2*(WHICHSTRIP+1) ], [0,2*(WHICHSTRIP+1)], green ) ],YARD):
else
frame:=plots[display]([MOWN, lawn( [30 *(1-FRACSTRIP),
2*(WHICHSTRIP )], [30,2*(WHICHSTRIP )],
[30,2*(WHICHSTRIP+1)], [30 *( 1- FRACSTRIP),
2*(WHICHSTRIP+1) ] , green ) ],YARD):
fi:
movie:=movie,frame:
od:

>

> plots[display]([movie],insequence=true,axes=none);

[Maple Plot]

>

This works pretty well but but we need to test it by varying the values of the parameters. Lets check it with some new ones. As is our procedure we make another copy of the working code rather than tampering with it.

> NUMSTRIPS:=7; TOTALTIME:=25;Wdth:=37; Lngth:=30;

[Maple Math]

[Maple Math]

[Maple Math]

[Maple Math]

>

> movie:=NULL:
YARD:=lawn([0,0],[30 , 0],[30 ,10 ],[ 0,10 ], aquamarine):
for TIME from 0 to TOTALTIME do
WHICHSTRIP:= floor(NUMSTRIPS*TIME/TOTALTIME);
FRACSTRIP:=TIME*(NUMSTRIPS/TOTALTIME) - WHICHSTRIP;
MOWN:=lawn( [0,0],[30,0],[30,2*WHICHSTRIP],
[0,2*WHICHSTRIP] ,green): if WHICHSTRIP mod 2 = 0 then
frame:=plots[display]([MOWN, lawn( [0,2*(WHICHSTRIP )] ,
[30 *FRACSTRIP,2*(WHICHSTRIP ) ],
[30*FRACSTRIP,2*(WHICHSTRIP+1) ],
[0,2*(WHICHSTRIP+1)], green ) ],YARD):
else
frame:=plots[display]([MOWN, lawn(
[30 *( 1-FRACSTRIP),2*(WHICHSTRIP )],
[30,2*(WHICHSTRIP )], [30,2*(WHICHSTRIP+1)],
[30 *( 1- FRACSTRIP),2*(WHICHSTRIP+1) ] , green ) ],YARD):
fi:
movie:=movie,frame:
od:

>

> plots[display]([movie],insequence=true,axes=none);

[Maple Plot]

>

Hmmm.... little problem here. What happened caused it to work for one set of data and not for another is that we had "hard coded" some "magic numbers". One of them was "2" the width of the strip. We told the computer to mow a 37 foot wide lawn in 7 strips two foot wide strips. It got confused. We correct that by letting ir calculate the width of its mower as the ratio of the width of the lawn to the number of strips.

> movie:=NULL:
YARD:=lawn([0,0],[30 , 0],[30 ,10 ],[ 0,10 ], aquamarine):
MRWDTH:=Wdth/NUMSTRIPS:
for TIME from 0 to TOTALTIME do
WHICHSTRIP:= floor(NUMSTRIPS*TIME/TOTALTIME);
FRACSTRIP:=TIME*(NUMSTRIPS/TOTALTIME) - WHICHSTRIP;
MOWN:=lawn( [0,0],[30,0],[30,MRWDTH*WHICHSTRIP],
[0,MRWDTH*WHICHSTRIP] ,green):
if WHICHSTRIP mod 2 = 0 then
frame:=plots[display]([MOWN, lawn( [0,MRWDTH*(WHICHSTRIP )] ,
[30 *FRACSTRIP,MRWDTH*(WHICHSTRIP )],
[30*FRACSTRIP,MRWDTH*(WHICHSTRIP+1)],
[0,MRWDTH*(WHICHSTRIP+1)], green ) ],YARD):
else
frame:=plots[display]([MOWN, lawn(
[30 *( 1-FRACSTRIP),MRWDTH*(WHICHSTRIP )],
[30,MRWDTH*(WHICHSTRIP )], [30,MRWDTH*(WHICHSTRIP+1)],
[30 *( 1- FRACSTRIP),MRWDTH*(WHICHSTRIP+1) ] , green ) ], YARD):
fi:
movie:=movie,frame:
od:

>

> plots[display]([movie],insequence=true,axes=none);

[Maple Plot]

>

Pretty close now - we forgot the other "magic numbers" "30" and "10" in the code. They were the length and width of our original lawn. All we have to do is substitute the variables "Wdth" and "Lngth" for them:

> movie:=NULL:
YARD:=lawn([0,0],[Lngth , 0],[Lngth ,Wdth ],[ 0,Wdth ], aquamarine):
MRWDTH:=Wdth/NUMSTRIPS:
for TIME from 0 to TOTALTIME do
WHICHSTRIP := floor(NUMSTRIPS*TIME/TOTALTIME);
FRACSTRIP := TIME*(NUMSTRIPS/TOTALTIME) - WHICHSTRIP;
MOWN := lawn( [0,0],[Lngth,0],[Lngth,MRWDTH*WHICHSTRIP],
[0,MRWDTH*WHICHSTRIP] ,green):
if WHICHSTRIP mod 2 = 0 then
frame := plots[display]([MOWN, lawn(
[0,MRWDTH*(WHICHSTRIP )] ,
[Lngth *FRACSTRIP,MRWDTH*(WHICHSTRIP )],
[Lngth*FRACSTRIP,MRWDTH*(WHICHSTRIP+1)],
[0,MRWDTH*(WHICHSTRIP+1)], green ) ],YARD):
else
frame := plots[display]([MOWN, lawn(
[Lngth *( 1-FRACSTRIP),MRWDTH*(WHICHSTRIP )],
[Lngth,MRWDTH*(WHICHSTRIP )],
[Lngth,MRWDTH*(WHICHSTRIP+1)],
[Lngth *( 1- FRACSTRIP),MRWDTH*(WHICHSTRIP+1) ] ,
green ) ],YARD):
fi:
movie:=movie,frame:
od:

>

> plots[display]([movie],insequence=true,axes=none);

[Maple Plot]

>

This works pretty well. The reader will have noticed the small "antenna" that sprouts at the end of the mowing. In some sense its a "ghost" mower waiting to start a strip thats not there. To look for it change the loop in the code to run from TIME=0 to TIME = TOTALTIME -1 (one less frame) and see what happens. This makes it apparent that the artifact is generated in the last frame. We want the final view to be a completely mown lawn anyhow so we just modify the code accordingly.

> movie:=NULL:
YARD:=lawn([0,0],[Lngth , 0],[Lngth ,Wdth ],[ 0,Wdth ], aquamarine):
MOWEDYARD:=lawn([0,0],[Lngth , 0],[Lngth ,Wdth ],[ 0,Wdth ], green):
MRWDTH:=Wdth/NUMSTRIPS:
for TIME from 0 to TOTALTIME-1 do
WHICHSTRIP:= floor(NUMSTRIPS*TIME/TOTALTIME);
FRACSTRIP:=TIME*(NUMSTRIPS/TOTALTIME) - WHICHSTRIP;
MOWN:=lawn( [0,0],[Lngth,0],[Lngth,MRWDTH*WHICHSTRIP],
[0,MRWDTH*WHICHSTRIP] ,green):
if WHICHSTRIP mod 2 = 0 then
frame:=plots[display]([MOWN, lawn( [0,MRWDTH*(WHICHSTRIP )] ,
[Lngth *FRACSTRIP,MRWDTH*(WHICHSTRIP )],
[Lngth*FRACSTRIP,MRWDTH*(WHICHSTRIP+1)],
[0,MRWDTH*(WHICHSTRIP+1)], green ) ],YARD):
else
frame:=plots[display]([MOWN, lawn(
[Lngth *( 1-FRACSTRIP),MRWDTH*(WHICHSTRIP )],
[Lngth,MRWDTH*(WHICHSTRIP )],
[Lngth,MRWDTH*(WHICHSTRIP+1)],
[Lngth *( 1- FRACSTRIP),MRWDTH*(WHICHSTRIP+1) ] ,
green ) ],YARD):
fi:
movie:=movie,frame:
od:
LASTframe:=MOWEDYARD:
movie:=movie,LASTframe:

>

> plots[display]([movie],insequence=true);

[Maple Plot]

>

A lawn mowing word

Finally, we make this into a procedure which accepts the dimensions of a lawn, the number of strips, and the total time it takes to mow it (i.e. the number of frames in the movie) and returns a movie of that lawm being mowed in that time.

> lawnmower:=proc(Lngth, Wdth, TOTALTIME, NUMSTRIPS)
local movie, YARD, MOWEDYARD, MRWDTH, TIME, WHICHSTRIP, FRACSTRIP, MOWN, frame, LASTframe;
Digits :=4:
movie:=NULL:
YARD:=lawn([0,0],[Lngth , 0],[Lngth ,Wdth ],[ 0,Wdth ], aquamarine):
MOWEDYARD:=lawn([0,0],[Lngth , 0],[Lngth ,Wdth ],[ 0,Wdth ], green):
MRWDTH:=Wdth/NUMSTRIPS:
for TIME from 0 to TOTALTIME-1 do
WHICHSTRIP:= floor(NUMSTRIPS*TIME/TOTALTIME);
FRACSTRIP:=TIME*(NUMSTRIPS/TOTALTIME) - WHICHSTRIP;
MOWN:=lawn( [0,0],[Lngth,0],[Lngth,MRWDTH*WHICHSTRIP],
[0,MRWDTH*WHICHSTRIP] ,green):
if WHICHSTRIP mod 2 = 0 then
frame:=plots[display]([MOWN, lawn( [0,MRWDTH*(WHICHSTRIP )] ,
[Lngth *FRACSTRIP,MRWDTH*(WHICHSTRIP )],
[Lngth*FRACSTRIP,MRWDTH*(WHICHSTRIP+1)],
[0,MRWDTH*(WHICHSTRIP+1)], green ) ],YARD):
else
frame:=plots[display]([MOWN, lawn(
[Lngth *( 1-FRACSTRIP),MRWDTH*(WHICHSTRIP )],
[Lngth,MRWDTH*(WHICHSTRIP )],
[Lngth,MRWDTH*(WHICHSTRIP+1)],
[Lngth *( 1- FRACSTRIP),MRWDTH*(WHICHSTRIP+1) ] ,
green ) ],YARD):
fi:
movie:=movie,frame:
od:
LASTframe:=MOWEDYARD:
movie:=movie,LASTframe:
plots[display]([movie],insequence=true):
end:

> lawnmower(38,21,20,10); :

[Maple Plot]

>

Two Mowers mowing side by side.

At this time we can momentarily revisit the original problem, and seek an animation of both mowers mowing.

Problem : Make a movie of Sam and Bill mowing their respective lawns which shows two lawns side by side. Both Sam and Bill should start mowing at the beginning of the movie. The movie should end when the slowest mower completes his lawn.

Let us assume that Sam and Bill who stared this are both around and we want to stage a "race" with them mowing side by side lawns. Our " lawnmower" does the two separately. The interesting problem will be to make them do it side by side. First we want to modify our "lawnmower " to take separately the number of time units the mower needs to mow the lawn, MOWINGTIME and the number of time units the movie is to represent MOVIELENGTH. If the number of movie units is greater than the number of units it takes to mow the lawn then the movie should show the lawn being mowed in the correct number of units and should simply show a mown lawn for the remaining frames. If there are not enough movie time units then the movie should end with the lawn incompletely mown. Of course we want to do this by adapting our "lawnmower code".

What was originally our TOTALTIME we are now calling MOVIELENGTH and the MOWINGTIME is the number of frames actually needed to complete the lawn. If MOWINGTIME is less than the MOVIELENGTH then the mower finishes early in the movie and the last few frames show a mown lawn. If the MOWINGTIME is greater than the MOVIELENGTH then the movie runs out of frames before the lawn is completely mown. What we want to do is use MOVIELENGTH in some places where we use TOTALTIME in the original code and MOWINGTIME in others. We will certainly need to change our LASTframe because it now ends the movie with a completely mown lawn. Now if the movie runs out we want to see the unmown remainder. The reader should note the very small number of changes we have made to the working code and should be sure to understand what each is doing.

> lawnmower2:=proc(Lngth, Wdth, MOWINGTIME, MOVIELENGTH, NUMSTRIPS)
local movie, YARD, MOWEDYARD, MRWDTH, TIME, WHICHSTRIP, FRACSTRIP, MOWN, frame, LASTframe;
movie:=NULL:
YARD:=lawn([0,0],[Lngth , 0],[Lngth ,Wdth ],[ 0,Wdth ], aquamarine):
MOWEDYARD:=lawn([0,0],[Lngth , 0],[Lngth ,Wdth ],[ 0,Wdth ], green):
MRWDTH:=Wdth/NUMSTRIPS:
for TIME from 0 to MOVIELENGTH-1 do
if TIME <=MOWINGTIME then
WHICHSTRIP:= floor(NUMSTRIPS*TIME/MOWINGTIME);
FRACSTRIP:=TIME*(NUMSTRIPS/MOWINGTIME) - WHICHSTRIP;
MOWN:=lawn([ 0,0],[Lngth,0],[Lngth,MRWDTH*WHICHSTRIP],
[0,MRWDTH*WHICHSTRIP] ,green):
if WHICHSTRIP mod 2 = 0 then
frame:=plots[display]([MOWN, lawn( [0,MRWDTH*(WHICHSTRIP )] , [Lngth *FRACSTRIP,MRWDTH*(WHICHSTRIP )], [Lngth*FRACSTRIP,MRWDTH*(WHICHSTRIP+1) ], [0,MRWDTH*(WHICHSTRIP+1)], green ) ],YARD):
else
frame:=plots[display]([MOWN, lawn(
[Lngth *( 1-FRACSTRIP),MRWDTH*(WHICHSTRIP )],
[Lngth,MRWDTH*(WHICHSTRIP )],
[Lngth,MRWDTH*(WHICHSTRIP+1)],
[Lngth *( 1- FRACSTRIP),MRWDTH*(WHICHSTRIP+1) ] ,
green ) ],YARD):
fi:
movie:=movie,frame:
else
movie:=movie,MOWEDYARD:
fi:
od:
if MOVIELENGTH >= MOWINGTIME then LASTframe:=MOWEDYARD:
movie:=movie,LASTframe:
plots[display]([movie],insequence=true):
fi:
end:

>

> lawnmower2(30,20,7,20,10);

[Maple Plot]

>

Now if we want side-by-side mowers we need different lawns. This we need to introduce a shift which moves the original lawn to a different location. BEFORE we start directly into this however we examine what we have done and notice that the only way that coordinates are used is in the word "lawn". Thus if we simply adapt the word "lawn" to accept a shift (it probably should have had one anyhow). We are also changing our porgram so that it returns the movie rather than plays it. This is because we are going to want to run two movies at the same time so we will need to "splice" them together.

> lawnwithshift := proc (v1,v2,v3,v4, clr, shift)
plots[polygonplot]([v1+shift,v2+shift,v3+shift,v4+shift],
color=clr,style=patch,scaling=constrained ) end:

>

> lawnmower3:=proc(Lngth, Wdth, MOWINGTIME, MOVIELENGTH,
NUMSTRIPS,SHIFT)
local movie, YARD, MOWEDYARD, MRWDTH, TIME, WHICHSTRIP,
FRACSTRIP, MOWN, frame, LASTframe;
movie:=NULL:
YARD:=lawnwithshift([0,0],[Lngth , 0],[Lngth ,Wdth ],[ 0,Wdth ],
aquamarine,SHIFT):
MOWEDYARD:=lawnwithshift([0,0],[Lngth , 0],[Lngth ,Wdth ],[ 0,Wdth ],
green,SHIFT):
MRWDTH:=Wdth/NUMSTRIPS:
for TIME from 0 to MOVIELENGTH-1 do
if TIME <=MOWINGTIME then
WHICHSTRIP:= floor(NUMSTRIPS*TIME/MOWINGTIME);
FRACSTRIP:=TIME*(NUMSTRIPS/MOWINGTIME) - WHICHSTRIP;
MOWN:=lawnwithshift(
[0,0],[Lngth,0],[Lngth,MRWDTH*WHICHSTRIP],
[0,MRWDTH*WHICHSTRIP] ,green,SHIFT):
if WHICHSTRIP mod 2 = 0 then
frame:=plots[display]([MOWN, lawnwithshift( [0,MRWDTH*(WHICHSTRIP )] ,
[Lngth *FRACSTRIP,MRWDTH*(WHICHSTRIP )],
[Lngth*FRACSTRIP,MRWDTH*(WHICHSTRIP+1) ],
[0,MRWDTH*(WHICHSTRIP+1)], green,SHIFT ) ],YARD):
else
frame:=plots[display]([MOWN, lawnwithshift(
[Lngth *( 1-FRACSTRIP),MRWDTH*(WHICHSTRIP )],
[Lngth,MRWDTH*(WHICHSTRIP )],
[Lngth,MRWDTH*(WHICHSTRIP+1)],
[Lngth *( 1- FRACSTRIP),MRWDTH*(WHICHSTRIP+1) ] ,
green,SHIFT ) ],YARD):
fi:
movie:=movie,frame:
else
movie:=movie,MOWEDYARD:
fi:
od:
if MOVIELENGTH >= MOWINGTIME then
LASTframe:=MOWEDYARD:
movie:=movie,LASTframe:plots[display]([movie],insequence=true):
fi:
[movie];
end:

>

> MOVIE:=lawnmower3(30,20,13,20,10,[32,0]):
plots[display]( MOVIE,insequence=true);

[Maple Plot]

>

Now lets assume that Sam and Bill are next door neighbors with idential 20 by 30 lawns. They each have a lawnmower which will mow their lawn in 7 strips. Sam can mow his lawn in 15 time units and Bill can mow his in 30. We can view each of them mowing his lawn with what we have:

> SAMMOWING:=lawnmower3(30,20,15,15,7,[0,0]):
plots[display](SAMMOWING,insequence=true):

>

> BILLMOWING:=lawnmower3(30,20,30,30,7,[32,0]):
plots[display](BILLMOWING,insequence=true);

[Maple Plot]

>

If we are going to watch both of them we want to run the movie for the length of time it takes the slowest person to do the job. Thus we need to make Sam's movie run 30 units.

> SAMMOWING:=lawnmower3(30,20,15,30,7,[0,0]):
plots[display](SAMMOWING,insequence=true);

[Maple Plot]

>

Now we have two movies of the same length. Check that with nops.

> nops(SAMMOWING); nops(BILLMOWING);

[Maple Math]

[Maple Math]

>

So now we can view Sam and Bill mowing their lawns side by side if we can solve the problem of viewing two movies at the same time.

Problem : (Movie splicing problem). Given two movies (as lists of plots) how can we view them simultaneously?

Solution: We use seq. Each of the two movies is simply a list of plot structures. We simply want to make a new list in which the ith element of the new list is the display of both the ith elements of each list. We may as well illustrate on the ones we have.

> MOWINGSIDEBYSIDE:=seq(plots[display]([SAMMOWING[i],BILLMOWING[i]]), i=1..nops(SAMMOWING)):

>

> plots[display]([MOWINGSIDEBYSIDE],insequence=true);

[Maple Plot]

>

Exercises

Exercise : Suppose A and B are rectangular tanks with identical dimensions, only B is below A and rotated 90 degrees. At a certain time A is full and B is empty, then the valve between them is opened and all the fluid flows into B at a constant rate determined by the valve. Make a 20 frame movie showing the fluid level in each tank with A full at the beginning and B full at the end.

Beginning of Solution:

We aren't given the dimensions of the tanks so we will assume some. The spacing isn't given either, nor the orientations. In this case its our job to make some reasonable assumptions. This is basically a two dimensional problem so we will let the tanks be one unit thick. The side view would look the same regardless of how thick they were. Here is a diagram:

[Maple OLE 2.0 Object]

ch6tanks

There isn't any mathenatical difference between the description of a "lawn" and the lateral view of a tank so we use our lawn procedure.

> lawn := proc (v1,v2,v3,v4, clr )
plots[polygonplot]([v1,v2,v3,v4],color=clr,style=patch,scaling=constrained ) end:

>

Our time is to run from t=0 to t=19 (20 frames) so at time t in this range tank B is t/19 full while tank A is (1-t/19) full. This means that at time t between 0 and 19 the fluid level of tank B is at 10*t/19 and that at tank A is at 37-25*t/19. Thus the fluid in tank A is described by

lawn([0,0],[25,0], [25,10*t/19],[0,10*t/19], red);

and that in tank B is described by

lawn([15,12],[25,12], [25,37-25*t/19],[15,37-25*t/19], red);

A first approximation to our basic movie is:

> movie:=NULL: for t from 0 to 19 do
frame:= plots[display]([ lawn([0,0],[25,0], [25,10*t/19],[0,10*t/19], red), lawn([15,12],[25,12], [25,37-25*t/19],[15,37-25*t/19], red)] ):
movie:=movie,frame: od:

>

> plots[display]([movie],insequence=true);

[Maple Plot]

>

a. Modify the basic movie so that the complete tanks are there - not just the fluid.

b. Modify the movie so that the color of the fluid changes as if moves from tank A to tank B.

c. Add the pipe connecting the two tanks to the movie. Have the pipe full thorugh the last (t=19) frame of the current movie then add a new last frame (t=20) in which the pipe is empty.

Exercise : Suppose there are three tanks A,B,C arranged as in the picture. The volumes of tanks A and B are equal to that of tank C. When tank A is empty and C is full and the valve between A and C is open then tank A will fill in 20 minutes. When tank B is empty and C is full and the valve between B and C is open then tank B will fill in 35 minutes. If both tanks A and B are empty and tank full is empty, how long will it take for tank C to empty and how much will be in each of tanks A and B at that time?

[Maple OLE 2.0 Object]

ch63tanks

Exercise : Suppose there are three tanks A,B,C arranged as in the picture. The volumes of tanks A and B are equal to half that of tank C. When tank A is empty and C is full and the valve between A and C is open then tank A will fill in 20 minutes. When tank B is empty and C is full and the valve between B and C is open then tank B will fill in 35 minutes. If both tanks A and B are empty and tank full is empty, how long will it take for both tanks A and B to fill up? Animate your answer.

[Maple OLE 2.0 Object]

ch6tanksABC

Exercise : Suppose there are three tanks A,B,C arranged as in the picture. The volumes of tanks A and B are equal to half that of tank C. When tank A is full and tanks A and C are empty all of the fluid in tank A will flow into tank C in 20 minutes. When tank B is full and tanks A and C are empty all of the fluid in tank B will flow into tank C in 35 minutes. If both tanks A and B are full and tank C is empty, how long will it take for tanks A and B to fill tank C? Animate your answer.

[Maple OLE 2.0 Object]

ch6tanks4

Exercise : Modify the lawnmower code to accept the dimensions of the lawn and the width if the mower rather than the number of strips. Have it then calculate the number of strips and have it deal rationally with what happens if the number of strips is not a whole number. This should be a reasonable thing for a real person to do when mowing such a lawn.

Exercise : Suppose Larry, Curley, and Moe are neighbors with identical 10 by 10 square lawns. It takes Larry 20 minutes to mow his lawn, Curley takes 15, and Moe 10. Make a movie of all three mowing their lawns, starting at the same time.

Table of Contents