Introduction
to Problem Solving
Steps in Programming
• A Very Simplified Picture
– Problem
Definition & Analysis
– High Level Strategy for a solution
– Arriving
at an algorithm
– Verification
and analysis of the algorithm
– Encoding
the algorithm as a program
(in a programming language)
– Testing
the program
• Each step iterative and the whole process also iterative
Problem Definition & Analysis
• Understanding the problem is half the solution
• A precise solution requires a precise definition
• This step leads to clear definition of the problem
• The definition states WHAT the problem to be solved
• rather than HOW the problem to be solved
• Analysis done to get a complete and consistent specification
• Specification precisely and unambiguously states
– Constraints on the inputs
– Desired Properties of the outputs
High Level Strategy
• This is a crucial and most difficult step
• Most creative part of the whole process
• No standard recipe for arriving at a strategy
• There do exist many standard techniques proved successful
– Divide and Conquer
– Dynamic Programming
– Greedy Approach
– Backtracking
– Local Search
• Compare alternate techniques to arrive at the best
Algorithm Development
• Algorithm precise and complete description of high level
strategy
• The high level strategy, in general, sketchy and usable only
by humans
• Many more details needed which are added in this phase
• Leads to a precise sequence of instructions
• Instructions specify the various data objects and operations
• The data objects are at a very high level closer to the
problem domain
• Various constructs like sequencing, conditionals and looping
are used to control the flow of execution of the instruction
Algorithm Analysis
• Algorithm analyzed for correctness and
efficiency
• They are precise and detailed enough
for these analysis
• Correctness analysis:
– to ensure the algorithm solves the
given problem
– This involves a mathematical proof that
algorithm satisfies the specification; termination proofs
• Efficiency analysis:
– to determine the amount of time or number of operations and amount
of memory required for executing the algorithm
• This explores possible alternate
designs of data and control structures to select the best possible one
Programming (coding algorithms)
• Writing programs in a programming
language is the last step
• No doubt it is important and one need
to pay attention and care
• But it is somewhat straightforward
• It requires mastery over the
programming language
• This step is programming language
dependent
• So in the development of a solution,
only this step need to change for a different programming language
• This step is called implementation or
coding
Testing the Program
• In this phase, the program is compiled to generate machine
code that can run on a specific machine
• Errors could be introduced in the programming process or by
the compiler
• Hence it is essential that the generated code is run with
specific set of inputs to see whether it produces the right outputs
• Syntax errors eliminated in the step
• Some logical errors may also be caught in this step
• It also gives an idea about time and space requirements for
executing the program
Problem Solving Strategies
• Arriving at a strategy and an algorithm
is the most crucial and difficult step
• Crucial because behavior of the final
code is dependent on this
• Difficult because it is a creative step
• Though many standard techniques are
available no general recipe to ensure success
• New problems may require newer
strategies
• Problem solving skills can be developed
only with experience
• Main emphasis of the course: to expose
you to various problem solving strategies by way of examples
• The programming languages is for
concreteness and execution of your ideas
Illustrative Examples
• Problem: Given a set of students
examination marks, (range 0 to 100), count the number of students that passed
the examination and those passed with
distinction;
– pass mark: >=50, distinction mark:
>=80
• Study the problem and analyze
• Is the problem definition clear?
The Strategy
•
Keep two counters one for pass and the other for distinction
• Read the marks one by one
• compare each mark with 50 and 80 and
increase the appropriate counters
• Print the final results
The algorithm
Algorithm pass_count:
Input: List of marks
Output: pass_count, distinction_count
1. initialize p_count, d_count to zero
2. Do while (there is next_mark) steps
2.1 and 2.2
2.1
If next_mark => 50 then increment p_count
2.2
If next_mark => 80 then increment d_count
end pass_count
Observations
• The algorithm is a sequence of precise instructions
– Involves
variables for storing input, intermediate and output data
– uses
high level operations and instructions
– Data
types closer to the problem domain
• What does the algorithm do for marks that do not lie between
0 and 100 ?
• Rewrite the algorithm
Correctness of the Solution
• Is the solution correct?
• Show that
– if an input satisfies the input
constraints
– then output produced satisfies required
properties
• Input Constraints
– List of integers lying between 0 and
100
• Required Property
– p_count contains the no. of marks >=
50
– d_count contains the no. of marks >=
80
• Termination is an implicit requirement
How to establish correctness
• Establish that
if input
constraint is satisfied then
the program will terminate producing the
output that satisfies the desired properties
• How to establish?
– Testing?
– How many inputs will convince you?
– 5, 10, 100 – in general infinite
Testing establish presence of bugs never their
absence
Mathematical Argument
• Prove the correctness using mathematical arguments
• Proof of Correctness involves two-Step argument
– Loop Invariants
– Loop Termination
Loop invariants
•
A
condition (logical expression) involving program variables
– It holds initially
– If it holds before start of iteration, it holds at the end;
– The condition remains invariant under iteration
•
Loop
invariant for our example
p_count and d_count hold the total number of pass and distinction marks
in the marks read so far
•
Loop
invariants holds at every iteration if it holds initially
•
In
particular, it holds at the end
•
Input
constraints imply loop invariant initially
•
Loop
invariant at the end, implies output condition
Loop Termination
• Non termination is an important source
of incorrectness.
• Correctness proof includes termination
proof
• An integer valued expression called
bound function that reduces in each iteration
• When the bound function reaches 0, loop
terminates
• For our example, the bound function is:
length of the input list yet to be processed
Efficiency Analysis
• How many number of operations?
– In each iteration of the loop, constant
number of comparisons
• Can we improve this?
– If the number is less than 50, there is
no need for comparing it with 80.
• Rewrite the algorithm
Encoding the algorithm
• How to implement the algorithm?
• More or less straightforward:
– counter
variables are integer variables
– read
and print statements
– the
loop into a `do statement’
– But wait!
– How
to terminate the loop?
• We need to have a protocol for communication
– Input
the total no. of marks
– Input
a blank line or line with a special number
– What
could be the special number?
Program pd_count
implicit none
integer, parameter:: p_mark = 50
integer, parameter:: d_mark = 80
integer:: p_count,d_count
integer:: N, mark, index
! N - the total number of marks to be processed
! mark - temporary variable to store the mark being processed
p_count = 0;
d_count = 0;
read *, N;
do index = 1, N
read *, mark
if (mark > = p_mark) then
p_count = p_count + 1
if (mark >= d_mark) then
d_count = d_count +1
endif
endif
end do
print *, p_count,d_count
Some Observations
• Note the use of constant identifiers
p_mark and d_mark rather than actual values 50, 80. This is preferable when the
pass mark or distinction marks change.
• variables and constants have meaningful
names conveying the intent. Programs need to be maintained. Human understanding
is essential
• All variables need to be initialized
• Always use implicit none to catch
typographical errors
Testing
•
Finally
Compile the program and test
•
Why
test? We have already verified!
•
What
inputs should be given?
•
Inputs
that exercise boundary conditions
– Total Number of
marks: 0, 1
– Actual Marks: 49, 50,
51, 79, 80, 81
•
Representative
Inputs:
– Total Number of
inputs: 0, 25, 100
– Actual Marks: -34, 0, 25, 67, 92, 120