Programming Logic
An Introduction to Computer Science with Java, Python and C++ Community College of Philadelphia edition Copyright 2018 by C.W. Herbert, all rights reserved.
Last edited September 24, 2018 by C. W. Herbert
This document is a draft of a chapter from An Introduction to Computer Science with Java, Python and C++, written by Charles
Herbert. It is available free of charge for students in Computer Science courses at Community College of Philadelphia during the
Fall 2018 semester. It may not be reproduced or distributed for any other purposes without proper prior permission.
Please report any typos, other errors, or suggestions for improving the text to [email protected]
Contents Chapter 3 – Programming Logic .................................................................................................................... 3
Boolean Logic in Branching and Looping .......................................................................... 4
Boolean Relational Operations ............................................................................................................. 5
Boolean Relational Operators in Python .............................................................................................. 5
Boolean Logical Operations .................................................................................................................. 7
Boolean Logical Operators in Python .................................................................................................. 10
Boolean Expressions Using Boolean Variables .................................................................................... 10
CheckPoint 3.1 ..................................................................................................................................... 11
The Nature of Algorithms................................................................................................ 12
Turing Machines and the Church-Turing Thesis ................................................................................. 12
Elements of Logical Structure in Algorithms ....................................................................................... 16
Tools for Describing Algorithms .......................................................................................................... 19
Linear Sequences ................................................................................................................................ 23
CheckPoint 3.2 ..................................................................................................................................... 24
Conditional Execution (Branching ) ................................................................................. 24
Binary Branching – Bypass vs. Choice ................................................................................................. 24
Binary Branching in Python ................................................................................................................. 25
Multiple Branching .............................................................................................................................. 27
Pythons elif statement ........................................................................................................................ 30
CheckPoint 3.3 ..................................................................................................................................... 31
Chapter 3 – Programming Logic DRAFT September 2018 pg. 2
Lab Reports and Collaborative Editing ............................................................................ 32
Computer Science 111 Lab Report ...................................................................................................... 32
Collaborative Editing of Word Documents ......................................................................................... 33
Tracking Changes ................................................................................................................................ 33
Document Comments ......................................................................................................................... 34
Lab 3A – Body Mass Index ...................................................................................................................... 34
Lab 3B – Quadratic Equations ................................................................................................................ 36
Key Terms in Chapter 3 ........................................................................................................................... 39
Chapter 3 – Questions ............................................................................................................................ 39
Chapter 3 – Exercises .............................................................................................................................. 40
Chapter 3 – Programming Logic DRAFT September 2018 pg. 3
Chapter 3 – Programming Logic This chapter is about branching – conditional execution of code segments that depends on the
result of Boolean logic in a computer program.
The chapter begins with a look at relational operations that compare values to yield true or false
results, such as less than or greater than, and logical operations that combine and modify such
values in Boolean expressions, such as if (hours > 40.0 and rate > 12.50).
The nature of algorithms and their structure are briefly examined, including the concept of a
Turing machine and its importance in the history of computer science and math. The bulk of the
chapter is about branching in Python. Repetition of a code segment in an algorithm, also known as
looping, will be covered in the next chapter.
Learning Outcomes
Upon completion of this chapter students should be able to:
• list and describe the six comparison operators and the three primary logical operators used in
Boolean logic;
• describe the use of comparison and relational operators in forming Python Boolean expressions;
• describe the concept of a Turing machine and the nature and importance of the Church-Turing
Thesis;
• list and describe the three elements of logical structure in algorithms;
• describe the difference between a binary bypass and a binary choice in the logic of an algorithm;
• describe the concept of multiple branching and how it relates to binary branching;
• describe the use of the if statement for establishing conditional execution in Python;
• describe the use of the if…else statement for establishing multiple branching in Python, and how
to establish nested if…else structures in Python;
• describe the proper use of the elif statement for establishing multiple branching in Python.
• create Python code that demonstrates correct use of each of the following: conditional
execution, multiple branching with an if…else structure, and multiple branching with an elif
structure;
• describe the requirements of a properly organized programming lab report for Computer
Science 111, and how to use Microsoft Word’s track changes and commenting features to
collaboratively edit lab reports.
Chapter 3 – Programming Logic DRAFT September 2018 pg. 4
Boolean Logic in Branching and Looping
In chapter one we saw Python’s Boolean data type, whose variables have the values True and False. The
data type is named for George Boole, a brilliant self-taught mathematician with little formal training who
became the first Professor of Mathematics at Queen’s College in Cork, Ireland. Boole wrote two books
that laid a foundation for what are today known as Boolean logic and Boolean algebra: The
Mathematical Analysis of Logic (1847) and An investigation into the Laws of Thought, on which are
founded the Mathematical Theories of Logic and Probabilities (1854).²
The digital logic that is today the basis of both computer hardware and computer software evolved over
a period of about 90 years following Boole’s first publications on the subject. Many people contributed
to perfecting Boole’s ideas, in particular Augustus De Morgan at London University, London economist
and mathematician William Stanley Jevons, and Claude Shannon, a Bell Labs mathematician and
electrical engineer who developed digital circuit logic.
Boolean logic is a system of logic dealing with operations on the values 1 and 0, in which 1 can represent
true and 0 can represent false. We will use the values true and false in discussing Boolean operations.
Boolean algebra is a formal language for describing operations on true and false values based on
Boolean logic. Boolean algebra is covered in Math 121, Math 163 and several other courses at
Community College of Philadelphia.
Computers derive Boolean true and false values primarily by comparing things. For example, a condition
in a payroll program might compare the number of hours a person worked to the value 40 to see if the
person should receive overtime pay:
if (hours are greater than 40)
calculate overtime pay
The condition (hours are greater than 40) will be true or false. If it is true, then the computer will
be directed to calculate overtime pay, if it is false, the computer will ignore this directive.
Simple conditions such as these can be combined or modified using logical operations to form
compound conditions, such as:
if ((burglar alarm is on) AND (door is open))
sound alarm
There are two simple conditions in this case that both need to be true for the alarm to sound.
In this section we will look at the comparisons that yield true and false results and the language for
specifying them in Python. In the next section, we will look at logical operations like the AND operation
that form compound conditions, then see how Boolean logic forms branching and looping sequences in
the structures of algorithms.
Chapter 3 – Programming Logic DRAFT September 2018 pg. 5
Boolean Relational Operations
In Python programming, a Boolean variable is assigned a true or false value by using the Boolean
constants True or False, or by using an assignment statement with Boolean expressions:
A Boolean variable can be set to True or False, such as in the following:
licensed = False
citizen = True
The terms True and False are known as Boolean constants or Boolean literals. Boolean literals are
tokens that represent the values true and false in Python code. They are not Strings. There are only two
Boolean literals – True and False.
We can also obtain a true or false value by using relational operations in Boolean expressions. A
relation operation is a comparison of two values to see if they are equal, or if one is greater or lesser
than the other. A relational operation forms a Boolean expression that may be true or false. The
relational operations are indicated by relational operators for equality and inequality. A Boolean
expression is an expression that evaluates to a true or false value.
For example, the expression (x < 3) can be evaluated for a specific value of x. When x is 2, the
expression evaluates to true; when x is 4, the expression evaluates to false.
Boolean Relational Operators in Python
There are six common relational operations in Boolean logic. The table below describes each of the six,
along with the operators used for them in math and in Python programming.
Boolean Relational Operations
Condition math Python Examples A equals B A = B (A == B) zipcode == "19130"
A is not equal to B A ≠ B (A!= B) root != 0.0
A is less than B A < B (A < B) name < "Miller"
A is greater than B A > B (A > B) temperature > 98.6
A is less than or equal to B A ≤ B (A <= B) rate <= 12.50
A is greater than or equal to B A ≥ B (A >= B) bedrooms >= 3
Note that the logical operator for equals uses two equal signs together, as opposed to the operator in
Python assignment statements that uses a single equal sign. The equals and not equals operators are
sometimes referred to as equality operators.
The symbols for the six logical operators in Python are the same in many programming languages,
including Java and C++.
Simple Boolean conditions for branching in Python each have a single conditional operation in following
the keyword if, as in the following example:
Chapter 3 – Programming Logic DRAFT September 2018 pg. 6
if hours > 40
overtimeHours = hours - 40.0
overTimepay = overtimeHours * rate * 0.5
In this case, the condition is immediately followed by a new block of code indicated by indenting the
block of code. If the condition is true, then the entire block of code will be executed. If the condition is
false, the computer will skip the block of code and move on to whatever comes next in the code. This is
an example of conditional execution. We will see more about if statements in Python later in this
chapter.
If we compare numbers, then it is obvious what the less than and greater than operations mean, but
what about text data, such as strings in Python?
A collating sequence is used for comparison of text data. A collating sequence is a defined order of
characters for a particular alphabet or set of symbols. The formal name for this is lexicographic order or
lexicographical order A lexicon is a dictionary -- a set of words in a particular order. In mathematics,
lexicographic order means that a set of word is ordered according to the defined order of their
component letters. In other words, alphabetic order, according to some defined alphabet.
The version of the Latin alphabet used for the English language is an example: {A, B, C, … Z}. It seems
simple, but almost immediately complications can arise. What is the order of the characters if we have
both uppercase and lowercase characters? Here are three different collating sequences based on the
English version of the Latin alphabet with both uppercase and lowercase characters:
Three Collating Sequences for the English Alphabet
1. {A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}
2. {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z}
3. {A,a,B,b,C,c,D,d,E,e,F,f,G,g,H,h,I,i,J,j,K,k,L,l,M,m,N,n,O,o,P,p,Q,q,R,r,S,s,T,t,U,u,V,v,W,w,X,x,Y,y,Z,z}
All three sequences use the traditional A-Z order learned by children, but differ as to how they handle
upper and lower case letters. In the first sequence, uppercase letters come before lowercase letters. In
the second sequence lowercase letters are first, or less than the upper case letters. The third sequence
is more traditional, with the uppercase and then the lowercase version of each character coming before
the uppercase and lowercase version of the next character in the A-Z sequence. (Can you see what a
fourth sequence might be?)
Consider the order of the words "apple" and "Ball" according to the three sequences above.
• Using the first sequence, B comes before a because uppercase B comes before lowercase a; B is
less than a. In this case, Ball comes before apple.
• With the second sequence, lowercase letters come before uppercase letters, so a comes before
B. Here apple comes before Ball.
Figure 1 –
Block of code in an if statement
Chapter 3 – Programming Logic DRAFT September 2018 pg. 7
• The third sequence, which is more commonly used in everyday language, indicates that both
uppercase and lowercase versions of a letter come before the next letter in the sequence. In this
case, apple comes before Ball.
We also need to consider non-alphabetic symbols in a collating sequence for text data. Do the symbols
for numeric digits come before or after letters of the alphabet? What about special symbols, such as the
question mark, the dollar sign, and the ampersand? What about symbols from other alphabets?
As we saw in the previous chapter, most modern computer programming languages, including Python,
use the defined order of the Unicode UTF-16 character set as the collating sequence for text data. So do
most modern operating systems, including all current versions of Microsoft Windows, Apple OS X, and
most newer Linux and Android operating systems.
Each Unicode character has a code number. The order of the code numbers is the order of the
characters when Unicode is used as a collating sequence. Here is a chart showing part of the UTF-16
code1 in order. The entire UTF-16 code has over 64,000 characters (216 = 65,536) characters:
A Portion of the UTF-16 Version of Unicode ! " # $ % & ' ( ) * + - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
@ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _
` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
Each line in the chart is a continuation of the previous line. The chart shows us that the numeric digits
come before uppercase letters, which come before lowercase letters. Symbols other than alphanumeric
characters are in different parts of the code; some before alphanumeric characters, some after.
A String value is a sequence of characters. When we learn more about Strings, we will see that the
Unicode sequence is also used to compare String values, character by character
Boolean Logical Operations
Simple Boolean conditions based on comparing values can be combined using Boolean logical
operations to form compound conditions, such as the burglar alarm condition mentioned earlier:
(burglar alarm is on) AND (door is open)
There are three primary logical operations in Boolean logic:
• conjunction, represented by the word AND
• disjunction, represented by the word OR
• negation, represented by the word NOT
The AND operator takes two Boolean operands and yields a Boolean result. If both operands are true,
then the result is true, otherwise the result is false. If either operand is false, the result is false.
1 Unicode also includes characters from other languages, such as the Cyrillic, Arabic and Hebrew alphabets. For detailed information on Unicode, see the Unicode Consortium Website, online at: http://www.unicode.org/
Chapter 3 – Programming Logic DRAFT September 2018 pg. 8
The OR operator takes two Boolean operands and yields a Boolean result. If both operands are false,
then the result is false, otherwise the result is true. If either operand is true, the result is true.
The NOT operator is a unary operation with a single operand. If the operand is true, the result is false. If
the operand is false, the result is true. This is known as inverting a Boolean value. The NOT operation
inverts the true or false value of the operand.
The table below defines the three primary Boolean logical operations:
AND OR NOT
false AND false -> false
false AND true -> false
true AND false -> false
true AND true -> true
false OR false -> false
false OR true -> true
true OR false -> true
true OR true -> true
not(false) -> true
not(true) -> false
The AND and OR operations are both commutative and associative:
commutative (a AND b) = (b AND a) (a OR b) = ( b OR a)
associative (a AND b) AND c = a AND (b AND c) (a OR b) OR c = a OR (b OR c)
AND and OR operations are not distributive with regard to the NOT operation. You may recall from
elementary algebra that the distributive law involves two different operations. For example,
multiplication is distributive over addition, as in these two examples:
a*(b+c) = (a*b) + (a*c) 3(x+y) = 3x + 3y
We often use this in reverse to simplify expressions:
17x + 11x = 28x
We might be tempted to say that NOT(a AND b) = NOT(a) AND NOT(b), but this is incorrect; the NOT
operation is not distributive with respect to AND, nor with respect to OR. Instead De Morgan’s laws
apply.
De Morgan’s Laws
NOT (a AND b) = NOT(a) OR NOT (b) NOT(a OR b) = NOT(a) AND NOT (b)
Like the distributive law in elementary algebra, De Morgan’s laws are often used in reverse in computing
and logic to simplify Boolean expressions.
De Morgan’s laws were developed by George Boole’s contemporary, Augustus De Morgan, who, at age
22 became the first professor of Mathematics at the University of London, shortly after it was founded.
In addition to the primary Boolean operations, there are derived Boolean operations, that can be
derived from the three primary operations. The most common of these are NAND, NOR, and XOR.
These derived Boolean operations are important in the design of modern computer chips because they
are easy to mass-produce in electronic logic circuits (called gates) at a microscopic level. Some chips are
composed entirely of NAND gates or of NOR gates.
NAND NOR XOR
a NAND b = NOT(a AND b) a NOR b = NOT(a OR b) a XOR b = (a OR b) AND NOT(a AND b)
Chapter 3 – Programming Logic DRAFT September 2018 pg. 9
Toward That Grand Prodigy: A Thinking Machine
In 1984, Oxford University Press published The Boole-De Morgan Correspondence, 1842-1864, containing a collection of more than 90 letters between the two friends. George Boole in Cork and Augustus De Morgan in London laid the foundation for modern digital logic. In the Spring of 1847 Boole published Mathematical Analysis of Logic. Later that year De Morgan published Formal Logic or The Calculus of Inference. Much of modern digital electronics and computer programming is based on their work. Boole died from pneumonia in 1864 at age 49. De Morgan went on to found the field of Relational Algebra, the basis for most modern database management systems.
Boole and De Morgan were part of a British circle of acquaintances important in the history of computing, including Charles Babbage and Ada Augusta Lovelace. Most of their writing is available freely online, including their books, papers, and letters.
One interesting artifact is a letter of condolence to Boole’s wife from Joseph Hill describing a meeting of Boole and Babbage at the Crystal Palace Exhibition of 1851. In it Hill wrote:
… Mr. Babbage arrived and entered into a long conversation with Boole. Oh, the scene would have formed a good subject for a painter. As Boole had discovered that means of reasoning might be conducted by a mathematical process, and Babbage had invented a machine for the performance of mathematical work, the two great men together seemed to have taken steps towards the construction of that grand prodigy – a Thinking Machine.”
A copy of Boole’s The Mathematical Analysis of Logic is available online at Project Guttenberg (along with his other works): http://www.gutenberg.org/ebooks/36884
De Morgan’s Formal Logic or The Calculus of Inference is at the Internet Library: https://archive.org/details/formallogicorca00morggoog
A copy of Babbage’s On the Application of Machinery to the Purpose of Calculating and Printing Mathematical Tables is available online from the Hathi Trust Digital Library: http://hdl.handle.net/2027/mdp.39015004166164
Lovelace’s translation and notes from Menabrea’s Sketch of the Analytical Engine is available in its 1843 published form at Google Books: http://books.google.com/books?id=qsY- AAAAYAAJ&pg=PA666&source=gbs_toc_r&cad=3#v=onepage&q&f=false
Text from and images of Hill’s letter to MaryAnn Boole can be found online in the University of Cork’s Boole Papers Collection: http://georgeboole.ucc.ie/index.php?page=11#S01BIx
George Boole 1815-1864
Augustus De Morgan 1806-1871
Charles Babbage 1791-1871
Ada Augusta Lovelace 1815-1852
Chapter 3 – Programming Logic DRAFT September 2018 pg. 10
Boolean Logical Operators in Python
Compound Boolean conditions in Python are formed by using Boolean logical operations AND, OR and
NOT to combine and modify simple conditions. Python simply uses the lowercase versions of the words
and, or and not as the Boolean logical operators:
Operation Python Notes
AND op1 and op2 both operands must be True to yield True
OR op1 or op2 if any operand is True the result is True
NOT not(op1) the Boolean value of the operand is reversed
Logical operations have an order of precedence just as numeric operations do. Parentheses may be used
to group logical operations to specify an order, just as with numeric expressions. In the absence of
parentheses, AND has precedence over OR.
NOT modifies whatever immediately follows it. If a parenthesis follows NOT, then everything in the
parentheses is resolved to a Boolean value, which is then reversed by the NOT operation.
Here are examples of Boolean expressions using AND, OR, and NOT:
# more than 40 hours AND status is “hourly” # a score between 90 and 100, including 90 hours > 40 and status == “hourly” score >= 90 and score < 100
# 1,00 words or 5 pages # month not in the range 1 to 12 wordCount >1000 or pageCount > 5 month < 1 or month > 12
# not (x < 3) or not (y < 4) # not ( ( x < 3) and (y < 4) ) not(x < 3) or not(y < 4) not( x < 3 and y < 4 )
Can you see how the bottom two expressions in the examples above are related to De Morgan’s laws?
Boolean Expressions Using Boolean Variables
Recall that a Boolean variable has a True or False value, so a Boolean condition testing for True only
needs the name of a Boolean variable, not a comparison. The statement to test if innerDoorClosed is
True would be
if innerDoorClosed
rather than
if (innerDoorClosed == true)
Conversely, to test for false, the condition would be
if not(innerDoorClosed)
The parentheses around innerDoorClosed optional. not applies to whatever immediately follows it.
Parentheses are often used, even when not needed, for clarity.
Figure 2 –
compound
Boolean expressions
Chapter 3 – Programming Logic DRAFT September 2018 pg. 11
CheckPoint 3.1
1. How do computers derive Boolean values?
2. What are the six Boolean comparison operators that can be used in Python? Which of these
operators works with string values?
3. What do each of the three primary Boolean operations (conjunction, disjunction, and negation)
do, and what word is associated with each one?
4. What are the symbols in Python for the three primary Boolean operations?
5. Describe two forms of De Morgan’s Laws, and how De Morgan’s laws are related to the
distributive properties of AND and OR.
Chapter 3 – Programming Logic DRAFT September 2018 pg. 12
The Nature of Algorithms
We saw in chapter one that an algorithm is a step-by-step process and that computer programs are
algorithms. In this section we will begin to focus on the nature of algorithms. What problems can and
cannot be solved by following an algorithm? How are algorithms structured?
Algorithms contain the steps necessary to complete a task or solve a particular problem. Algorithms are
a part of everyday life. A recipe for baking a cake will have a list of all the ingredients needed for the
cake and instructions for what to do with those ingredients. The recipe provides an algorithm for baking
a cake. A child who learns to perform long division is learning an algorithm. A doctor can follow an
algorithm to diagnose a patient’s illness. Professionals, such as engineers, architects, and accountants,
use many different algorithms in the course of their work. Some algorithms are simple; some can be
quite long and complex. An algorithm to design the optimum propeller for an ocean-going vessel using
The Holtrop and Mennen Method to determine a vessel's resistance to water uses techniques of matrix
algebra with thousands of steps and must be run on a computer.
Even though algorithms are an important part of life all around us, they are not the kind of thing that
most people spend time thinking about. So, how much do we really know about the nature of
algorithms? How much do we need to know? Mathematicians, engineers, and computer scientists need
to know quite a bit about them, beginning with the question: What can and can’t be done by following
an algorithm?
Turing Machines and the Church-Turing Thesis
in the 1930s a young mathematician at Cambridge University named Alan Turing was considering the
question: Is there an algorithm to determine if any given problem can be solved with an algorithm? To
Figure 3 –
applied algorithms
Chapter 3 – Programming Logic DRAFT September 2018 pg. 13
answer his question, he came up with the concept of a simple theoretical machine that could follow any
algorithm. Today we call his machine a Turing machine.
One of the burning questions in mathematics In the late 1800s and early 1900s, was the decidability
question: Is there a method we can use to look at any math problem and decide if the problem can be
solved? To answer this question, we need a Boolean test – one with a clear yes or no answer – yes, this
problem can be solved, or no, this problem can’t be solved. We need one test that works for all
problems. Some of the best mathematicians of the time – people such as David Hilbert, Kurt Gödel, and
Alonzo Church – worked on what Hilbert called the Entscheidungsproblem (German for decision-making
problem). It turns out that Turing’s question is equivalent to the Entscheidungsproblem.
The truth of mathematics and logic for all real numbers is based on first and second order predicate
logic and a set of axioms, called Peano’s Axioms, after the 19th Century Italian mathematician who
described them. Hilbert and company were trying to prove that math is complete, consistent and
decidable. They had trouble with the decidability part – the Entscheidungsproblem: Is there a method
we can use to look at any math problem and decide if the problem can be solved? 2
Turing realized that this question was the same as what he called the Halting Problem: For all computer
programs, is there a way to tell if any particular program that is running will halt, or continue to run
indefinitely? He thought of his Turing machine as one of the simplest of computing machines, which can
calculate what people can calculate. He thought of it as a tool to examine computation and algorithms.
The work of Alan Turing, along with the work of Alonzo Church from Princeton University, surprised the
world of mathematics by illuminating two important concepts in modern computer science:
1. All mechanical systems of algorithmic computation with real numbers are functionally
equivalent. That is, given an infinite amount of time and an infinite amount of memory, they
can compute exactly the same things. Today this is known as the Church-Turing Thesis. Church3
and Turing4, working independently of each other, released their results in the spring of 1936. At
the time, Church was a Princeton University math professor; Turing was a 23 year old student
who had finished his bachelor’s degree in 1934.
2. The answer to the halting problem, and hence the answer to the Entscheidungsproblem, was no,
math is not decidable. (Gödel suggested the same thing a few years earlier with his
Incompleteness Theorems, but his theorems themselves proved to be incomplete.)
Church was working on a system to describe functional math called lambda calculus. Turing quickly
realized and showed in an appendix to his paper that Church’s theorems based on lambda calculus were
equivalent to his ideas based on the Turing machine; that whatever could be determined in Lambda
2 More specifically, Hilbert asked if there is an algorithm that can be used to decide if any given theorem is true.
3 Church, Alonzo, An Unsolvable Problem of Elementary Number Theory, Amer. Journal of Math., Vol. 58, No. 2. (1936)
4 Alan Turing, On computable numbers, with an application to the Entscheidungsproblem, Proc. London Math. Soc. (1937) s2-42
Chapter 3 – Programming Logic DRAFT September 2018 pg. 14
Calculus, or any other system of logic based on functional algorithms and Peano’s Axioms, could be
determined with a Turing machine. Church’s former student, Stephen Kleene, showed the same thing.
A Turing machine is a theoretical model for a very simple mechanical computer. A Turing machine has:
1. a tape broken up into separate squares, in each of which we can write a symbol. There is no
limit to the length of the tape, it is infinitely long. (Turing mentions that he chose a tape as it is
one-dimensional, as opposed to two dimensional sheets of paper.)
2. a read/write head for the tape. The square under the read/write head is called the current
square. The symbol the machine just read from the current square is called the scanned symbol.
3. a state register, which is a memory that can store the current state of the machine. There are a
finite number of possible states for the machine, listed in a state table.
4. a state table with entries for each possible configuration of state and scanned symbol. A state
table tells the machine what to do for each possible configuration (state, scanned symbol) of he
system. There is a special initial state we can call the start state.
The Turing machine has a machine execution cycle that works like this:
• read the symbol in the current square;
• lookup the configuration in the state table;
• perform an operation based on the lookup;
• set the new state of the machine.
The process is repeated indefinitely, or until the machine reaches a final state and halts.
In each operation, the machine can do one of three things - write a new symbol in the current square,
erase the current square, or leave the current square alone; it then moves the tape to the left one
square or to the right one square.
Here is an example of a state table for a Turing machine:
Figure 4 –
model Turing machine
Chapter 3 – Programming Logic DRAFT September 2018 pg. 15
state scanned symbol
operation* new state
S1 0 R S1 S1 1 P0, R S2 S2 0 R S2 S2 1 P0,R S3
*Pn means print n; L move left, R move right.
This example is only a small part of what could be a much longer state table. We program the machine
by establishing a state table then giving the machine a tape with symbols on it.
Turing was a pioneer in what has come to be known as automata theory. Automata theory is the study
of theoretical computing machines to explore the nature and scope of computation. It involves the
languages of such machines as well as how they operate and what they are able to do. The primary
focus of automata theory is not really the machines, but on learning more about computation, language,
and algorithms.
State diagrams are used in automata theory. A state diagram shows the possible states of a system, and
how the system moves from one state to another. The state diagram shown here is based on the turns
players take in a game of chess.
Each state is represented by a circle, and the events or
activities that cause a change in state are represented by
lines connecting the states. The initial state is represented
by a dark circle. The terminal states, or halting states, are
represented by dark circles with lines around them. The
example on this page shows a very simple view of the
moves in a game of chess. Turing’s state diagrams dealt
with combinations of elementary processes, in which it
takes time to understand the big picture. We shall skip
them for now.
The algorithm for players taking turns in a game of chess is
shown in pseudocode on the next page. In the pseudocode
we can see some items that are not needed in Python, such
as braces to indicate the beginning and end of a block of
instructions. We can also see some structured language that
we have not yet learned about, such as the if and while
instructions.
The if statement sets up conditional execution – part of the algorithm is only executed if a certain
condition is true. The while statement sets up repetition, part of the algorithm forms a loop that is
repeated if a certain condition is true. The conditions are enclosed in parentheses. If you look back at
Figure 5 –
chess state digram
Chapter 3 – Programming Logic DRAFT September 2018 pg. 16
the state diagram, you can find branches and loops there as well. For example, white’s turn, then black’s
turn, then white’s turn, then black’s turn, and so on, is repeated until a checkmate or stalemate occurs.
We are looking at this from a higher-level, so we don’t see the details about board position that
determine if there is a checkmate or stalemate, nor do we see how a player decides what move to
make. Those algorithms would be far more detailed and require massive state tables and long
pseudocode, or more likely, be broken down into many smaller parts that would each be described in
separate units. Our purpose here is simply to see how tools such as state diagrams and pseudocode
illustrate algorithms with the simple example of the flow of moves in a game of chess.
# initialize variables
set checkmate to false
set stalemate to false
set result to “draw”
# when the board is placed in a new position, checkmate and stalemate are set, if applicable
Start the game
while (checkmate and stalemate are both false) {
white moves # white puts the board in a new position
if (checkmate is now true)
result = “White wins”
if (checkmate and stalemate are both false) {
black moves # black puts the board in a new position
if (checkmate is now true)
result = “Black wins”
} # end if (checkmate and stalemate are both false)
} # end while (checkmate and stalemate are both false)
print result
Stop the game
Elements of Logical Structure in Algorithms
Conditional execution and repetition form patterns in the sequential logic of algorithms. These patterns
fall into categories that can be understood as elements of logical structure, which can be combined in a
myriad of ways to form the algorithms we see in modern software. Programmers who are familiar with
elements of logical structure can more easily create and edit computer programs. They can use
elements of logical structure like building blocks as they design and build software.
Think about how this compares to a plumber or an electrician. A person who wishes to design a
plumbing system for a building, such as a residential home, has a selection of existing parts from which
to choose. We can see these parts in a hardware store – elbow joints, T- joints, certain kinds of valves,
and so on. Despite the differences from one home to another, the plumbing systems will mostly be
Figure 6 –
chess pseudocode
Chapter 3 – Programming Logic DRAFT September 2018 pg. 17
composed of the same parts, which we might think of as the elements of a plumbing system. The
architects and plumbers who will design and build the system need to be familiar with each of the
elements and how they fit together.
The same thing is true for an electrical system. The electrical engineers and electricians who design and
build such systems need to be familiar with the electrical parts that are available, how they work, and
how they fit together. Switches, wires, outlets, junction boxes, circuit breakers, and so on, can be
thought of as the building blocks or elements of electrical systems.
So it is with the logical structure of algorithms. The elements of logical structure are the building blocks
we can put together to design and create algorithms. But, just what are these elements of logical
structure? How many of them do we need to learn about? The answer is: surprisingly few.
We don’t need hundreds or even dozens of different kinds of parts such as plumbers and electricians
would need to build their systems. In 1966 an Italian computer scientist, Corrado Böhm and his student,
Giuseppe Jacopini, published a paper in the Communications of the ACM showing that all algorithms are
composed of three basic elements of logical structure, each one a sequence of instructions: 5
• linear sequences
• selection sequences (conditional execution)
• repetition sequences
A more abstract equivalent of Böhm and Jacopini’s work
was contained in the work of Stephen Kleene in the
1930s, but Böhm and Jacopini’s 1966 paper captures the
move toward structured programming that was
happening in the 1960s and 1970s. Most modern
programming languages, including Python, have
branching and looping instructions based on what was
happening then with languages like ALGOL, C and Pascal,
whose underlying basis in sequential logic was described
by Böhm and Jacopini.
5Corrado Böhm, Giuseppe Jacopini Flow diagrams, Turing machines and languages with only two formation rules, Communications of the ACM, Volume 9 Issue 5, May 1966 available online at: http://dl.acm.org/citation.cfm?id=365646
Figure 7 –
Böhm and Jacopini flow diagrams
Chapter 3 – Programming Logic DRAFT September 2018 pg. 18
(People) != (Turing Machines)
Programmers must bridge the logical divide between the way computers work and the way
people think. Computers are algorithmic and precise. They follow instructions step-by-step
doing exactly what each instruction says to do, whereas, people are generally not
algorithmic.
People think heuristically. They are constantly looking for shortcuts and trying new ways
to do things. They are creative and intelligent, interpreting language to see what it really
means. But because of this, they often don’t follow directions very well, and are often
imprecise in their use of language. People are not Turing machines.
This can cause problems for programmers who must turn the heuristic logic of what people
say into the algorithmic logic of a computer program. Here is an example:
A boss says to a computer programmer: “Give me a list of all the people who live in
Pennsylvania and New Jersey.” What should the Boolean expression in our code look like,
assuming each person can only live in one state? The expression will be part of a loop,
looking at the data for each person, one at a time.
If we write (state == “PA” and state == “NJ”) our list will be empty. The variable state
cannot be equal to both PA and NJ at the same time. We need to write:
(state == “PA” or state == “NJ”) to get one list with each person who lives in Pennsylvania
or who lives in New Jersey. If state = “PA”, the condition will be true, and the person will
be included in the list. If state = “NJ”, the condition will be true and the person will be
included in the list. We will end up with one list with all of the people who live in
Pennsylvania and all of the people who live in New Jersey.
The boss is not using proper Boolean language. Yet, a programmer who understands
Boolean logic will most likely understand the boss and translate the request properly. This
example illustrates the difference between how people think and how computers work. It
also shows that programmers are often called upon to help bridge that gap.
Chapter 3 – Programming Logic DRAFT September 2018 pg. 19
Tools for Describing Algorithms
Böhm and Jacopini used a system they called flow diagrams to describe their work. Figure 7 on page 18
is an image from their manuscript showing basic flow diagrams. They weren’t the first to use such
diagrams, which had been around in business and industry since the 1920s. The diagrams later became
known as flowcharts. A flow chart is a diagram showing the logical flow and structure of an algorithm.
In CSCI 111, 112, and 211 we will see many other tools for describing software systems in general and
algorithms in particular, such as state tables and pseudocode like we saw above, and various UML
diagrams. For now, we will use two simple tools to illustrate the elements of logical structure in
algorithms: simple flowcharts, similar to Böhm and Jacopini’s, and pseudocode.
Today pseudocode is the most common tool used to describe and discuss algorithms. We saw in
chapter 2 that pseudocode is somewhere between a human language like English and a formal coding
language like Python or Java. It might be thought of as structured English, which is easy to read, but
which has language structures such as [if…then…else…] and [for count = 1 to n] to describe branching
and looping in algorithms.
The following example describes an algorithm using both pseudocode and a flowchart.
* * * * * * * * * * * * * * * Guessing Game Example * * * * * * * * * * * * * * * * * * * * * * * * * * * *
We wish to create a computer program for a guessing game. The computer will pick a random integer
between 1 and 100, and then ask the user to guess the number.
If the user’s guess is not correct, then the program should tell the user that the guess is either too low or
too high and allow the user to guess again. This process should continue until the user enters the
correct guess. Once the user enters the correct guess, the computer should tell the user that the guess
is correct, along with the number of guesses it took to get the correct number.
Here is a sample run of the program:
I am thinking of a number between 1 and 100.
Try to guess what it is.
Your guess?
50
Too low. Try again.
Your guess?
75
Too High. Try Again.
Your guess?
63
Too Low. Try Again.
Your guess?
69
Too High. Try Again.
Your guess?
66
Too High. Try Again.
Your guess?
65
Too High. Try Again.
Your guess?
64
Correct! The number is 64
It took you 7 guesses
The psuedocode for the algorithm is shown on the next page:
Chapter 3 – Programming Logic DRAFT September 2018 pg. 20
start
int pick # the number the computer picks
int guess = 0 # the user’s guess, initialized to zero
int count = 0 # the number of guesses
pick = a random number between 1 and 100
print “I am thinking of a number between 1 and 100.”
print ”Try to guess what it is.”
print” Your guess?”
user inputs guess # get value of guess from the keyboard input
while (guess ≠ pick) # set up a loop to repeat until the user guesses the number
{
increment count # keep track of how many guesses
if (guess < pick) # in the loop guess cannot equal pick: it will be low or high
print “Too low. Try again.”
else
print “too high. Try again.”
print ”Your guess?”
user inputs guess # get value of guess from the keyboard input
} # end while (guess ≠ pick), the loop ends when guess = pick
print “Correct. The number is ” + pick
print “It took you ” + count + “ guesses”
stop
We can see in the above example that pseudocode is somewhere between English and a programming
language. Quoting from the book Introduction to Algorithms by Cormen, Lierson and Rivest: 6
“What separates pseudocode from ‘real’ code is that in pseudocode, we employ whatever
expressive method is most clear and concise to specify a given algorithm. Sometimes the clearest
method is English, so don’t be surprised if you come across an English expression or phrase
embedded within a section of ‘real’ code. Another difference between pseudocode and real code
is that pseudocode is not typically concerned with issues of software engineering. Issues of data
abstraction, modularity, and error handling are often ignored in order to convey the essence of
the algorithm more concisely.”
6 Cormen, Thomas; Lierson, Charles; and Rivest, Ronald; An Introduction to Algorithms; MIT Press; 1990 pg. 2 This text is an important work on algorithms, used in many advanced courses in algorithms.
Figure 8 –
guessing game pseudocode
Chapter 3 – Programming Logic DRAFT September 2018 pg. 21
Pseudocode often uses mixed terminology – language from both the problem domain and the
implementation domain. The problem domain is the environment in which the need for software arises,
such as a specific business or engineering environment. It is the world of the user of an application. The
implementation domain for software is the programming environment. Pseudocode is developed as we
move from specifications in the problem domain to code in the implementation domain. We need to
watch for terms from the problem domain that have specialized meaning, perhaps working with an
expert on the problem domain or a specially trained systems analyst to clarify language.
Pseudocode uses programming terms from the implementation domain, such as if…else and while, that
have a specific meaning for people with knowledge of structured programming languages, such as C,
C++, Java, and Python. Terms such as if, while, and for, generally are used the same way in pseudocode
as in these languages. We will use such terms as they are defined in Python, but with less formal syntax.
As we learn about conditional execution and repetition in Python, we will be learning terminology
needed to understand pseudocode.
The flowchart for the same algorithm as the pseudocode in Figure 8 is shown here:
A flowchart may appear to be more formal and precise than pseudocode, but looks can be deceiving.
Details about such things as initializing variables, how variables are used in conditions, how messages
Figure 9 –
guessing game flowchart
Chapter 3 – Programming Logic DRAFT September 2018 pg. 22
are displayed, and so on, often are not shown in a flowchart. A flowchart is a good map of the logical
flow in an algorithm, illustrating branching and looping very well, but often lacking other critical details.
In an attempt to rectify this, companies like IBM in the mid-to-late 20th Century introduced many
additional flowchart symbols and rules. IBM actually had a 40-page manual for flowcharting with
several dozen different symbols and a series of templates to draw flowcharts by hand, like the one
shown here:7.
However, drawing complicated flowcharts can make programming more cumbersome, not easier.
Today the use of complicated flowcharts in software development has fallen out of favor, in part
because of better use of structured language and the emergence of UML. They are still used to define
business processes, in accordance with ISO standards for business process management and information
systems, but used far less often by programmers to describe the details of an algorithm. We will use a
simple version of flowcharting to illustrate the elements of logical structure found in our algorithms.
Böhm and Jacopini’s flow diagrams were very simple. They had only two symbols: rectangles to show
each step in an algorithm, and diamond-shaped boxes to show what they called a logical predicative.
More commonly, a logical predicative is called a predicate or a conditional. To say that one thing is
predicated on another means that one thing is determined by another. In other words, there is some
condition that will determine what happens next.
We will use only four symbols: rectangles and diamonds as Böhm and Jacopini did, along with a black
circle marking the beginning of an algorithm and black circles with another circle around them to
represent the end of an algorithm. These symbols are the same as those used in UML activity diagrams.
Effectively, we are using UML activity diagrams to illustrate the logical structures found in all algorithms
– linear sequences, selections sequences (branching) and repetition sequences (loops).
7 IBM flowcharting template courtesy of Walt Johnson, retired CCP professor of Computer Information Systems and former IBM Systems Engineer.
Figure 10 –
IBM flow chart template
Chapter 3 – Programming Logic DRAFT September 2018 pg. 23
individual steps in an algorithm are shown on a flowchart using rectangles. There is one line entering
each rectangle and one line exiting each rectangle to show the flow of a sequence of instructions. A
diamond is used when branching occurs, with the condition for branching clearly stated in the diamond
and multiple exits from the diamond, each with labels showing which values will cause the branching
routine to select that branch of the algorithm. One-way connecting lines should be vertical or horizontal
only, with directional arrows (but not too many arrows). In general, since a flowchart is used to help us
see the logical structure of an algorithm, we should keep it clear and concise, doing what we can to
make it easy to understand.
In the rest of this chapter we will briefly look at linear sequences, then focus on conditional execution –
also known as branching. We will explore repetition in the next chapter.
Linear Sequences
The simplest element of logical structure in an algorithm is a linear sequence, in which one instruction
follows another as if in a straight line. The most notable characteristic of a linear sequence is that it has
no branching or looping routines – there is only one path of logic through the sequence. It does not
divide into separate paths, and nothing is repeated.
On a flowchart or activity diagram, this appears just as the name suggests, as a single path of logic,
which would always be executed one step after another, as shown here.
Linear sequences seem simple, but programmers need to make sure that linear sequences meet the
following criteria:
• They should have a clear starting and ending point.
• Entry and exit conditions need to be clearly stated. What conditions need
to exist before the sequence starts? What can we expect the situation (the
state of the system) to be when the sequence is finished?
• The sequence of instructions needs to be complete. Programmers need to
be sure not to leave out any necessary steps. (This can be harder than you
might expect.)
• The sequence of instructions needs to be in the proper order.
• Each instruction in the sequence needs to be correct. If one step in an
algorithm is incorrect, then the whole algorithm could be incorrect.
In short, linear sequences must be complete, correct, and in the proper order, with clear entry and exit
conditions.
Linear sequences can be identified in pseudocode by the absence of branching and looping instructions
– one instruction after another with no language indicating branching or looping. The same is true in
most computer programming languages.
Chapter 3 – Programming Logic DRAFT September 2018 pg. 24
CheckPoint 3.2
1. What does the Church-Turing Thesis tell us?
2. What is a Turing machine and how is it related to Automata Theory?
3. List and briefly describe the three elements of logical structure in algorithms, as shown by Böhm
and Jacopini.
4. What are pseudocode and flowcharts and how are they used to describe algorithms?
5. Summarize the criteria that should be met by linear sequences in algorithms.
Conditional Execution (Branching )
A selection sequence, or conditional execution, occurs whenever the path or flow of sequential logic in
an algorithm splits into two or more paths. As an example of a selection sequence, consider this
example of a student who has chemistry lab at 2:00 p.m. on Fridays only:
start
if (Today is Friday)
(Get to chemistry lab by 2:00 p.m.)
stop
Each path is called a branch, so selection sequences are also
known as branching routines. They establish conditional
execution of part of an algorithm.
Binary Branching – Bypass vs. Choice
Whenever conditional execution divides an algorithm into two, and only two, possible paths we have
binary branching. If there are more than two paths, then it is called multiple branching. “Would you
like vanilla ice cream?” is a binary question – it has two possible answers, yes and no. “What flavor ice
cream would you like?” is a question with multiple possible answers, not just yes or no. Binary branching
is similar to the first question above; multiple branching is similar to the second.
There are two forms of binary branching: a binary bypass and a binary choice.
binary bypass
binary choice
Chapter 3 – Programming Logic DRAFT September 2018 pg. 25
In a binary bypass, part of an algorithm is either executed or bypassed. In a binary choice, one of two
parts of an algorithm is chosen. The difference between a bypass and a choice is subtle but significant.
In a binary bypass, it is possible that nothing happens, whereas in a binary choice, one of the two
instructions will be executed, but not both.
In pseudocode, a bypass is equivalent to: IF (condition) THEN (instruction) structure. (Note that in all of
these examples a single instruction could be replaced by block of instructions.) If the condition is true,
then the instruction is executed; if the instruction is not true, then the instruction is ignored, and
nothing happens. The chemistry lab example above shows a binary bypass.
A binary choice is equivalent to an IF (condition) THEN (instruction A) ELSE (instruction B) structure. If the
condition is true, then instruction A is executed; if the instruction is not true, then instruction B is
executed. Either instruction A or instruction B will be executed, but not both. One of the two is always
executed, as seen in the example below.
A student has Math class on Monday, Wednesday, and Friday, and History class on Tuesday and
Thursday. We will assume the student only needs to consider weekdays and not weekends:
start
if (today is Monday, or today is Wednesday, or today is Friday)
(go to math class)
else
(go to history class)
stop
The student will always go to either Math class or History class, but not both at the same time.
Binary Branching in Python
The if and if … else statements set up binary branching in Python. The if statement sets up simple
conditional execution, sometimes also called a binary bypass as we saw above. If the condition is true,
the instruction or block of instructions following the if statement is executed; if the condition is false,
the instruction or block of instructions is bypassed. The terms if and else in Python are both lowercase.
The Boolean condition following if could be in parentheses, but they are not required.
In Python, A colon is used after the condition in an if statement and the instruction or block of
instructions to be executed are indented:
if hours > 40:
grossPay = regular pay + (hours-40) * rate * .5
Chapter 3 – Programming Logic DRAFT September 2018 pg. 26
Indentation is used in python to mark a block of code. all of the statement indented in an if statement
will be executed an one block of code if the condition is true. In the example below, the three
statements indented become a block of code to be executed if the condition (hours > 40) is true.
if hours > 40:
regular pay = hours * rate
overtime pay = (hours-40) * rate * 1.5
grosspay = regular pay + overtime pay
A colon and Indentation are also used following else and in an if…else… statement.
Here are some additional examples of Python if statements:
# example 1 - if statement - simple conditional execution – binary bypass
if (temp > 98.6):
print("The patient has a fever")
# example 2 – if statement – binary bypass – a block of code
if (temp > 98.6):
print("The patient has a fever.")
print("Please have blood work done to check for an infection.")
# end if (temp > 98.6)
# example 3 – if else statement – binary choice
if (temp > 98.6):
print("The patient has a fever")
else:
print("The patient’s temperature is normal")
#example 4 – if statement – binary bypass – checking a range of values
if (temp > 97.0) AND (temp < 99.0):
print("The patient’s temperature is in the normal range.”)
#example 5 – if else statement – binary choice – two blocks of code
if (temp > 98.6):
print("The patient has a fever.")
print("Please have blood work done to check for an infection.")
# end if (temp > 98.6)
else:
print("The patient’s temperature is normal.")
print("Please check blood pressure and pulse.")
# end else (temp > 98.6)
Figure 12 –
examples of
binary branching
Chapter 3 – Programming Logic DRAFT September 2018 pg. 27
Multiple Branching
As we saw earlier, multiple branching occurs when the path of logic in an algorithm divides into many
different paths based on a single condition, such as “What flavor ice cream would you like?” It is not a
true or false question, but one with many different possible answers.
A flowchart showing this might look something like a pitch fork, as shown in Figure 13:
A multiple branching routine is equivalent to a series of binary branching routines. Consider the ice
cream question. Instead of asking the multiple branching question, “What flavor ice cream would you
like?”, a series of binary questions could be asked – “Would you like vanilla ice cream?”, “Would you like
chocolate ice cream?”, “Would you like strawberry ice cream?”, and so on.
There are two ways to do this: as independent binary branching routines or as a set of nested binary
branching routines.
Independent binary branching could be an inefficient solution. Consider the following psuedocode:
if (flavor = vanilla)
get vanilla
if (flavor = chocolate)
get chocolate
if (flavor = strwaberry)
get strawberry
…and so on.
Figure 13 –
multiple branching
Chapter 3 – Programming Logic DRAFT September 2018 pg. 28
If the flavor does equal vanilla, and there can be only one flavor, the if routines that follow for
chocolate, strawberry, and so on, are still executed, even though we know that they will be false.
A better solution is to implement a set of nested binary branching routines. If the answer to any one of
these questions is yes, then the branching is complete, if not, then the algorithm moves on to the next
binary selection.
The flowchart and pseudocode in Figure 14 shows the same ice cream question as above, but as a series
as a set of nested if… else… statements, with the second if… else… enclosed in the else portion of the
first if… else… , the third nested in the else portion of the second if… else…, and so on.
start
if (flavor = vanilla)
get vanilla
else
if (flavor = chocolate)
get chocolate
else
if (flavor = strawberry)
get strawberry
else
if (flavor = pistachio)
get pistachio
else
get chocolate chip
deliver
stop
We can see from the flowchart and pseudocode that if any one of the if conditions is true, the remaining
if routines are bypassed. This is a result of the nesting.
Figure 14 –
nested if...else statements
Chapter 3 – Programming Logic DRAFT September 2018 pg. 29
The flowchart matches the pseudocode logically and shows that as soon as there is a true condition we
break out of the chain of if… else… statements. However, its arrangement doesn’t give the same clear
impression of the nested if.. else… structure that the pseudocode does.
The flowchart in Figure15 is logically the same, but it shows the if… else... nesting more clearly.
Nested if…else… statements are preferable to a series of independent if statements, but they can
become messy if there are too many choices. What would this look like if we have 28 flavors of ice
cream to choose from?
Here is code similar to situation above with four choices in above in Python:
Figure 15 –
nested if...else statements
Chapter 3 – Programming Logic DRAFT September 2018 pg. 30
if flavor = "vanilla":
print("vanilla")
else:
if flavor = "chocolate":
print("chocolate ")
else:
if flavor = "pistachio":
print("pistachio")
else:
print("chocolate chip")
Notice that in the above example chocolate chip becomes a default choice. If none of the if conditions
are true, chocolate chip is printed. It is often better to have a default that indicates none of the
available options were chosen, as in the following:
if flavor = "vanilla":
print("vanilla")
else:
if flavor = "chocolate":
print("chocolate ")
else:
if flavor = "pistachio":
print("pistachio")
else:
if flavor = "chocolate chip":
print("chocolate chip")
else:
print("Your choice was not on the menu.")
Pythons elif statement
Python has a an elif statement that can be used to simplify such nested branching. An elif statement
takes the place of an else clause that is immediately followed by another if statement in nested
branching. Like else, elif only needs to be indented to the same level as the corresponding if statement.
Here is the example from above using elif:
if flavor = "vanilla":
print("vanilla")
elif flavor = "chocolate" :
print("chocolate ")
elif flavor = "pistachio":
print("pistachio")
elif flavor = "chocolate chip":
print("chocolate chip")
else:
print("Your choice was not on the menu.")
Chapter 3 – Programming Logic DRAFT September 2018 pg. 31
CheckPoint 3.3
1. What is the difference between a binary bypass and a binary choice in an algorithm?
2. Show how to establish a binary bypass in Python.
3. Show how to establish a binary choice in Python.
4. Show how to use nested else clauses to establish multiple branching in Python.
5. Show how to use elif for multiple branching in Python.
Chapter 3 – Programming Logic DRAFT September 2018 pg. 32
Lab Reports and Collaborative Editing
Lab reports are an important part of computer programming courses. They are similar to project
documentation and help you to prepare for writing project documentation, which is an important part
of professional programming.
Computer Science 111 Lab Report
A template for programming lab reports for Computer Science 111 is included in the files for Week 3 in
Canvas. Unless directed to do something different by the assignment, a programming lab report
should include the following five sections:
a. Heading
Include your name, course and section number, semester, and identification of the assignment.
b. Assignment Analysis and Design
In your own words, describe the problem including input and output. Briefly describe how you
developed your code. Briefly describe what your code does and how it works – including anything
different or unique or special that you did in your software. If the software is long or complicated,
describe how it is organized. Include a copy of any pseudocode or other design documents you used.
If you worked with anyone else, asked anyone for help, or looked anything up, then mention it here.
Include proper references to source material.
c. Assignment Code
Include the code for your assignment as directed by the assignment or by your instructor. In most
cases, this will be a zipped copy of the source code file for your program attached to the report. You
can put the report and the program all in one zipped folder. In the report, either tell the reader that
the code is in an attached file or include the code.
A zipped folder may contain another zipped folder. In Java, You could copy the zipped folder for a
NetBeans project and your lab report into a folder for your assignment, then zip the assignment
folder. Alternatively, you could copy the report into your NetBeans project’s folder before zipping it.
Your instructor may have specific requirements for this.
d. Assignment Testing
Describe how you tested this program to verify that it runs correctly.
e. Assignment Evaluation
Briefly describe what you learned from this project. What things did you struggle with? What was
easy? Give your opinions of the process, including what you liked about the project and any
suggestions you have for improving the project.
The report does not need to be long, but it should be complete.
Chapter 3 – Programming Logic DRAFT September 2018 pg. 33
Collaborative Editing of Word Documents
From time to time it will be necessary to work on programming projects with other people. This
happens more often than not in a professional environment. You should know how to use Document
Markup and Review features in Word to markup and comment on what other people have written, and
to edit your own documents that have been marked by others.
The notes below are for Office 2013. There are similar features in other versions of Word.
There are two things you can do to mark and edit an existing document:
1. make changes to the document with Track Changes turned on;
2. add document comments to the document.
The Track Changes feature and the comment feature are both found on the Review Ribbon in Word
2013, as shown below:
These features are easy to use, as described below. Several short tutorials for tracking changes and
commenting in Word are available on the Web. See the following:
• from Microsoft: http://office.microsoft.com/en-us/support/results.aspx?ctags=CH010372680
• from Office consultant Shauna Kelly,: http://shaunakelly.com/word/sharing/howtrackchangesworks.html
• a YouTube video from a graduate student: http://www.youtube.com/watch?v=AUf-IxzXyVk
Tracking Changes
To use track changes, click the Track Changes button to turn the feature on. The button works like a
toggle switch – each time you click the button it changes the track changes setting to either on if it is off,
or off if it is on. When it is on, any changes you make in the document will show up as editor’s marks in
the document.
The settings to the right of the Track Changes button allows you to see the final document with the
markup, to see what the original document looked like without the markup, or to see what the final
New Comment
Button
Track Changes
switch
Track Changes
navigation Comment
navigation
Figure 25 –
Track Changes
in Word 2013
Chapter 3 – Programming Logic DRAFT September 2018 pg. 34
document looks like without the markup. You should experiment with Track Changes in Word to get a
feeling for how it works. Open an old document and experiment with the settings while making changes
to the document.
If someone sends you a document with changes that were made while Track Changes was on, you can
change the Track Changes settings to see the document showing the markup, to see it as it originally
was, or to see what the final document looks like without the markup.
Starting from the beginning of your document, you can use the Track Changes navigation buttons to
move through the document from one change to another, accepting or rejecting the changes.
Document Comments
To place comments in a document without changing the document, select the location where you want
to comment or click the item you wish to comment on, then click the New Comment button on the
Review pane.
If someone sends you a document with comments, you can move from one comment to another or
delete comments using the comment navigation buttons to the right of the New Comment button.
Just as with track changes, it is best to open an existing document and experiment with document
comments.
Lab 3A – Body Mass Index
Here is a program that will make you popular with your friends and family. According to the Centers for
Disease Control, 8 “Body Mass Index (BMI) is a number calculated from a person's weight and height.
BMI is an inexpensive and easy-to-perform method of screening for weight categories that may lead to
health problems.” The formula for BMI using weight in pounds and height in inches and a table showing
the standard weight status categories associated with BMI ranges for adults are given here:
BMI = 𝑾
𝑯𝟐 ∗ 703
𝑾 is weight in pounds
𝑯 is height in inches
BMI Weight Category
BMI < 18.5 underweight
18.5 ≤ BMI < 25 normal
25 ≤ BMI < 30 overweight
BMI ≥ 30 obese
We wish to design a program that will ask the user for height and weight and then calculate and display
the person’s BMI and BMI category.
STEP 1.
We will start by writing the BMI formula as a valid Python assignment statement:
bmi = wt / (ht * ht) * 703
STEP 2.
8 The CDC Body Mass Index Web page can be found at: http://www.cdc.gov/healthyweight/assessing/bmi
Chapter 3 – Programming Logic DRAFT September 2018 pg. 35
Next, we need to write the categories in the table as Boolean expressions in Python. The first and last
conditions are okay as they appear in the table, but the two middle conditions need to be rewritten.
They are ranges of values. All four would look like this as Python Boolean conditions:
underweight bmi < 18.5
normal 18.5 <= bmi AND bmi < 25.0
overweight 25.0 <= bmi AND bmi < 30.0
obese bmi >= 30.0
STEP 3.
What variables will we need?
height; # person’s height in inches
weight; # person’s weight in pounds
bmi; # person’s calculated body mass index
category; # the BMI category
STEP 4.
Now we are ready to design our algorithm and describe it using pseudocode.
# Body Mass Index calculator
height # person’s height in inches
weight # person’s weight in pounds
bmi # person’s calculated body mass index
category # the BMI category
print opening message
get person’s height
get person’s weight
# calculate BMI using CDC formula
bmi = wt / (ht * ht) * 703
# determine BMI category
if ( bmi < 18.5 )
category = “underweight”
else if ( bmi < 25.0 )
category = “normal”
else if (( bmi < 30.0 )
category = “overweight”
else
category = “obese”;
print results – BMI and BMI category message
END
Figure 28 –
BMI Algorithm
STEP 5 It is left for you to complete the exercise by converting this to Python code and
getting the program to run as a program named bmiCalculator.
Chapter 3 – Programming Logic DRAFT September 2018 pg. 36
Lab 3B – Quadratic Equations
A second-degree polynomial, such as 𝑥2 + 2𝑥 − 8 = 0 has the standard form 𝑎𝑥2 + 𝑏𝑥 + 𝑐 = 0.
a, b and c are the coefficients of the equation. The values for x, called the roots of the equation, can be
found using the quadratic formula x = −𝑏±√𝑏2−4𝑎𝑐
2𝑎 .
The term (𝑏2 − 4𝑎𝑐) in the quadratic formula is called the discriminant. It could be negative, zero, or
positive. This will tell us how many roots a quadratic has:
• If (𝑏2 − 4𝑎𝑐) is negative, the equation has no real roots, since a negative number has no square
root.
• If (𝑏2 − 4𝑎𝑐) is zero, then its square root is zero, and since (–b + 0) = (–b – 0), the equation has
one real root: –𝑏
2𝑎 .
• If (𝑏2 − 4𝑎𝑐) is positive, the equation has two real roots: x1 = −𝑏−√𝑏2−4𝑎𝑐
2𝑎 and
x2 = −𝑏+√𝑏2−4𝑎𝑐
2𝑎 . A positive number has two square roots. For example, both 4 and -4 are √16.
Quadratic equations could represent ballistics, such as a thrown baseball. If we ask the question “When
will the baseball be exactly 50 ft. above the ground?”, the answer could be twice if it is thrown high
enough and hard enough, once on the way up and once on the way down; once if it just reaches 50 ft. at
its peak; or never if it isn’t thrown hard enough to reach 50 ft. The roots of a quadratic equation
representing ballistics could answer the question. We could have two roots, one root, or no roots.
We wish to design a program to solve quadratic equations. in standard form. The software should:
• ask for the three coefficients, then calculate the discriminant.
• If the discriminant is negative, the software should tell the user there are no real roots.
• If the discriminant is zero, it should tell the user there is one real root and calculate and display
the root.
• If the discriminant is positive, it should tell the user there are two real roots and calculate and
display the roots. We start by defining the algorithm with pseudocode and a flowchart:
Figure 35 –
Quadratic Roots
Chapter 3 – Programming Logic DRAFT September 2018 pg. 37
Finding the Roots of a Quadratic Equation
start
a # coefficient of x2
b # coefficient of x
c # constant term
disc # the discriminant
root1 # the first root or only root if there is a single root
root2 # the second root
get values of the coefficients a, b, and c from the user
calculate the discriminant disc = 𝑏2 − 4𝑎𝑐
if (disc < 0)
# no real roots
print appropriate message
else if (disc = 0)
# one real root
root1 = –𝑏
2𝑎
display root1
else
# two real roots
root1 = −𝑏−√𝑏2−4𝑎𝑐
2𝑎
root2 = −𝑏+√𝑏2−4𝑎𝑐
2𝑎
display both roots
stop
Once we have pseudocode that seems to be correct, we can start to turn the pseudocode into
comments and begin building our program, as shown on the next page.
Figure 36 –
Quadratic Roots Algorithm
Chapter 3 – Programming Logic DRAFT September 2018 pg. 38
a = 0.0 # coefficient of x2
b = 0.0 # coefficient of x
c = 0.0 # constant term
disc = 0.0 # the discriminant
root1 = 0.0 # the first root or only root if there is a single root
root2 = 0.0 # the second root
# get coefficient a from the user
a = float( input("Enter the value of A: ")
# get coefficient b from the user
b = float( input("Enter the value of B: ")
# get coefficient c from the user
b = float( input("Enter the value of C: ")
# calculate the discriminant
disc = b*b – (4.0 * a * c)
if (disc < 0.0):
# print no real roots
print("No real roots")
elif (disc == 0.0):
# calculate and print one real root
root1 = ( -b ) / ( 2.0*a )
print("One real root:\n\t", root1)
else
# calculate print two real roots
root1 = ( -b - math.sqrt(disc) ) / ( 2.0*a )
root2 = ( -b + math.sqrt(disc) ) / ( 2*a )
print("Two real roots:\n\t", root1, "\n\t", root2)
Here is some data to test your software.
A B C result
1 1 12 no real roots
1 - 6 9 one root 3
1 2 -8 two roots -4, 2
Figure 37 – developing comments and code
for a quadratic roots algorithm
Chapter 3 – Programming Logic DRAFT September 2018 pg. 39
Key Terms in Chapter 3
After completing this chapter, You should be able to define each of the following key terms:
AND, 8
Automata theory, 15
binary branching, 24
binary bypass, 25
binary choice, 25
Boolean algebra, 4
Boolean expression, 5
Boolean literals, 5
Boolean logic, 4
Church-Turing Thesis, 13
collating sequence, 6
conditional execution, 15
conjunction, 7
De Morgan’s laws, 8
decidability question, 13
derived Boolean operations, 8
disjunction, 7
elif, 25
else, 25
flow chart, 19
Halting Problem, 13
if, 25
implementation domain, 21
inverting , 8
lexicographic order, 6
linear sequence, 23
multiple branching, 24
NAND, 8
negation, 7
NOR, 8
NOT, 8
OR, 8
problem domain, 21
relation operation, 5
repetition, 15
state diagram, 15
state table, 14
Turing machine, 13
XOR, 8
Chapter 3 – Questions
1. What values can be used in Boolean logic? How is Boolean logic different from Boolean algebra? How
do computers derive Boolean values? How else can a Boolean variable obtain a true or false value?
2. What are the six Boolean relational operations? What operators are used for these operations in
Python? How is an equality operator different from a relational operator?
3. What does Python use as a collating sequence for text data? What are some other programming
languages that use the same collating sequence? Which of these operating systems use the same
collating sequence: Microsoft Windows, Apple OS X, most versions of Unix, and most newer Android
operating systems? What is the order of the following characters using Python’s collating sequence: a, B,
A, and b?
4. What are the names of the three primary logical operations in Boolean logic, and what words are used
to represent each of them? Which of these is a unary operation and what does that mean? Which
operation yields a true value, given a true value and a false value? Which operation yields a false value,
given a true value and a false value?
Chapter 3 – Programming Logic DRAFT September 2018 pg. 40
5. Which of the Boolean logical operations are commutative and what does that mean? Which are
associative and what does that mean? Which are distributive? What are the two versions of
De Morgan’s laws? What statement using the OR operation would be equivalent to saying NOT (A and
B)?
6. What are three common derived Boolean operations? How are primary and derived Booelan operations
important in the design and manufacture of computer chips?
7. What operators are used in Python for the three primary Boolean operations? In the absence of
parentheses, which of these operations takes precedence over another?
8. Who was Alan Turing? What is a Turing machine? How is his Halting Problem related to Hilbert’s
Entscheidungsproblem?
9. What is Lambda Calculus? Who developed Lambda Calculus? What does the Church-Turing Thesis tell us
about the relationship between what can be calculated with a Turing machine and what can be
calculated with Lambda Calculus?
10. What is the focus of automata theory? What two things does a state diagram show us about a system?
11. Why are the elements of logical structure important in designing and creating algorithms? What are the
three elements of logical structure described by Bohm and Jacopini? What tool is most commonly used
today to describe and discuss algorithms?
12. What is the difference between a problem domain and an implementation domain? Language from
which of these domains is used in Pseudocode? How is pseudocode related to these two domains?
13. What are the four symbols used in flowcharts in this chapter that are the same as in UML activity
diagrams? What does each of them represent?
14. What criteria do programmers need to make sure linear sequences meet? How can we identify linear
sequences in pseudocode and computer software?
15. What is the difference between a binary bypass and a binary choice? What statements are used in
Python for each of these?
Chapter 3 – Exercises
1. Write each of the following as valid Python Boolean expressions: (Pay attention to data types.)
A. length of a fish greater than or equal to 22 inches
B. joint income greater than $17,400 and less than or equal to $70,700
C. name less than “Smith”
D. water level greater than 5 feet and less than 14 feet
E. number of students less than 36
2. Write each of each of the three derived logical operations described on page 6 – NAND, NOR, and XOR –
as Python Boolean expressions using only and, or, and not.
Chapter 3 – Programming Logic DRAFT September 2018 pg. 41
3. We have three variables: age, weight and height. An airbag warning sign on the sun visor in the front of
a car says “Passenger must be at least 12 years old, with a weight of at least 75 pounds or a height of at
least 57 inches” to sit in the front seat. Write this rule as a Boolean expression.
4. In most states in the US, a vehicle must stop at an intersection with a traffic light when the traffic light is
red, except when making a right turn, in which case the driver must pause and can then make a right
turn on red if the way is clear, unless otherwise posted. At a particular intersection there is a sign that
says, “No right turn on red, 6 am to 6 pm, except Saturdays and Sundays.” Write the set of rules and
conditions for this intersection as an if…else statement with a single Boolean expression of the form:
if (Boolean condition)
right turn on red
else
no right turn on red
5. Which of the following does not contain a valid Boolean expression, and why?
a. If (romeDistance < veniceDistance OR naplesDistance)
b. If (count > 10 AND count < 20)
c. While (count < 5 AND > 1)
d. While (height < count OR height < 12.5)
e. If (message = “Hello, World.” OR “Hello, World!”)
6. We can test for divisibility by performing a remaindering operation (the % operator in Python) on a
numeric value. If A % B is 0, then A is divisible by B. For example, (15 % 3) = 0, so 15 is divisible by 3. The
rule for determining if a year is a leap year can be found at the U.S. Naval Observatory’s Website online
at http://aa.usno.navy.mil/faq/docs/leap_years.php
Create a Python program that asks the user for the year, determines if the year is a leap year, then gives
the user the result.
7. CCP Airways has a frequent flyer program that rewards people with frequent flyer miles in different
categories, as follows:
• up to 10,000 miles CCP Flyer
• 10,000 to 24,999 miles CCP Silver Flyer
• 25,000 to 50,000 miles CCP Gold Flyer
• more than 50,000 miles CCP Platinum Flyer
Create a Python application that asks for the user’s number of CCP Airways frequent flyer miles, then
determines and displays the user’s frequent flyer status.
8. A company determines an employee’s pay based on hours times rate, with “time and a half for
overtime”. Overtime is more than 40 hours in one week. If an employee works more than 40 hours, the
gross pay is equal to the regular pay for 40 hours, plus 1.5 times the rate for overtime hours.
Chapter 3 – Programming Logic DRAFT September 2018 pg. 42
Create a Python payroll program that prompts the user to enter the employee’s name, hours, and rate;
calculate gross pay; then prints a report with the employee’s data – name, hours, rate and gross pay.
9. A university recognizes graduates with high GPA’s in different honors categories using the following
cutoffs:
• summa cum laude 3.8 or higher
• magna cum laude 3.6 or higher, up to summa cum laude
• cum laude 3.2 or higher, up to magna cum laude
A 2.0 GPA is needed to graduate. Students with less than a 2.0 are not eligible for graduation.
Create a Python program that asks the user to enter a student’s GPA then determines and displays the
student’s graduation status.
10. The Python math library has a function to determine the hypotenuse of a right triangle, given the two
other sides of the triangle: math.hypot(a, b) returns the square root of ( a2+ b2). (See the table of math
Functions in Chapter 2.) Remember, a2+ b2 = c2, where a and b are the lengths of the shorter sides in a
right triangle and c is the hypotenuse. So, c = √𝑎2 + 𝑏2.
The distance from any point (x,y) in a Cartesian Coordinate system to the origin (0,0) is the hypotenuse
of a right triangle with the two short sides of the triangle equal to the x and y coordinates. In the
example below, the distance from the point (3,4) to origin is √32 + 42, which equals 5.
The example on the right also shows us that the quadrants of a Cartesian plane are numbered I through IV, with the following properties:
• If both x and y are non-negative, the point is in Quadrant I.
• If x is negative and y is non-negative, the point is in Quadrant II
• If x and y are both negative, the point is in Quadrant III.
• If x is non-negative and y is negative, the point is in Quadrant IV.
Y axis
X axis
(3,4)
4
3(0,0)
Quadrant IQuadrant II
Quadrant III Quadrant IV
Your task is to create a Python application that asks the user for the x and y coordinates of a point, then
returns the distance to the origin and which quadrant the point is in.
— End of Chapter 3 —