CHAPTER 2 1. Tables Everyone has seen tables of numbers. For example, consider the table shown below. In this table the numbers are car speeds. In each row, the speeds shown increase from left to right correspondingly with each second of acceleration. Thus, the first entry shows zero meters per second at the end of zero seconds, the second number shows the speed after one second, and the third shows the speed after two seconds. For the top row the acceleration is one meter per second each second. For the second row, the car's speed data is for a car that increases its speed by two meters per second each second, and in the third row the speeds are shown for a car that is accelerating at three meters per second per second. 0 1 2 0 2 4 0 3 6 In the case of tables of data like this, there are two variables. The data in each row correspond to a single value of one of the variables while the other variable is different for each entry. The same can be said of the columns, but the variable that is fixed in each row now changes as you go up or down, while the variable that changes in going from left to right in a row now is fixed as you go up or down in a column. Tables like the one above are also called "square matrices". A table such as the one above extended to include three seconds elapsed is rectangular. It would be called a 3X4 matrix. (3 rows and 4 columns). The square matrix above is a 3X3 matrix. The number of rows and the number of columns are called dimensions. In programs, a table variable is denoted by a name followed by two numbers in parenthesis that are separated by a comma. For example, you might pick just the name T for table. Then, in the program you would use T(i,j), where the value of i identifies a row and the value of j identifies a column. Also in the program you have to tell Chipmunk Basic the dimensions of the table, or matrix, right at the beginning. You do so for a 5X7 table with a line statement simply written DIM T(5,7) in one of the early numbered lines of your program. Actually, declaring the dimensions does not require your program to use all of its possible entries, but it allows the program to know what the maximum number of entries can be. Recall from the previous chapter that the DIM statement was used for a list---in that case it gave the maximum size for the list, and a list is really just a one column matrix. The following program illustrates the use of a table. This program considers the case of inventory control and disposition of products to customers. A shop has three items for sale that are priced at $25, $37, and $41. In one day the shop sells 8 of the cheapest item, 14 of the mid-priced item and 3 of the most expensive items. It sells different quantities during different periods of time during the day---the first two hours, the second two hours, the third two hours, and the closing two-hour period, these times being designated times 1,2,3, and 4,respectively. The shop owner would like a report for the day. A note in advance is that line 200 contains two statements separated by a colon. This is the means of making a multiple statement line and could also have been broken into two lines---say 200 next time 201 next item The way it is done below just saves space. Here is the program: 10 rem Report for the big boss on sales today! 20 rem The items sold in each time slot are in lines 1020-50 100 read m,n 110 rem m is the no. of time intervals & n is the no. of items 111 rem m & n are entered as data in line 1000 below 120 dim sp(3) 121 rem sp(i) is the sales price of item i 130 for item=1 to n step 1 140 read sp(item) 150 next item 160 dim table(m,n) 170 for time=1 to m step 1 180 for item=1 to n step 1 190 read table(time,item) 200 next item:next time 210 for time=1 to m step 1 220 s=0:s1=0 240 for item=1 to n step 1 250 s=s+sp(item)*table(time,item) 260 s1=s1+table(time,item) 270 next item 280 print "time period",time 290 print "number of items",s1 300 print "total sales=$";s 310 print 320 next time:print 1000 data 4,3:rem no. of times & items 1010 data 25,37,41:rem price of each item 1020 data 1,1,1:rem no. of each item sold in time1 1030 data 2,0,1:rem same for time period 2 1040 data 5,10,1:rem same for time period 3 1050 data 0,3,0:rem closing time period 9999 end OK, this is a pretty fancy program. Its output looks like this: time period 1 number of items 3 total sales=$103 time period 2 number of items 3 total sales=$91 time period 3 number of items 16 total sales=$536 time period 4 number of items 3 total sales=$111 So, here is the explanation of how it works. The rem statements tell you most of it. In line 120 we dimension the sales price as a list of three items. Lines 130-150 instruct the program to read the sales price data for each item. This is given in line 1010, as line 1000 has by then already been read as m and n, the dimensions of the table. We next officially dimension the table in line 160. Between lines 170 and 200 is the heart of a FOR-NEXT loop that steps through the time periods. It starts with time period 1 and these lines execute with that value for the time period. Then it loops back and does everything it is told to do between lines 170 and 200 all over again, but this time for time period 2. Line 180-270 is another FOR-NEXT loop (called a "nested" loop as it is nested within another loop--the time period loop). This loop cycles through the item numbers, starting, of course, with item 1. For each item line 140 reads the sales price table data starting with the first unused data line (line 1020 for the first item), and the next value of the item number directs it to read the next line of unused data (which for item 2 will be line 1030), etc. At this point all the data have been read by the program and calculations can begin. Lines 210-320 are a FOR-NEXT loop on the time periods. We initialize the variables for total sales (s) and number of items sold in each time period (s1) in line 220, which is a multiple-statement line for succinctness reasons. Lines 240-270 form a nested FOR-NEXT loop on the items. In line 250 we replace the initial value of s with s plus the product of the sales price and the particular table entry for which the time period and item number values are present at this point in the double loop. The next time through the nested loop, the table entry has been stepped to another item, and the values accumulate for s, i.e., for the total sales in the time period at hand. Note that the sales price times the number of items of that price that are sold is in fact the total sales of that item, and we are stepping through all the items, accumulating as we go. Similarly, the total number of items sold is accumulated for that time period in line 290. We then print out the time period and its totals before going on to the next time period as directed by line 320. The remaining lines are the data and end command (This is not needed, but some forms of BASIC need it and it is convenient to go ahead and include it--especially as we might want to change the program in a way that would require the end command--usually as a result of wishing to end the program if some condition warrants it.) If you want other totals in the program, you can add the following lines: 340 for item=1 to n step 1 350 s=0 360 for time=1 to m step 1 370 s=s+table(time,item) 380 next time 390 print "item";item,s 400 print "total sales=$";s*sp(item) 450 print 500 next item You should see for yourself what this does. 2. Subroutines Sometimes you use complicated formulas and you would like to use them in a convenient way. Maybe you would even like to use them in several programs. This is some of the purposes of subroutines, which are miniprograms within a larger program and which are commanded to execute by a "gosub" statement. At the end of a subroutine you must always put a "return" statement. This returns the program to the line it would have executed were it not for the gosub statement. Consider now the problem of adding two vectors in two dimensions. Here is a subroutine for adding them in any given number of dimensions. 6551 rem Subroutine for adding two vectors 6552 for i=1 to n step 1 6553 c(i)=a(i)+b(i) 6554 next i 6555 return The number n is specified in the master program as the number of dimensions before the subroutine is called. Also, the master program must know the components a(1), a(2),... of the vector A and the components b(1), b(2),... of vector B. Notice that an array, or list, is used for the vectors. The vector sum C has components which are each the sum of the corresponding components of A and B. So here is the whole program: 10 rem program to do vector algebra 50 print "This program uses 2 known vectors A and B" 60 print "You need to know their components." 70 print "The vector sum of the vectors A & B is the vector C" 80 input "How many dimensions are you considering? ";n 100 dim c(n):dim a(n):dim b(n) 200 input "What is the x component of vector A? ";a(1) 210 input "What is the y component of vector A? ";a(2) 300 input "What is the x component of vector B? ";b(1) 310 input "What is the y component of vector B? ";b(2) 400 gosub 6551 500 print "The x component of vector C is: ";c(1) 510 print "The y component of vector C is: ";c(2) 600 clength=sqr((c(1))^2+(c(2))^2) 700 print "The length of vector C is: ";clength 800 goto 9999 6551 rem Subroutine for adding two vectors 6552 for i=1 to n step 1 6553 c(i)=a(i)+b(i) 6554 next i 6555 return 9999 end The output is shown below for a very simple example. This program uses 2 known vectors A and B You need to know their components. The vector sum of the vectors A & B is the vector C How many dimensions are you considering? 2 What is the x component of vector A? 0 What is the y component of vector A? 1 What is the x component of vector B? 1 What is the y component of vector B? 0 The x component of vector C is: 1 The y component of vector C is: 1 The length of vector C is: 1.414214 The following is a subroutine that uses the random number generator of Chipmunk Basic. The quantity rnd in Chipmunk is a random number in the interval from 0 to 1. Similarly, 2*rnd gives a random number in the interval 0 to 2. It also uses the built-in function of Chipmunk written int(argument). The quantity int followed by some number in parenthesis (and serving as the argument) gives just the integer part of that number. The subroutine is: 3004 rem Subroutine for rolling dice 3005 dice1=int(6*rnd+1) 3006 dice2=int(6*rnd+1) 3007 dice=dice1+dice2 3008 return It is a good policy in subroutines (that you may use again) to use large numbers as line numbers and to choose some that are not likely to be used in other programs. Then you can fit them into most any program you like without renumbering the lines. In this subroutine, since each of the dice has 6 numbers of randomly appearing nature (one hopes!), the rnd is multiplied by six and the roll is the integer part of 6*rnd+1. That is, 6*rnd gives a random number in the interval from 0 to 6. This is so for each one of the pair and the total from rolling the dice is made in line 3008. The master program is given below: 10 rem dice game (craps) 20 print "If you roll a 7 or 11 on the 1st roll, you win" 30 print "If you roll a 2,3,or 12 on the 1st roll you lose." 40 print "For any other no. you must get that no. again." 50 print "But before 7 or 11 comes up." 60 print "Below are given the results of your 10 games!" 90 for game=1 to 10 step 1 100 gosub 3004 110 on int(dice-1) goto 400,400,150,150,150,550,150,150,150,550,400 150 outcome=dice 160 gosub 3004 170 if int(dice)=int(outcome) then goto 200 180 if int(dice)=7 then goto 300 190 goto 160 200 print "You are a winner for making the point!" 250 goto 600 300 print "You lose for not making your point." 350 goto 600 400 print "Tough--snake eyes,3, or 12--a 1st-roll loser." 500 goto 600 550 print " 7 or 11--A 1st-roll winner!" 600 next game 650 stop 3004 rem Subroutine for rolling dice 3005 dice1=int(6*rnd+1) 3006 dice2=int(6*rnd+1) 3007 dice=dice1+dice2 3008 return 9999 end Now there's a cute trick in line 110. First note that the "on" refers to the value of the integer part (in case you get round-off error--this is just good practice as there are cases in which that happens) of the dice roll minus 1. The "on" here directs the program to goto the nth line shown if the dice roll produces the result n+1. That is, if you roll a 2 (snake eyes), then the goto is to line 400--the loser line. If you roll a 3, then the goto is to the second line that is given in the list, i.e., also line 400 because 3 is a loser. If you roll a 4, then the 3rd entry in the line numbers is 150 and the goto is to this line, etc. Notice that the subroutine is then called to roll the dice again. Thus.the subroutine gives not only the 1st roll, but any more that are needed. This subroutine is pretty lame, but it shows the idea. 3. Files There are many occasions in which you have a set of data in some text document or create such a document. Then you may wish to call the data into a program that calculates something useful from the data. Let us suppose that you have the following set of data in a document in the Macintosh word processor SimpleText (or in TeachText for older Macs). 1,3,7,3 2,2,1,9 3,5,4,3 Suppose that the data have the following meaning. The first column identifies a type of food,i.e, food 1,food 2,food 3. The second column is the fraction of fat by weight in each food. The third column is the fraction of protein by weight in each food, and the third column is the fraction of carbohydrate by weight of each of the foods. For example, Food 2 has 9 grams carbohydrates in 100 grams. Such data are available from the U.S. Department of Agriculture database. The fractions do not add to unity as there is water and other nonnutrients in the foods. Make a document with just the above data in it typed in exactly with the given format (Use copy/paste if you like.). Name the document nutrients.st with the .st being the appropriate suffix identifying a data file to Chipmunk Basic. Put the document into the Chipmunk Basic folder. Now suppose that you wish to know the ratio of fat to the total of the protein and carbohydrates for each of the three foods. Here is the program to give you that information. 10 rem Food composition program 20 rem mf is the mass of fat in grams for 100 grams 30 rem mp is the mass of protein in grams for 100 grams 40 rem mc is the mass of carbohydrate in grams for 100 grams 70 print "Food No. ";"Ketogenic Ratio" 100 open "nutrients.st" for input as #1 110 input #1,lnn,mf,mp,mc 120 ratio= mf/(mp+mc) 200 print lnn,ratio 300 if int(lnn)=int(3) then goto 600 500 goto 110 600 close #1 999 end This program is a simple example of the kind used for parents of epileptic children on the ketogenic diet. The diet is a high-fat diet that has remarkable success in controlling seizures, so this is a "real-world" program. Line 70 prints the heading for the output of the program. Line 100 tells the program to open the document nutrients.st and start inputing the data as data file number 1. Notice that there are quotes around the document name. The data in the first row are read first. Line 110 tells the program the names of the variables that correspond in sequential order to the input. The name lnn is used for the line number and this is the food number in the list. The user must of course have a list of names of the foods with the foods numbered accordingly. Line 120 calculates the desired ratio for the data in the line at hand, and line 200 prints the corresponding result. Once all the data have been read, line 300 instructs Chipmunk to goto line 600 which closes the document. If the data are not al l read, the program moves to line 500 and is directed to read another line of the data in the document. If you wish to save the data output from some other program you have written, you can use a data file (document) to accept the data output. In this case, you would use a statement like open "datadoc.st" for output as file #3 or use whatever name you prefer and whatever file number is appropriate. After the calculations, say some which calculate the quantities x,y, and z, are carried out in the meat of the program you use a statement like print #3, x,y,z which takes your data and puts it into the document. From: f44@cosmail1.ctd.ornl.gov (Thomas L. Ferrell)