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