This lesson covers:
- Comments
- Multi-statement lines and multi-line statements
- Input with the read function
- Output with the print statement
You should read Lesson 1 and Lesson 2 before this one.
This is my least favorite lesson. Nothing in this lesson makes it possible to solve new problems. It's just stuff to make your programs easier to read. The problems we solve in this lesson will be kind of lame. Let's get this over with.
Comments
Comments are simply text that bc ignores. The purpose of comments is to tell people reading your program what it does, how it does it, and how they can use it.
There are two ways to make a comment in bc. The way I prefer uses a pound sign #, which you may call a number sign, hash, or octothorpe. Everything on a line after a # is a comment, which will be ignored when your program is run.
You can also start a comment with slash-star /* and end it with star-slash */. You might prefer this way if you have comments that go on for more than one line. If I want a multi-line comment, I'll just put a # at the beginning of each line, but you feel free to use /* and */.
Commenting is also used to temporarily disable some of your program. If you want to see how your program would run without a certain line, you can "comment it out" by putting a # at the beginning of the line, and bc will just skip that line.
Here's a comic that uses the fact that comments in C++ start with //. The idea is that you can ignore someone by putting // in front of them. Get it?
Comment example
Anyway, here's an example of a program with comments:
# Find the nth Fibonacci number n = 12 r = (1 + sqrt(5)) / 2 # The golden ratio (r^n - (1 - r)^n) / sqrt(5) # Binet's formula halt
Writing good comments is a skill that you'll pick up over time as you write and read programs. One common rookie mistake is over-commenting. You should assume that people reading your program understand how bc works, so don't explain obvious things.
# Find the nth Fibonacci number # This file is called fib.bc, because fib is short # for Fibonacci. That's because we're finding the # nth Fibonacci number. # Beginning of program # n is a variable that represents n n = 12 # Assign 12 to n # sqrt(5) means take the square root of 5 r = (1 + sqrt(5)) / 2 # The golden ratio # About to output the nth Fibonacci number # sqrt(5) means take the square root of 5 (r^n - (1 - r)^n) / sqrt(5) # Binet's formula # Done outputting the nth Fibonacci number halt # halt means to exit bc # End of program # Thank you
So I won't give you any rules for when to comment. Just use your judgment. But one thing I'll always do is start each program with a comment that says what the program does.
Short statements
Normally every statement is exactly one line long, and every line has exactly one statement on it. Occasionally, putting more than one short statement on a single line makes your program more readable. You can do this by separating statements with a semicolon ;:
day1 = 21 ; month1 = 12 ; year1 = 1872 day2 = 21 ; month2 = 11 ; year2 = 1955 day3 = 1 ; month3 = 1 ; year3 = 802701
That's a little clearer than having each statement on its own line, and it's interpreted the same way by bc:
day1 = 21 month1 = 12 year1 = 1872 day2 = 21 month2 = 11 year2 = 1955 day3 = 1 month3 = 1 year3 = 802701
If you like you can also put a ; at the end of every statement. It doesn't do anything. Some people do this because it's required in some languages, but it's optional in bc, so either way is fine.
Long statements
If a statement is really long, you might want to break it up into more than one line. This can be done by ending every line that doesn't end the statement with a backslash \. If you do this, the \ has to be the very last character on the line: you can't even put spaces or comments after it:
tedious_sum = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + \ 9 + 10 + 11 + 12 + 13 + 14 + 15 \ + 16 + 17 + 18 + 19 + 20 + 21 + \ 22 + 23 + 24 + 25
Smooth programming rarely requires statements so long that they don't fit on a single line. I'm never going to use this feature in this tutorial.
The read function
The read function is how a bc program gets input from the user (the person running the program). When bc gets to read(), it will stop and wait for the user to enter a number. Let's solve a problem using the read function.
# Count the number of possible number plates # given the number of letters and digits nletters = read() ndigits = read() 26^nletters * 10^ndigits halt
This program tells you how many different number plates (like on a car) you can make, if each plate has a certain number of letters and digits on it (and they appear in the same order, and you can tell the letter O from the number 0, etc.). If there are 3 letters and 2 digits, there are 1,757,600 possible plates. If we run the program and enter 3 and 2, it should give us this answer:
christopher:~/smooth$ bc -q plates.bc 3 2 1757600 christopher:~/smooth$
Problem 1: Number Plates
Which option will give you more possible plates? Using 5 letters and 1 digit, or using 0 letters and 8 digits? Solve this problem without changing the text of the program, just by running it twice and inputting different numbers.
5 letters and 1 digit give you more possible plates:
christopher:~/smooth$ bc -q plates.bc 5 1 118813760 christopher:~/smooth$ bc -q plates.bc 0 8 100000000 christopher:~/smooth$
The print statement
So far we've seen that when you enter an expression that's not an assignment, its value gets printed. The print statement is another way to print a value. It can also be used to print text, by placing double-quote marks " at the beginning and end of the text:
christopher:~/smooth$ bc -q print "hello world" hello world
You'd think that printing stuff out should be the simplest thing in the world, right? Well here's where it gets complicated. When you use a print statement, there's no newline at the end. (A newline is what you get when you press Enter.) If you want a newline, there are two ways to do it. The bad way is just to put an Enter inside your quotes:
print "hello world "
But don't do that. The preferred way is with backslash-n \n:
print "hello world\n"
If you need to print out a double-quote mark, use backslash-q \q, and to make a backslash, use double-backslash \\\\:
print " \qhello world\q\n\\\\o/\n" "hello world" \o/
If you really feel like it, you can print text without print. Just put it on a line in ", but \n, \q, and \\\\ won't work:
"hello world\n" hello world\n
I'll always use print when printing text.
Multiple print statements
You can use print statements to give context to the values that you print out. Just printing 1757600 is not as useful as printing The number of possible plates is: 1757600. The following in a program:
x = 4 y = 3 print "(x, y) = (" print x print ", " print y print ")\n"
will print:
(x, y) = (4, 3)
When you have consecutive print statements like that, you can combine them into one, by separating the things you're printing with commas. You can print out both text and expressions using the same print statement when you do this, that's fine.
print "(x, y) = (", x, ", ", y, ")\n"
In this example it can be confusing which commas are inside the quotes and which ones are outside, but that's the way you have to do it.
Triangular Tower
Say you've got a tower 4 levels high. The top level is 1 block, then 2, then 3, then 4. How many blocks make up the tower? It's 1 + 2 + 3 + 4 = 10. Now what if the tower is 100 blocks high? Then it's 1 + 2 + ... + 99 + 100 blocks.
So what's the sum of the numbers from 1 to 100? It's said that the mathematician Carl Gauss figured out how to get the answer quickly when he was seven years old. But then again, a lot of things get said about Gauss. (Like, Gauss can recite all the digits of π... backward.) Anyway, the technique he would have used basically comes down to this. A tower n levels high has this many blocks:
$$1 + 2 + ... + (n-1) + n = {n(n+1)}/2$$
If we used this formula with n = 100, we would see that the tower needs 5,050 blocks.
Problem 2: Program for the triangular tower
Let's bring it all together. Write a program that uses the read function and the print statement to input the number of levels in the triangular tower from the user, and output the number of blocks in the tower. Your program should also contain at least one comment. Here's what it should look like when you run the program:
christopher:~/smooth$ bc -q tower.bc How many levels in the tower? 36 1 + 2 + ... + 35 + 36 = 666 so there will be 666 blocks in the tower.
# Find the number of blocks in a triangular tower print "How many levels in the tower?\n" n = read() b = n * (n+1) / 2 # number of blocks print "1 + 2 + ... + ", n-1, " + ", n, " = ", b, "\n" print "so there will be ", b, " blocks in the tower.\n" halt
Next time
Sometimes in your programs, you want to sometimes do one thing and sometimes do another. Next time we'll see how to make decisions like this.
Your program for Zeller's Congruence is nice, and it works for the limited test suite of three dates in your example. But three dates is not enough, is it? Your program doesn't do very well for days in that messy Month, February, which has a varying number of days. You need to begin the year in March, I think. But that's just a suggestion. Otherwise, your program's good, and even the slight error is more useful than someone else's b.s., in my view. J. Wagner, <gnujohn"at"gmail"dot"com.
ReplyDelete