Physics 230 -- Lab 7 (Programming II)

Fall 2015 - Transtrum

Labs developed by John S. Colton, BYU Physics & Astronomy, based in part on past labs by Branton Cambell and Steve Turley

Now that you understand the basics of Boolean logic, conditional statements, looping, and local vs. global variables, we can do some real programming!

Clear["`*" ]

Review

Local vs.Global variables

The last lab introduced you to the differences between local and global variables. To quickly review: a global variable is one that can be accessed from anywhere; a local variable is one that can only be used in a much more limited fashion--only inside a particular function, for example. Using local variables will prevent you from unintentionally modifying a global variable that might need to be used in a different part of your Mathematica notebook. In fact, a local variable can even be given the very same name as a global variable, and the global variable will remain untouched. 

Even though the concept of local variables may still seem new to you, you have already seen local variables several times this semester, for example as iterators in loop structures like Table, Sum, and Do.  Evaluate the cell below, and observe that the local variable i inside the loops does not interact with global variable i on the outside.

i = 3;

Table[i^2,{i,1,10}]
Sum[i^2,{i,1,10}]
Do[Print[i],{i,1,10}]

i

Modules

Take a moment to review the information on Modules at the end of last week’s lab. To summarize: a Module is what most computer people would call a program. When used with  :=  and a function definition, it takes arguments, does calculations on them often using loops and conditionals, can (and should!) employ local variables in the process, and returns a value if desired. 

For example, this program curves a list of student scores. You give it the list of scores and the desired average. It computes the average of the list you give it, and shifts all of the scores by some amount such that the new average is what you want.

changescores[oldlist_List, desiredave_]:=Module[{oldave,shift},
oldave=Mean[oldlist];  (* write your Module commands on separate lines like this!! *)
shift=desiredave-oldave;
oldlist+shift //N
]

