Professional Documents
Culture Documents
Algorithm
Algorithms describe the solution to a problem in terms of the data needed to
represent the problem instance and the set of steps necessary to produce the
intended result. Programming languages must provide a notational way to represent
both the process and the data. To this end, languages provide control constructs and
data types.
Control constructs allow algorithmic steps to be represented in a convenient
yet unambiguous way. At a minimum, algorithms require constructs that perform
sequential processing, selection for decision-making, and iteration for repetitive
control. As long as the language provides these basic statements, it can be used for
algorithm representation.
Simple statements
A simple statement is comprised within a single logical line. Several simple statements may occur on
a single line separated by semicolons. The syntax for simple statements is:
An expression statement evaluates the expression list (which may be a single expression).
Assignment statements
Assignment statements are used to (re)bind names to values and to modify attributes
or items of mutable objects:
class Cls:
x = 3 # class variable
inst = Cls()
inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3
if __debug__:
if not expression: raise AssertionError
if __debug__:
if not expression1: raise AssertionError(expression2)
Deletion is recursively defined very similar to the way assignment is defined. Rather
than spelling it out in full details, here are some hints.
Deletion of a target list recursively deletes each target, from left to right.
Deletion of a name removes the binding of that name from the local or global
namespace, depending on whether the name occurs in a global statement in the
same code block. If the name is unbound, a NameError exception will be raised.
Deletion of attribute references, subscriptions and slicings is passed to the primary
object involved; deletion of a slicing is in general equivalent to assignment of an empty
slice of the right type (but even this is determined by the sliced object).
return may only occur syntactically nested in a function definition, not within a nested
class definition.
return leaves the current function call with the expression list (or None) as return
value.
When return passes control out of a try statement with a finally clause,
that finally clause is executed before really leaving the function.
yield <expr>
yield from <expr>
(yield <expr>)
(yield from <expr>)
Yield expressions and statements are only used when defining a generator function,
and are only used in the body of the generator function. Using yield in a function
definition is sufficient to cause that definition to create a generator function instead of
a normal function.
Otherwise, raise evaluates the first expression as the exception object. It must be
either a subclass or an instance of BaseException. If it is a class, the exception
instance will be obtained when needed by instantiating the class with no arguments.
The type of the exception is the exception instance’s class, the value is the instance
itself.
Exception chaining can be explicitly suppressed by specifying None in the from clause:
>>>
>>> try:
... print(1 / 0)
... except:
... raise RuntimeError("Something bad happened") from None
...
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened
break may only occur syntactically nested in a for or while loop, but not nested in
a function or class definition within that loop.
It terminates the nearest enclosing loop, skipping the optional else clause if the loop
has one.
If a for loop is terminated by break, the loop control target keeps its current value.
When break passes control out of a try statement with a finally clause,
that finally clause is executed before really leaving the loop.
continue may only occur syntactically nested in a for or while loop, but not nested
in a function or class definition or finally clause within that loop. It continues with
the next cycle of the nearest enclosing loop.
When continue passes control out of a try statement with a finally clause,
that finally clause is executed before really starting the next loop cycle.
The basic import statement (no from clause) is executed in two steps:
When the statement contains multiple clauses (separated by commas) the two steps
are carried out separately for each clause, just as though the clauses had been
separated out into individual import statements.
Examples:
Future statements
A future statement is a directive to the compiler that a particular module should be
compiled using syntax or semantics that will be available in a specified future release
of Python where the feature becomes standard.
The future statement is intended to ease migration to future versions of Python that
introduce incompatible changes to the language. It allows use of the new features on
a per-module basis before the release in which the feature becomes standard.
A future statement must appear near the top of the module. The only lines that can
appear before a future statement are:
A future statement is recognized and treated specially at compile time: Changes to the
semantics of core constructs are often implemented by generating different code. It
may even be the case that a new feature introduces new incompatible syntax (such
as a new reserved word), in which case the compiler may need to parse the module
differently. Such decisions cannot be pushed off until runtime.
For any given release, the compiler knows which feature names have been defined,
and raises a compile-time error if a future statement contains a feature not known to
it.
The global statement is a declaration which holds for the entire current code block.
It means that the listed identifiers are to be interpreted as globals. It would be
impossible to assign to a global variable without global, although free variables may
refer to globals without being declared global.
Names listed in a global statement must not be used in the same code block textually
preceding that global statement.
The nonlocal statement causes the listed identifiers to refer to previously bound
variables in the nearest enclosing scope excluding globals. This is important because
the default behavior for binding is to search the local namespace first. The statement
allows encapsulated code to rebind variables outside of the local scope besides the
global (module) scope.
Names listed in a nonlocal statement must not collide with pre-existing bindings in
the local scope.
if Statements
Perhaps the most well-known statement type is the if statement. For example:
>>>
>>> x = int(input("Please enter an integer: "))
Please enter an integer: 42
>>> if x < 0:
... x = 0
... print('Negative changed to zero')
... elif x == 0:
... print('Zero')
... elif x == 1:
... print('Single')
... else:
... print('More')
...
More
There can be zero or more elif parts, and the else part is optional. The keyword
‘elif’ is short for ‘else if’, and is useful to avoid excessive indentation.
An if … elif … elif … sequence is a substitute for
the switch or casestatements found in other languages.
for Statements
The for statement in Python differs a bit from what you may be used to in C or Pascal.
Rather than always iterating over an arithmetic progression of numbers (like in
Pascal), or giving the user the ability to define both the iteration step and halting
condition (as C), Python’s for statement iterates over the items of any sequence (a
list or a string), in the order that they appear in the sequence. For example (no pun
intended):
>>>
>>> # Measure some strings:
... words = ['cat', 'window', 'defenestrate']
>>> for w in words:
... print(w, len(w))
...
cat 3
window 6
defenestrate 12
If you need to modify the sequence you are iterating over while inside the loop (for
example to duplicate selected items), it is recommended that you first make a copy.
Iterating over a sequence does not implicitly make a copy. The slice notation makes
this especially convenient:
>>>
>>> for w in words[:]: # Loop over a slice copy of the entire
list.
... if len(w) > 6:
... words.insert(0, w)
...
>>> words
['defenestrate', 'cat', 'window', 'defenestrate']
With for w in words:, the example would attempt to create an infinite list,
inserting defenestrate over and over again.
The range() Function
If you do need to iterate over a sequence of numbers, the built-in
function range() comes in handy. It generates arithmetic progressions:
>>>
>>> for i in range(5):
... print(i)
...
0
1
2
3
4
The given end point is never part of the generated sequence; range(10) generates
10 values, the legal indices for items of a sequence of length 10. It is possible to let
the range start at another number, or to specify a different increment (even negative;
sometimes this is called the ‘step’):
range(5, 10)
5 through 9
range(0, 10, 3)
0, 3, 6, 9
To iterate over the indices of a sequence, you can combine range() and len() as
follows:
>>>
>>> a = ['Mary', 'had', 'a', 'little', 'lamb']
>>> for i in range(len(a)):
... print(i, a[i])
...
0 Mary
1 had
2 a
3 little
4 lamb
>>>
>>> print(range(10))
range(0, 10)
In many ways the object returned by range() behaves as if it is a list, but in fact it
isn’t. It is an object which returns the successive items of the desired sequence when
you iterate over it, but it doesn’t really make the list, thus saving space.
We say such an object is iterable, that is, suitable as a target for functions and
constructs that expect something from which they can obtain successive items until
the supply is exhausted. We have seen that the for statement is such an iterator. The
function list() is another; it creates lists from iterables:
>>>
>>> list(range(5))
[0, 1, 2, 3, 4]
Later we will see more functions that return iterables and take iterables as argument.
Loop statements may have an else clause; it is executed when the loop terminates
through exhaustion of the list (with for) or when the condition becomes false
(with while), but not when the loop is terminated by a breakstatement. This is
exemplified by the following loop, which searches for prime numbers:
>>>
>>> for n in range(2, 10):
... for x in range(2, n):
... if n % x == 0:
... print(n, 'equals', x, '*', n//x)
... break
... else:
... # loop fell through without finding a factor
... print(n, 'is a prime number')
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3
(Yes, this is the correct code. Look closely: the else clause belongs to
the for loop, not the if statement.)
When used with a loop, the else clause has more in common with the else clause
of a try statement than it does that of if statements: a try statement’s else clause
runs when no exception occurs, and a loop’s else clause runs when
no break occurs. For more on the try statement and exceptions, see Handling
Exceptions.
The continue statement, also borrowed from C, continues with the next iteration of
the loop:
>>>
>>> for num in range(2, 10):
... if num % 2 == 0:
... print("Found an even number", num)
... continue
... print("Found a number", num)
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5
Found an even number 6
Found a number 7
Found an even number 8
Found a number 9
pass Statements
The pass statement does nothing. It can be used when a statement is required
syntactically but the program requires no action. For example:
>>>
>>> while True:
... pass # Busy-wait for keyboard interrupt (Ctrl+C)
...
This is commonly used for creating minimal classes:
>>>
>>> class MyEmptyClass:
... pass
...
Another place pass can be used is as a place-holder for a function or conditional body
when you are working on new code, allowing you to keep thinking at a more abstract
level. The pass is silently ignored:
>>>
>>> def initlog(*args):
... pass # Remember to implement this!
...
Functions
Defining Functions
We can create a function that writes the Fibonacci series to an arbitrary boundary:
>>>
>>> def fib(n): # write Fibonacci series up to n
... """Print a Fibonacci series up to n."""
... a, b = 0, 1
... while a < n:
... print(a, end=' ')
... a, b = b, a+b
... print()
...
>>> # Now call the function we just defined:
... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
The keyword def introduces a function definition. It must be followed by the function
name and the parenthesized list of formal parameters. The statements that form the
body of the function start at the next line, and must be indented.
The first statement of the function body can optionally be a string literal; this string
literal is the function’s documentation string, or docstring. (More about docstrings can
be found in the section Documentation Strings.) There are tools which use docstrings
to automatically produce online or printed documentation, or to let the user
interactively browse through code; it’s good practice to include docstrings in code that
you write, so make a habit of it.
The execution of a function introduces a new symbol table used for the local variables
of the function. More precisely, all variable assignments in a function store the value
in the local symbol table; whereas variable references first look in the local symbol
table, then in the local symbol tables of enclosing functions, then in the global symbol
table, and finally in the table of built-in names. Thus, global variables cannot be directly
assigned a value within a function (unless named in a global statement), although
they may be referenced.
The actual parameters (arguments) to a function call are introduced in the local symbol
table of the called function when it is called; thus, arguments are passed using call by
value (where the value is always an object reference, not the value of the
object). [1] When a function calls another function, a new local symbol table is created
for that call.
A function definition introduces the function name in the current symbol table. The
value of the function name has a type that is recognized by the interpreter as a user-
defined function. This value can be assigned to another name which can then also be
used as a function. This serves as a general renaming mechanism:
This example also introduces the in keyword. This tests whether or not a sequence
contains a certain value.
i = 5
def f(arg=i):
print(arg)
i = 6
f()
will print 5.
Keyword Arguments
Functions can also be called using keyword arguments of the form kwarg=value. For
instance, the following function:
Normally, these variadic arguments will be last in the list of formal parameters,
because they scoop up all remaining input arguments that are passed to the function.
Any formal parameters which occur after the *args parameter are ‘keyword-only’
arguments, meaning that they can only be used as keywords rather than positional
arguments.
>>>
pseudo code
Pseudo code is an ordered version of your code written for human understanding rather than
machine understanding.
e.g.
pseudo code
python code
flowcharts
A standard way to plan code is with flowcharts.
Diamonds show a
decision/conditional
Conditional/ (this is normally if, else if/elif,
Decision while and for)
creating flowcharts
There are many tools you can use to create flow charts.
draw.io is a good online tool you can use to create flowcharts. You can logon with a Google Drive
account.
Example 1
This program asks the user their name then says "Hello [Name]":
This is the same way we show a decision (if, else if/elif etc).
For loops normally repeat a nested block of code a set number of times or for a set range of
data.
One of the easiest ways to think about it is that there are normally two paths the computer can go
down when it reaches a loop:
For example:
i = 0
while i < 10 :
print ( i )
i += 1
Note: In this example there is no code after the loop so we represent this with the end symbol.
functions in flowcharts
Another type of symbol that is important for more advanced programs is the symbol used for functions.
Functions are sometimes also known as modules or pre-defined processes; they represent a completed
block of code that can be called form other parts of a program.
Functions are not taught in the Level 1 Python course and may not be required for basic programs.
(They are not required for Level 1 NCEA in New Zealand but they are for Level 2.)
The name of the function is normally added to the start symbol in these unconnected flowcharts.
There may be times when you do not need to show the contents of every function in your flowchart.
The example below shows a rough diagram of a program that makes use of functions that convert
Farenheit to Celcius and compare the current temperate to the monthly average. This is a rough example
only to show the idea of how you can represent functions in flowcharts; often the functions will be far
more complex than the examples below.
different types of inputs
When planning and creating code, it is important that you think about the different types of input
users can add.
Inputs can be integers (whole numbers), floats (numbers with decimal places), strings (text
characters) or even empty.
In Python when we create a variable with input we can specificy what type of variable it is.
For example:
integerInput = int ( input ( "Please input an integer e.g. 10" ))
floatInput = float ( input ( "Please input a float e.g. 3.75" ))
stringInput = str ( input ( "Please input a string e.g. Hello" ))
Floats can have numbers after a decimal place but do not need them.
When testing and planning code we define three different types of inputs.
Types of inputs:
expected
invalid
boundary
Expected inputs are inputs that we expect the users to add.
Expected inputs will be the right type of data within the expected range required for the program to work
properly.
Boundary inputs are numbers that are just inside and outside of the required range when inputs are
numbers (integers or floats).
Invalid inputs are inputs that we would not expect the user to add.
Invalid inputs will be the wrong type of data or outside of the range required for the program to work
properly.
There are several different ways to plan and create programs that respond
to invalid and boundary inputs.
Problems when strings are input
When an input is required to be a string the computer will allow any combination of text characters
numbers and symbols to be entered into that string.
Common problems related to inputting strings often relate to variations in capitalisation, spacing and
spelling; the program won't recognise the string if the string the user enters differs to the coded string
the computer uses to evaluate the input.
We can account for these errors by getting the program to decapitalise or capitalise characters in strings
and remove spaces.
Algorithms are often quite different from one another. Consider the example
of sqrt seen earlier. It is entirely possible that there are many different ways
to implement the details to compute the square root function. One algorithm
may use many fewer resources than another. One algorithm might take 10
times as long to return the result as the other. We would like to have some
way to compare these two solutions. Even though they both work, one is
perhaps “better” than the other. We might suggest that one is more efficient
or that one simply works faster or uses less memory. As we study algorithms,
we can learn analysis techniques that allow us to compare and contrast
solutions based solely on their own characteristics, not the characteristics of
the program or computer used to implement them.
Running through all the items in a list is called traversing the list, or traversal.
The while statement
Here is a fragment of code that demonstrates the use of the while statement:
def sum_to(n):
1 """ Return the sum of 1+2+3 ... n """
2 ss = 0
3 v = 1
4 while v <= n:
5 ss = ss + v
6 v = v + 1
7 return ss
8
9 # For your test suite
10 test(sum_to(4) == 10)
11 test(sum_to(1000) == 500500)
12
You can almost read the while statement as if it were English. It means, while v is less
than or equal to n, continue executing the body of the loop. Within the body, each time,
increment v. When v passes n, return your accumulated sum.
Evaluate the condition at line 5, yielding a value which is either False or True.
If the value is False, exit the while statement and continue execution at the next
statement (line 8 in this case).
If the value is True, execute each of the statements in the body (lines 6 and 7) and
then go back to the while statement at line 5.
The body consists of all of the statements indented below the while keyword.
Notice that if the loop condition is False the first time we get loop, the statements in the
body of the loop are never executed.
The body of the loop should change the value of one or more variables so that eventually
the condition becomes false and the loop terminates. Otherwise the loop will repeat
forever, which is called an infinite loop. An endless source of amusement for computer
scientists is the observation that the directions on shampoo, “lather, rinse, repeat”, are an
infinite loop.
Two-dimensional tables
A two-dimensional table is a table where you read the value at the intersection of a row
and a column. A multiplication table is a good example. Let’s say you want to print a
multiplication table for the values from 1 to 6.
A good way to start is to write a loop that prints the multiples of 2, all on one line:
Here we’ve used the range function, but made it start its sequence at 1. As the loop
executes, the value of i changes from 1 to 6. When all the elements of the range have
been assigned to i, the loop terminates. Each time through the loop, it displays the value
of 2 * i, followed by three spaces.
Recursion
Recursion means “defining something in terms of itself” usually at some smaller scale,
perhaps multiple times, to achieve your objective. For example, we might say “A human
being is someone whose mother is a human being”, or “a directory is a structure that
holds files and (smaller) directories”, or “a family tree starts with a couple who have
children, each with their own family sub-trees”.
Programming languages generally support recursion, which means that, in order to solve
a problem, functions can call themselves to solve smaller sub problems.
Drawing Fractals
For our purposes, a fractal is a drawing which also has self-similar structure, where it can
be defined in terms of itself.
Let us start by looking at the famous Koch fractal. An order 0 Koch fractal is simply a
straight line of a given size.
An order 1 Koch fractal is obtained like this: instead of drawing just one line, draw
instead four smaller segments, in the pattern shown here:
Now what would happen if we repeated this Koch pattern again on each of the order 1
segments? We’d get this order 2 Koch fractal:
Repeating our pattern again gets us an order 3 Koch fractal:
Now let us think about it the other way around. To draw a Koch fractal of order 3, we can
simply draw four order 2 Koch fractals. But each of these in turn needs four order 1 Koch
fractals, and each of those in turn needs four order 0 fractals. Ultimately, the only
drawing that will take place is at order 0. This is very simple to code up in Python:
Fibonacci numbers
The famous Fibonacci sequence 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 134, ... was devised
by Fibonacci (1170-1250), who used this to model the breeding of (pairs) of rabbits. If, in
generation 7 you had 21 pairs in total, of which 13 were adults, then next generation the
adults will all have bred new children, and the previous children will have grown up to
become adults. So in generation 8 you’ll have 13+21=34, of which 21 are adults.
def fib(n):
if n <= 1:
return n
t = fib(n-1) + fib(n-2)
return t
Output
D:\Python\python.exe "C:/Users/G/PycharmProjects/Test/min in list.py"
-1
Process finished with exit code 0
guesses = 0
msg = ""
while True:
guess = int(input(msg + "\nGuess my number between 1 and 1000: "))
guesses += 1
if guess > number:
msg += str(guess) + " is too high.\n"
elif guess < number:
msg += str(guess) + " is too low.\n"
else:
break
output
D:\Python\python.exe 50 is too low. 199 is too low. Guess my number
"C:/Users/G/PycharmProj 500 is too high. 200 is too low. between 1 and 1000: 297
ects/Test/guess the 100 is too low. 250 is too low. 30 is too low.
number.py" 190 is too low. 300 is too high. 50 is too low.
195 is too low. 500 is too high.
Guess my number 193 is too low. Guess my number 100 is too low.
between 1 and 1000: 30 195 is too low. between 1 and 1000: 260 190 is too low.
30 is too low. 30 is too low. 195 is too low.
Guess my number 50 is too low. 193 is too low.
Guess my number between 1 and 1000: 199 500 is too high. 195 is too low.
between 1 and 1000: 50 30 is too low. 100 is too low. 199 is too low.
30 is too low. 50 is too low. 190 is too low. 200 is too low.
50 is too low. 500 is too high. 195 is too low. 250 is too low.
100 is too low. 193 is too low. 300 is too high.
Guess my number 190 is too low. 195 is too low. 260 is too low.
between 1 and 1000: 500 195 is too low. 199 is too low. 290 is too low.
30 is too low. 193 is too low. 200 is too low. 295 is too high.
50 is too low. 195 is too low. 250 is too low. 297 is too high.
500 is too high. 199 is too low. 300 is too high.
260 is too low. Guess my number
Guess my number Guess my number between 1 and 1000: 293
between 1 and 1000: 100 between 1 and 1000: 200 Guess my number
30 is too low. 30 is too low. between 1 and 1000: 290
50 is too low. 50 is too low. 30 is too low. Great, you got it in 17
500 is too high. 500 is too high. 50 is too low. guesses!
100 is too low. 100 is too low. 500 is too high.
190 is too low. 100 is too low.
Guess my number 195 is too low. 190 is too low.
between 1 and 1000: 190 193 is too low. 195 is too low.
30 is too low. 195 is too low. 193 is too low.
50 is too low. 199 is too low. 195 is too low.
500 is too high. 200 is too low. 199 is too low.
100 is too low. 200 is too low.
190 is too low. Guess my number 250 is too low.
between 1 and 1000: 250 300 is too high.
Guess my number 30 is too low. 260 is too low.
between 1 and 1000: 195 50 is too low. 290 is too low.
30 is too low. 500 is too high.
50 is too low. 100 is too low. Guess my number
500 is too high. 190 is too low. between 1 and 1000: 295
100 is too low. 195 is too low. 30 is too low.
190 is too low. 193 is too low. 50 is too low.
195 is too low. 195 is too low. 500 is too high.
199 is too low. 100 is too low.
Guess my number 200 is too low. 190 is too low.
between 1 and 1000: 193 250 is too low. 195 is too low.
30 is too low. 193 is too low.
50 is too low. Guess my number 195 is too low.
500 is too high. between 1 and 1000: 300 199 is too low.
100 is too low. 30 is too low. 200 is too low.
190 is too low. 50 is too low. 250 is too low.
195 is too low. 500 is too high. 300 is too high.
193 is too low. 100 is too low. 260 is too low.
190 is too low. 290 is too low.
Guess my number 195 is too low. 295 is too high.
between 1 and 1000: 195 193 is too low.
30 is too low. 195 is too low.
Tower of haoni
def hanoi(n, source, helper, target):
print
"hanoi( ", n, source, helper, target, " called"
if n > 0:
# move tower of size n - 1 to helper:
hanoi(n - 1, source, target, helper)
# move disk from source peg to target peg
if source[0]:
disk = source[0].pop()
print("moving " + str(disk) + " from " + source[1] + " to " +
target[1])
target[0].append(disk)
# move tower of size n-1 from helper to target
hanoi(n - 1, helper, source, target)
output
D:\Python\python.exe "C:/Users/G/PycharmProjects/Test/tower of hanoi.py"
moving 1 from source to helper
moving 2 from source to target
moving 1 from helper to target
moving 3 from source to helper
moving 1 from target to source
moving 2 from target to helper
moving 1 from source to helper
moving 4 from source to target
moving 1 from helper to target
moving 2 from helper to source
moving 1 from target to source
moving 3 from helper to target
moving 1 from source to helper
moving 2 from source to target
moving 1 from helper to target
([], 'source') ([], 'helper') ([4, 3, 2, 1], 'target')