450 likes | 627 Views
Methodology of Problem Solving. Efficiently Solving Computer Programming Problems . Doncho Minkov. Telerik Corporation. www.telerik.com. Technical Trainer. Problems Solving. From Chaotic to Methodological Approach. How to Solve Problems?. Read and analyze the problems
E N D
Methodology of Problem Solving Efficiently SolvingComputer Programming Problems Doncho Minkov Telerik Corporation www.telerik.com Technical Trainer
Problems Solving From Chaotic to Methodological Approach
How to Solve Problems? • Read and analyze the problems • Use a sheet of paper and a pen for sketching • Think up, invent and try ideas • Break the problem into subproblems • Check up your ideas • Choose appropriate data structures • Think about the efficiency • Implement your algorithm step-by-step • Thoroughly test your solution
Read and Analyze the Problems • Consider you are at traditional computer programming exam or contest • You have 5 problems to solve in 6 hours • First read carefully all problems and try to estimate how complex each of them is • Read the requirements, don't invent them! • Start solving the most easy problem first • Leave the most complex problem last • Approach the next problem when the previous is completely solved and well tested
Analyzing the Problems • Example: we are given 3 problems: • Set of Numbers • Count the occurrences of a number in set of numbers • Students • Read a set of students and print the name of the student with the highest mark • Binary Representation • Find the 'ones' and 'zeros' of a set of numbers in their binary representation
Analyzing the Problems (2) • Read carefully the problems and think a bit • Order the problems from the easiest to the most complex: • Set of Numbers • Whenever find the number increase a count variable with one • Students • Temporary student with current highest mark • Binary representation • If we know the 'ones', we can easily find the zeros
Using a Paper and a Pen Visualizing and Sketching Your Ideas
Use a Sheet of Paper and a Pen • Never start solving a problem without a sheet of paper and a pen • You need to sketch your ideas • Paper and pen is the best visualization tool • Allows your brain to think efficiently • Paper works faster than keyboard / screen • Other visualization tool could also work well
Paper and Pen • Consider the "Binary representation" problem • We can sketch it to start thinking • Some ideas immediately come, e.g. • Divide by 2 and check for the remainder • Bitwise shift right and check for the rightmost bit • Bitwise shift left and check for the leftmost bit • Count only the "zeros" • Count only the "ones" • Count both "ones" and "zeros"
Invent Ideas Think-up, Invent Ideas and Check Them
Think up, Invent and Try Ideas • First take an example of the problem • Sketch it on the sheet of paper • Next try to invent some idea that works for your example • Check if your idea will work for other examples • Try to find a case that breaks your idea • Try challenging examples and unusual cases • If you find your idea incorrect, try to fix it or just invent a new idea
Invent and Try Ideas – Example • Consider the "Binary Representation" problem • Idea #1: divide by 2 and check the remainder • How many times to do this? • Where to check? • Idea #2: Bitwise shift and check the left/rightmost bit • Left shift or right shift? • How many times to repeat this? • Is this fast enough?
Check-up Your Ideas Don't go Ahead before Checking Your Ideas
Check-up Your Ideas • Check-up your ideas with examples • It is better to find a problem before the idea is implemented • When the code is written, changing radically your ideas costs a lot of time and effort • Carefully select examples for check-up • Examples should be simple enough to be checked by hand in a minute • Examples should be complex enough to cover the most general case, not just an isolated case
Invent New Idea If Needed • What to do when you find your idea is not working in all cases? • Try to fix your idea • Sometime a small change could fix the problem • Invent new idea and carefully check it • Iterate • It is usual that your first idea is not the best • Invent ideas, check them, try various cases, find problems, fix them, invent better idea, etc.
Efficiency and Performance Is Your Algorithm Fast Enough?
Think About the Efficiency • Think about efficiency before writing the first line of code • Estimate the expected running time(e.g. using asymptotic complexity) • Check the requirements • Will your algorithm be fast enough to conform with them • You don't want to implement your algorithm and find that it is slow when testing • You will lose your time
Efficiency is not Always Required • Best solution is sometimes just not needed • Read carefully your problem statement • Sometimes ugly solution could work for your requirements and it will cost you less time • Example: if you need to sort n numbers, any algorithm will work when n∈ [0..500] • Implement complex algorithms only when the problem really needs them!
Implementation Coding and Testing Step-by-Step
Start Coding: Check List • Never start coding before you find correct idea that will meet the requirements • What you will write before you invent a correct idea to solve the problem? • Checklist to follow before start of coding: • Ensure you understand well the requirements • Ensure you have invented a good idea • Ensure your idea is correct • Ensure you know what data structures to use • Ensure the performance will be sufficient
Coding Check List – Example • Checklist before start of coding: • Ensure you understand well the requirements • Yes, counts values of bits • Ensure you have invented a correct idea • Yes, the idea seems correct and is tested • Ensure the performance will be sufficient • Linear running time good performance
Implement yourAlgorithm Step-by-Step • "Step-by-step" approach is always better than "build all, then test" • Implement a piece of your program and test it • Then implement another piece of the program and test it • Finally put together all pieces and test it • Small increments (steps) reveal errors early • "Big-boom" integration takes more time
Step #1 – Check The Value Of The First Bit • What happens to the number? • Do we need the first bit anymore? • Remove it by right shift • Now we have the value of the first bit int number=10; int firstBit = number & 1; int number=10; int firstBit = number & 1; number >>= 1;
Step #1 – Test • Testing if the correct bit is extracted and checked • Get feedback as early as possible: • The result is as expected: int number = 10; int firstBit = number & 1; number >>= 1; Console.WriteLine(firstBit); Console.WriteLine(number); 0 // the first bit 5 // the number without the first bit
Step #2 – Get All The Bits Of a Number • How many bits we want to check? • All for the number • But how many are they • Example: the number 10 • 10(10) = 8+2= 1010(2)– 4 bits • How the find out when to stop the checking? • When right shifting the zeros in the front get more and more • At some point the number will become zero
Step #2 – Get All The Bits Of a Number • Until the number becomes equal to 0 • Check the value of the bit • Right shift the number while (number != 0) { int firstBit = number & 1; number >>= 1; Console.Write("{0} ", firstBit); }
Step #2 – Test • Testing with 10 0 1 0 1 • Testing with 1111 1 1 1 0 1 0 1 0 0 0 1 1111 = 1024 + 64 + 16 + 4 + 2 + 1 = 210 + 26 + 24 + 22 + 21 + 20 • Seems correct
Step #3 – Check For The Occurrences Of Bit Value • So far: • We can get the values of all the bits of a number • Lets count the number of ones and zeros • while (number != 0) • { • int firstBit = number & 1; • number >>= 1; • if (firstBit == 1) • { • oneCount++; • } • else • { • zeroCount++; • } • }
Step #3 – Test • Test with number 111 (1101111(2)) • The result is correct ones:6 zeros:1 • Test with number 1234 (10011010010(2)) • The result is correct ones:5 zeros:6
Step #4 – Count The Bits Of The Whole Set • Pass through all the numbers • Count their bits • int zeroCount = 0, oneCount = 0, n = 5; • for (int i = 0; i < n; i++) • { • int number = int.Parse(Console.ReadLine()); • while (number != 0) • { • int firstBit = number & 1; • number >>= 1; • if (firstBit == 1) { oneCount++; } • else { zeroCount++; } • } • Console.WriteLine("ones:{0};zeros:{1}", • oneCount,zeroCount); • }
Step #4 – Count The Bits Of The Whole Set (2) • The result is surprisingly incorrect: • The result is surprisingly incorrect: • The count of ones and zeros appears as to stack for all the numbers of the set! • We defined the counters outside the iteration of the set loop • Put them inside Input: 1 2 3 4 5 Output: ones:1; zeros:0 ones:2; zeros:1 ones:4; zeros:1 ones:5; zeros:3 ones:7; zeros:4
Step #4 – Fixing the Bug • Now it is OK int n = 5; for (int i = 0; i < n; i++) { int zeroCount = 0, oneCount = 0; int number = int.Parse(Console.ReadLine()); while (number != 0) { int firstBit = number & 1; number >>= 1; if (firstBit == 1) { oneCount++; } else { zeroCount++; } } Console.WriteLine("ones:{0}; zeros:{1}", oneCount,zeroCount); }
Testing Thoroughly Test Your Solution
Thoroughly Test your Solution • Wise software engineers say that: • Inventing a good idea and implementing it is half of the solution • Testing is the second half of the solution • Always test thoroughly your solution • Invest in testing • One 100% solved problem is better than 2 or 3 partially solved • Testing existing problem takes less time than solving another problem from scratch
How to Test? • Testing could not certify absence of defects • It just reduces the defects rate • Well tested solutions are more likely to be correct • Start testing with a good representative of the general case • Not a small isolated case • Large and complex test, but • Small enough to be easily checkable
How to Test? (2) • Test the border cases • E.g. if n∈ [0..500] try n=0 , n=1, n=2, n=499, n=500 • If a bug is found, repeat all tests after fixing it to avoid regressions • Run a load test • How to be sure that your algorithm is fast enough to meet the requirements? • Use copy-pasting to generate large test data
Read the Problem Statement • Read carefully the problem statement • Does your solution print exactly what is expected? • Does your output follow the requested format? • Did you remove your debug printouts? • Be sure to solve the requested problem, not the problem you think is requested! • Example: "Write a program to print the number of permutations on n elements" means to print a single number, not a set of permutations!
Testing – Example • Test with a set of 10 numbers • Serious error found change the algorithm • Change the algorithm • The counters never reset to zero • Test whether the new algorithm works • Test with 1 number • Test with 2 numbers • Test with 0 numbers • Load test with 52 000 numbers
Test With 10000 Numbers – Example int n = 10000, startNumber=111; for (int i = startNumber; i < startNumber + n; i++) { int zeroCount = 0; int oneCount = 0; //int number = int.Parse(Console.ReadLine()); int number = i; int originalNumber = number; while (number != 0) { int firstBit = number & 1; number >>= 1; if (firstBit == 1){ oneCount++; } else { zeroCount++; } } } Replace the reading from the console with a easier type of check
Test With 10000 Numbers – Example (2) • The result is perfect: 111(10) = 1101111(2) -> ones:6;zeros:1 … 10110(10) = 10011101111110(2)-> ones:10;zeros:4
Testing Tips • You are given the task of the binary representation • The program must read from the console • Integer numbers N and B • N integer numbers • While writing and testing the program • Don't read from the console • First hardcode the numbers • Later make it • When you are sure it works
Hard-Coded Input – Example // Hardcoded input data – for testing purposes int n = 5; int num1 = 11; int num2 = 127; int num3 = 0; int num4 = 255; int num5 = 24; // Read the input from the console //int n = int.Parse(Console.ReadLine()); //for (int i=0; i<n; i++) //{ // int num = int.Parse(Console.ReadLine()); // // Process the number … // // … //} // Now count the bits for these n numbers …
Summary Problems solving needs methodology: • Understanding and analyzing problems • Using a sheet of paper and a pen for sketching • Thinking up, inventing and trying ideas • Decomposing problems into subproblems • Selecting appropriate data structures • Thinking about the efficiency and performance • Implementing step-by-step • Testing the nominal case, border cases and efficiency
Methodology of Problem Solving ? Questions? ? ? ? ? ? ? ? ? ? http://academy.telerik.com