(* let's test it out *)
listofscores={74,80,22,95,86,86,99,76}
Mean[%] //N
newlist=changescores[listofscores, 80] 
Mean[%]

Basic Debugging

The most frustrating situations in computer programming are undoubtedly when your program doesn’t work the way you think it should, and you have to figure out why. This type of troubleshooting is called “debugging” the program, i.e. getting rids of the “bugs”, or flaws in your logic. On the other hand, when you fix the bugs it’s very satisfying!

My top three suggestions

1. Don’t do too much at once. The number one issue I have seen with students’ programs is that they often try to do too much at once. Instead of trying to do several commands at once, break your program down into simpler commands, and make sure that each command works by itself the way you expect before incorporating it into a Module.

2. Use Print, liberally. The Print function is the easiest way to see what’s going on inside your Module once you start stringing several commands together. If things don’t work the way you expect, insert Print commands in several places to see what values your local variables have at various stages of the calculation. That allows you to track down where the break-down in logic is occurring. 

3. Test your programs throroughly. Once you think your program is working, test it out with an input that has an easily predicted output. For example, if you are writing a function to sort an array in numerical order (the extra credit assignment, below), test it with something like {1,2,4,3,5}, where the output should obviously be {1,2,3,4,5}. And then test it with {5,4,3,2,1}. And so forth. Only trust your program after you have fully tested it with a variety of inputs that produce outputs you can easily predict.

Interrupt

Although Print is the quick and dirty way of seeing the values of the variables as your program is proceeding, it is not the only way. A perhaps more elegant method is to use an Interrupt command. Interrupt[ ] pauses the program temporarily when it’s reached in the program, and if you click on “Enter Subsession”, you can enter commands while it’s paused--which can include testing the current values of local variables. Try it out here... normally the value of “n” in a Do loop like this is inaccessible. But when you interrupt the loop and enter into a subsession, you can type in “n” to see what its current value is.

Do[
If[n==5,Interrupt[]];  (* As with Module, I recommend you write your Do loop commands on separate lines! *)
Print[n]
,{n,1,10}];

n

Return[]

To exit the subsession and allow the program to complete, type Return[ ]. While inside the subsession, the “Running...” indicator in the status bar at the top of this window reminds you that the original calculation is still waiting.

A Word On Efficiency

As you've no doubt noticed, there are usually many different ways to solve a given problem in Mathematica. Up until now it typically hasn’t really mattered which route you take. However, when you do more and more complicated programming, it may matter quite a bit. In my lab, for example, we have the equivalent of ~15,000 lines of code in programs we’ve written to interact with and control the equipment in the lab. We’re editing and adding to it continually. If we don’t use clear and efficient methods, things can quickly devolve in a jumbled mess. This is termed spaghetti code. And if the programs don’t run speedily, we could be forced to waste time unnecessarily while the computer goes about its tasks.

With so many different ways to do things, how do you decide which way is best?  Here are four guiding principles. They apply to all programming languages, not just Mathematica.

1. You should choose an approach which is as clear as possible both to you and to others who may use your program later. Explain what you were thinking by leaving comments via (*  *) inside the program.

2. If you need to do a similar thing multiple times in your code, first define a function to do it and then call that function wherever needed. That way, if you later find a problem with the function and need to change it, you only have to do so in one place. 

3. If there are already built-in Mathematica functions that do what you want to do, it will probably be faster and clearer to use the built-in functions than it would be to write your own function. If you’re not sure whether a particular function is already exists but think it might, it’s worth your time to do a quick search.

4. One way of accomplishing a task may use up dramatically more computer memory or computing time than another way.  If the time your program takes to run becomes long enough to be noticable, or if the memory requirements limit what you can calculate, consider alternate approaches that are less computationally demanding.

Additionally, here’s a well-written blog post on writing fast code in Mathematica. I have found several of the tips helpful. You may not understand everything there, but some principles may stick in your mind for times when speed becomes an issue for you.

On the advantage of using built-in functions

Here’s a simple example of why built-in functions are nearly always better than functions you create yourself, adapted from point #10 of that blog post. Suppose you want to create a function which adds up all of the elements of a list. Here’s an obvious way to do that, that I wrote. I simply used a running total to keep track of the sum as the program goes through the list elements one by one.

adduplist[p_]:=Module[{runningtotal=0},
Do[
runningtotal+=list[[i]]  (* adds the current list element to the running total *)
,{i,1,Length[list]}];
runningtotal
]

Let’s use my function to add up the numbers from 1 up to 2 million.

list=Range[2000000]; (* here's the list of numbers from 1 to 2 million *)
adduplist[list] //Timing   (* adding them up with my special function; takes a few seconds *)

It took 4.8 seconds on my office computer. 

Now, it just so happens that Mathematica already has a built-in function designed to do exactly that. It’s called the Total function; we’ve used it in one or two previous labs. Let’s try adding up the list elements using Total instead of my own function:

Total[list] //Timing

It took 0.016 seconds on my office computer. That’s 300x faster!! (Your results may vary.)

You can imagine the dramatic difference you’d see if you needed to do that task over and over during the course of some extended calculation.

Side note: Why it’s faster: The blog post explains that the Total function is so much faster mainly because it goes about the adding process much more efficiently. Instead of doing 2 million additions one by one, like my function does, it does something like this: (1) organize the numbers into groups of two. (2) Add up all the pairs. (3) Organize the results into pairs of numbers. (4) Add them all up. (5) Organize those results into pairs, and add them up. (6) Repeat until there is one final pair left, then when you add that pair together the result is the sum of the entire list. If you follow through the logic behind doing things that way, it still has to do 2 million additions--but fewer of them involve very big integers, and so, on average, they are much quicker to do. 

I tell you that not so that you will know how to do lots of additions quickly, but so that you will appreciate the thought the Mathematica developers put into their built-in functions.

More Programming Assignments Using Module

Use a Module to do each of these tasks, even though the simpler ones could probably be done outside of a Module.

Assignment 1. “Is it a multiple of three?” function

Create a function that's like EvenQ, but for multiples of three. EvenQ stands for "even query", meaning it lets the user query if a number is a multiple of 2 or not. Your function should have one input and one output. It should return True if the number is a multipe of 3, False if not. Use your function to create a Boolean list of trues/falses for all the numbers between 1 and 30, inclusive, to indicate whether or not they are divisible by 3. Hint: the Mod function will be very helpful.

Assignment 2. Swap function

Many programming languages have a “swap” function for lists (or “arrays”, as they are normally called), which swaps two list elements. Oddly enough, Mathematica doesn’t seem to have one. So, create a function that swaps two elements of a list, using the [[ ]] symbols inside the Module to both access and change the list. The function should have three inputs: the list itself, and the indices for the two elements to be swapped. Force the three function inputs to be of type “List”, “Integer”, and “Integer”, respectively; refer back to the “it’s worth pointing out” paragraph just  before the “Hello world” assignment in the last lab if you can’t remember how to do that. The output should be the new list. Test it out by swapping the 3rd and 4th items of this list: {11,12,13,14,15,16}.

Assignment 3. Fibonacci

Hopefully at some point in your life you have run across the Fibonacci series before: 0,1,1,2,3,5,8,13,.... Each successive term is the sum of the two previous terms. Mathematica has a built-in Fibonacci command--Fibonacci[n] gives the nth Fibonacci number. For this assignment you need to create a function which returns a list of all the Fibonacci numbers that are less than or equal to a user-specified number (the input to the function). For example, if you call the function with an argument of 144, it should output this list:  {1,1,2,3,5,8,13,21,34,55,89,144}  because those are all the Fibonacci numbers less than or equal to 144.  If a non-integer is used as the input, the function should still work the same way. Feel free to use the Fibonacci command in your program, and AppendTo may be helpful as well. Test it out by creating a list of all Fibonacci numbers less than 58150.2.

Assignment 4. Number permutations

Create a function which will take two integer numbers as inputs, and return True if the two numbers are permutations of each other and False otherwise. For example, 1230041 and 4311002 are permutations of each other but 1230041 and 4311003 are not.  Hint: If you apply the IntegerDigits function to both numbers, then Sort them, the two will be equal if the original numbers were permutations.

Assignment 5. Create an intersection-finding program using Newton’s Method

Introduction to Newton’s method: In a previous lab, we solved the transcendental equation  x = cos(x)  by repeatedly taking cos(x) until the results didn’t change substantially between one iteration and the next. That is called  “fixed point iteration”. It’s great when it works, but it doesn’t always work. And it sometimes takes a lot of iterations to get within the tolerance level you want.

“Newton's method” is a way to solve transcendental equations that is considerably faster and more widely applicable than the fixed-point method. It involves both a function and its derivative. You create the function by subtracting one side of the equation to the other, so i.e. x = cos(x)  becomes f(x) = x - cos(x). The equation x = cos(x) is solved at the x-value where f(x) has a root (equals zero).

Here’s Wikipedia’s explanation of how Newton’s method works: “The idea of the method is as follows: one starts with an initial guess which is reasonably close to the true root, then the function is approximated by its tangent line, and one computes the x-intercept of this tangent line. This x-intercept will typically be a better approximation to the function’s root than the original guess, and the method can be iterated.”

Look at the animation under “Description” in the Wikipedia article to help you visualize why the sequence of guesses eventually converges to the root.

Thus, given a function f(x) and a guess that (Subscript[x, n]) may be close to a root, the next guess (iteration) will be (Subscript[x, n+1]) = (Subscript[x, n])-f((Subscript[x, n]))/f'((Subscript[x, n])).  The iterations continue until Abs[f(x)] , which ideally would become exactly zero at the position of the root, becomes less than some tolerance level like (10^(-6)) or (10^(-9)).

Here’s a function which, let’s say, we want to find a root of:

funky[x_] :=Cos[x+2*Cos[x]]
Plot[funky[x],{x,0,20}]

You can see how Newton's method would be implemented in a While loop to find the root of funky[x] that's near x = 5:

latest = 5; (* starting x value *)
While[Abs[funky[latest]]>10^(-9),
 latest =latest-funky[latest]/funky'[latest]; 
Print[N[latest,9]]  (* so you can see it getting closer and closer *)
]
N[latest,9] (* the final x-value *)

Comments: As a reminder, when we solved x = cos(x) in the last lab using the  NestWhileList function to do a “fixed-point iteration” of cos(x), it took 33 iterations before it converged to a tolerance of (10^(-6)). You should be impressed with how quickly Newton’s method works! Only 5 iterations to get a tolerance 1000x better! Newton isn’t considered a genius for nothing! In fact, Mathematica uses Newton’s method in its own FindRoot routine.

The assignment: Create a “Find the intersection” program. Remember the intersection of f1(x) and f2(x) is the same as the root of f1(x) - f2(x).

Your intersection-finding program should:
a) take four parameters as inputs: two functions, a starting x value, and a tolerance level
b) output the intersection point as {x,y}

For this assignment I don’t want you to use the built-in FindRoot command, but create your own version of it as in the While loop example just above. Test the program by finding the intersection of cos(x) and (x^2). Make a plot of the two functions first, to get an estimate of the intersection point and hence a good starting point.

Hint: Using functions as inputs is a bit more challenging than using numbers as inputs. I’ve found it easiest to use function names without the “[x]” attached. However, that means that the input argument might have to be a user-defined “nameless function” if you want to send in a function that does not have a built-in name. Here’s an example of what I mean:

(* this evaluates computes f1(x)/f2(x) *)
divide[f1_,f2_,number_]:=Module[{f,x}, 
f[x_] =f1[x]/f2[x];         (* look, you can define functions inside of Modules *)
f[number]
]
divide[Exp, #^2 &, 3]    (* this sends in e^x, x^2, and 3 as the three parameters *)
%//N

Getting Input From The User

There are many ways to make a program stop and ask for user input.  Evaluate the cells below to see several possibilities, which are listed in order of increasing complexity. See also the guide page on Basic input and output in programs.

res = InputString[];
"My name is "<> res <> "!"

res =Input["Enter an expression containing x and click OK or press Enter."]
Plot[res,{x,0,1}]

res = 0;
Do[res += ChoiceDialog["Make 3 selections, which will then be added together.",{" 1 "->1," 2 "->2," 3 "->3," 4 "->4," 5 "->5}],{3}]
res

waitforuser := DialogInput[DialogNotebook[{Button["Click 3 times to return to Kansas",DialogReturn[]]}]]
Do[waitforuser,{3}];

pickcolor=DialogInput[{col=Pink},
DialogNotebook[{TextCell["Click colored box below to pick a color"],ColorSetter[Dynamic[col]],Button["Proceed",DialogReturn[col]]}]
]

Graphics[{pickcolor,Disk[]},ImageSize->100]

Assignment 6. Using “Input”

Write some code that gets two numbers, x and y, from the user via input statements and then subtracts them, displaying the result with a Print statement saying “The result of x-y is: [answer]“.

Putting It All Together: A “Guess The Number” Program

Assignment 7. Write a “Guess the number” program

Write a guess the number program. Have the computer “think” of a random integer between 1 and 100. Use Input to get an initial guess from the user. Use successive Input statements to (a) inform the user as to whether their last guess was too high or too low, and (b) obtain a new guess. Repeat until the user gets it right (I suggest a While loop), then use a couple of Print statements to tell the user they were correct and how many guesses they took. Wrap everything inside a Module called “guessthenumber[ ]” (a function that does stuff but takes no arguments).

Side note: This is the first major program that I myself always write whenever I learn a new computer language. That’s because it uses loops, conditionals, gets input from the user, and displays output. If you can do all that, you’ll be able to write nearly any program you’ll need.

Advanced Debugging (Optional)

We’ve already discussed some basic debugging. Mathematica has many more debugging-related commands, which are lists on the Debugging guide page. There isn’t enough time to go into all of the available techniques, but here are a few more things you may want to be aware of. They are more-or-less in order of how useful I myself have found them.

Timing and Memory

You’ve already seen the Timing command in a previous lab. It can be useful when comparing two different ways of doing the same process. The  TimeConstrained command is related; it allows you to specify a maximum time for the calculation; after that, it aborts. The ByteCount  and  MemoryConstrained commands are very analogous, but for memory instead of timing--they report the amount of memory consumed during a command, and allow your program to abort automatically when too much memory is used, respectively.

Timing[
Module[{x = 1/Pi},
Do[x = 3.5 x(1-x),{10^6}];
x]
]

TimeConstrained[
Module[{x = 1/Pi},
Do[x = 3.5 x(1-x),{10^7}];  (* I increased the loop by a factor of 10 *)
x]
,5]  (* aborts after 5 seconds *)

ByteCount[Range[ 10^6]]  (* shows how much memory is required *)

MemoryConstrained[Range[10^6],10000000]  (* doesn't reach memory limit *)

MemoryConstrained[Range[10^6],2000000]  (* aborts when it reaches specified memory limit *)

Sow and Reap

(a) Sow and Reap work together to keep track of information. Each time Sow gets used during a command such as a loop, it adds the item that you have “tagged” with Sow to an invisible list. Reap then outputs the entire list once the loop is complete. Evaluate the following two cells, which perform nearly identical operations. The difference is that whereas the Print command just lets you look at the intermediate results, Sow and Reap actually give you the intermediate results in a potentially usable form.

res  = 0;
Do[
res = res+i;
Print[res];
,{i,1,10}]

res  = 0;
Do[
res = res+i;
Sow[res];
,{i,1,10}] //Reap
%[[2,1]]  (* For some strange reason the "sown" list shows up as the [[2,1]] element of the array returned by Reap *)

(b) Sow and Reap are especially useful if you want to generate a lengthy array of results during a loop, something that you might otherwise do with AppendTo. In the blog post on writing fast code in Mathematica mentioned above, the author points out: “Because of the flexibility of Mathematica data structures, AppendTo can’t assume that you will be appending a number, because you might equally append a document or a sound or an image. As a result, AppendTo must create a fresh copy of all of the data, restructured to accommodate the appended information. This makes it progressively slower as the data accumulates.” Instead, to generate a lengthy array of numerical results, the author recommends you always use a Sow/Reap pair. Try these two modules, both of which generate a list of the first 50,000 prime numbers. They are entirely equivalent, but the second runs 10x faster than the first one.

primearray[n_]:=Module[{start=1,currentprime,array={}},
currentprime=NextPrime[start];
AppendTo[array,currentprime];   (* adds first value into array *)
Do[   
currentprime=NextPrime[currentprime];
AppendTo[array,currentprime];   (* sticks each new value into array during loop *)
,{i,1,n-1}];
array
]
primearray[50000] //Timing  (* takes 11.2 sec on my office computer *)

primearray2[n_]:=Module[{start=1,currentprime,array={}},
Reap[     (* Notice I've used the regular form of Reap instead of postfix, as in the example (a) *)
currentprime=NextPrime[start];
Sow[currentprime];    (* adds first value into array *)
Do[   
currentprime=NextPrime[currentprime];
Sow[currentprime];    (* sticks each new value into array during loop *)
,{i,1,n-1}];
][[2,1]]  (* I added the [[2,1]] because Reap otherwise outputs the list result into the second list component *)
]
primearray2[50000] //Timing  (* takes 1.3 sec on my office computer. 10x faster!! *)

Other “flow control” commands

Interrupt (introduced above) is an example of a “flow control” command, in that it affects the regular flow of your program; see the guide entry on Flow Control for some more info. Other potentially useful flow control commands include Break, which terminates a loop, Continue, which allows you to skip one or more steps, Pause, which has the computer wait for the number of seconds you specify, and Abort, which stops all running cells. (Note that Interrupt and Abort can also be found under the Evaluation menu, and have useful short-cut keys.)

Evaluate the cells below to see how those other four commands behave.

Do[If[n==5,Break[]];Print[n],{n,1,10}];

Do[If[n==5,Continue[]];Print[n],{n,1,10}];

Do[If[n==5,Pause[2]];Print[n],{n,1,10}];

Do[If[n==5,Abort[]];Print[n],{n,1,10}];

Throw and Catch

Throw and Catch form a pair much like Sow and Reap, except instead of accumulating a whole list of items (such as Sow), the loop gets terminated as soon as the first Throw is executed. Catch returns the value tagged by Throw. In practice, Throw is usually used to flag an error condition or unexpected argument.  Catch can then be used to decide whether to continue the calculation, substitute another value, print an error message, or abort the calculation. 

For example, here’s a loop that keeps iterating until the user doesn’t enter a valid number, at which time it aborts.

While[True,  (* don't need a stop condition because Throw exits loop *)
usernum=Input["Enter a number"];
If[NumberQ[usernum],
(* if OK *) Print[usernum],
(* else *)  Throw["That's not a number!"] ]
]//Catch

Monitor

Mathematica's Monitor function allows the user to monitor the progress of a lengthy computation.  Evaluate the following two examples.  In the first example, which repeatedly evaluates the average of (10^6) random numbers, we implement both numeric and graphical monitors.  In the second example, which we modified from the "Applications" section of the help reference page, we fit a one-dimensional function to a set of data, while monitoring a plot of the fitting function.  Observe that monitors are temporary, disappearing after a computation has finished.

ranavg[num_]:=Sum[RandomReal[],{num}]/num;
Monitor[   Table[ranavg[10^6],{n,1,10}],  {n,ProgressIndicator[n,{0,10}]}   ]

data = {{0.18,-0.13},{0.84,-0.06},{0.05,0.88},{0.24,-0.63},{0.67,0.93},{0.05,0.88},{0.65,0.92},{0.01,0.99},{0.17,-0.04},{0.23,-0.55}};
lp = ListPlot[data, PlotRange->{-1,1},PlotStyle->{PointSize[0.02]}];

model[{a_, k_, w_, p_}] := a Exp[-k x] Sin[w x +p];
varlist = {a,k,w,p};

Monitor[FindFit[data, model[varlist],varlist,x,StepMonitor:>Pause[0.5]],Show[lp,Plot[model[varlist],{x,0,1}]]]

Evaluation Monitor

The tutorial on Monitoring Algorithms gives more information about EvaluationMonitor and StepMonitor, two options that are allowed inside many routines that either plot or numerically operate on mathematical functions (e.g. Plot, NIntegrate, FindRoot, FindMinimum, etc). I’ll just focus on EvaluationMonitor for now. It causes something to happen each time the algorithm being used (in a numerical integral, for example) gets evaluated.  

Here’s an example that uses EvaluationMonitor to Sow the points sampled during a numerical integration of f(x)=(Sqrt[x]).

f[x_] :=Sqrt[x]
{result,{points}} = Reap[NIntegrate[f[x],{x,0,1},PrecisionGoal->4,EvaluationMonitor:>Sow[x]]]  (* the funny arrow is obtained with ":>" *)
Show[Plot[f[x],{x,0,1}],ListPlot[Transpose[{points,f /@ points}]]]

Here’s another example, where the local variable evals gets incremented each time the FindMinimum algorithm gets evaluated. By contrast, StepMonitor only increments the local variable steps each time the algorithm makes a successful step, which might involve several evaluations.

algmonitor[method_] :=Module[{evals= 0,steps=0},
FindMinimum[(x-1)^2+100(y-x^2)^2,{{x,-1},{y,1}},Method->method,EvaluationMonitor:>evals++,StepMonitor:>steps++];
{method,evals,steps}
]
algmonitor/@ {Automatic,"LevenbergMarquardt","InteriorPoint","Newton","QuasiNewton", "ConjugateGradient","Gradient"}
TableForm[%,TableHeadings->{{},{"Method","Evaluations","Steps"}} ]

Additional Assignments

Assignment 8, Extra Credit. Bubble sort

Sorting lists is an important computational task, and while Mathematica has the built-in Sort function, it’s worthwhile seeing how such a function would be implemented. One of the simplest sorting function implementations is called the bubble sort. To quote Wikipedia:

“Bubble sort is a simple sorting algorithm that works by repeatedly stepping through the list to be sorted, comparing each pair of adjacent items and swapping them if they are in the wrong order. The pass through the list is repeated until no swaps are needed, which indicates that the list is sorted. The algorithm gets its name from the way smaller elements “bubble” to the top of the list.”

For example, if you wanted to bubble sort the list, {5,3,7,6,2}, the algorithm would proceed like this:

first pass: {3,5,7,6,2} (5 and 3 would be swapped), then {3,5,6,7,2} (7 and 6 would be swapped), then {3,5,6,2,7} (7 and 2 would be swapped)
second pass: {3,5,2,6,7} (6 and 2 would be swapped)
third pass: {3,2,5,6,7} (5 and 2 would be swapped)
fourth pass: {2,3,5,6,7} (3 and 2 would be swapped)
fifth pass: {2,3,5,6,7}  no change-- sort is complete!

Here’s the assignment:  Use a Module with local variables, a While loop to go through the “passes”, a Do loop to go through the pairs of array elements, and an If statement to compare array elements (at least, those are my recommendations) to create a bubblesort[list_]  function. It should take a list of numbers as input, and return the list sorted in numerical order. You can use the swap function that you wrote for the assignment 3 above, inside your Module.

Test your Module on this list. Done correctly, the bubble sort should take about 18 passes and 86 total swaps to complete.

testlist={0.9,9.7,6.1,7.7,2.4,5.7,4.5,8.1,1.3,3.4,4.6,6.2,6.3,6.5,3.1,8.7,7.5,3.7,1.2,9.1}

Wrap-up

The following functions were discussed in today's lab, or are very closely related:
The main command for creating your own programs: Module
Flow control functions: Break, Continue, Pause, Interrupt (with Return),  Abort, 
Basic user input functions: Input, InputString
To see text or a variable value (e.g. from inside a Module): Print
To see some output that’s normally surpressed: FullForm
To see a table in a nicely formatted fashion: TableForm
Advanced user input functions: ChoiceDialog, DialogInput, DialogNotebook, DialogReturn
Advanced flow control/debugging: Throw, Catch, EvaluationMonitor, StepMonitor, Sow, Reap, Trace, Monitor 
Time/memory management: Timing, TimeConstrained, ByteCount, MemoryConstrained

Potentially useful summary/tutorial pages: 
Guide: Flow Control
Guide: Basic input and output in programs
Guide: Debugging
Tutorial: Monitoring Algorithms