Previous | Next | Table of Contents | Index | Program List | Copyright

4.4 Problem Solving: More Strategies

Often what appears to be a new problem will turn out to be a variation of one that you have already solved. Consequently, an important skill in problem solving is the ability to recognize that a problem is similar to one solved earlier. As you progress through your education, you will start to build up a collection of programs and procedures. Whenever possible, you should try to adapt or reuse parts of a program that have been shown to work correctly.

Extending a Problem Solution

An experienced programmer usually writes programs that can be easily changed or modified to fit other situations. One reason for this is that programmers (and program users) often wish to make slight improvements to a program after having used it. If the original program is designed carefully from the beginning, the programmer will be able to accommodate changing specifications with a minimum of effort. In the next problem, it is possible to insert a new decision step rather than having to rewrite the entire program.


Case Study: Computing Overtime Pay

PROBLEM SPECIFICATION

Develop a payroll program so that employees who work more than 40 hours a week are paid double for all overtime hours.

ANALYSIS

This problem is an extension of the modified payroll problem solved by Program 4.1. Employees who work more than 40 hours should be paid one rate for the first 40 hours and a higher rate for the extra hours over 40. Employees who work 40 hours or less should be paid the same rate for all hours worked. We can solve this problem by replacing step 3 (compute gross pay) in the original algorithm with a decision step that selects either a straight pay computation or a computation with overtime pay.

Data Requirements

Problem Constants

maximum salary for no tax deduction (TaxBracket = 100.00)

amount of tax deducted (Tax = 25.00)

maximum hours without overtime pay (MaxHours = 40.0)

Problem Inputs

hours worked (Hours : NonNegFloat)

hourly rate (Rate : NonNegFloat)

Problem Outputs

gross pay (Gross : NonNegFloat)

net pay (Net : NonNegFloat)

DESIGN

The critical change to the algorithm involves modifying step 3 of thealgorithm. The algorithm is repeated below followed by a new refinement for step 3.

Initial Agorithm

1. Display user instructions.

2. Enter hours worked and hourly rate.

3. Compute gross salary including any overtime pay.

4. Compute net salary.

5. Display gross salary and net salary.

Algorithm Refinements

Step 3 Refinement

3.1. IF no overtime hours were worked THEN

     3.2. Gross gets Hours * Rate

      ELSE

     3.3. Compute Gross as (the pay for 40 hours) + (the pay for overtime hours)

      END IF;

IMPLEMENTATION

As shown below, we should replace the assignment statement in Program 4.1 thatcomputes gross pay by

    -- Compute gross pay including any overtime pay
    IF Hours <= MaxHours THEN
        Gross := Hours * Rate;
    ELSE
        Gross := (MaxHours * Rate) + ((Hours - MaxHours) * (2.0 * Rate));
    END IF;

If the condition Hours <= MaxHours is true, there is no overtime pay, so gross pay is computed as before; otherwise, Gross is computed using the second assignment statement above. The pay for the first 40 hours is added to the pay earned for the overtime hours (Hours - MaxHours).

The assignment statement for step 3.3 involves three arithmetic operators: +, -, and *. As recommended in Section 2.10, we have used parentheses to cause the operators above to be evaluated in the order of subtraction first, multiplication next, and addition last. Consequently, the overtime hours (Hours - MaxHours) are multiplied by 2.0 * Rate and added to the value of MaxHours * Rate computed earlier; the result is the new value of Gross. Modifying Program 4.1 as discussed here is left as an exercise.


Solution by Analogy

Sometimes a new problem is simply an old one presented in a new guise. Each time you face a problem, try to determine whether you have solved a similar problem before; if you have, adapt the earlier solution. This problem-solving strategy requires a careful reading of the problem statement to detect requirements that may be similar to those of earlier problems but worded differently.


Case Study: Computing Insurance Dividends

PROBLEM SPECIFICATION

Each year an insurance company sends out dividend checks to its policyholders. The dividend amount is a fixed percentage (4.5%) of the insurance premium paid in. If there were no damage claims made by the policyholder, the dividend rate for that policy is increased by 0.5%. Write a program to compute dividends.

ANALYSIS

This problem is similar to the overtime pay problem. Just as there was a bonuspay rate for workers with overtime hours, there is a bonus dividend for policyholders with no claims. We must first read in the input data (number of claims and premium). We then use a decision step to select either the basic dividend computation or the computation with a bonus dividend. (In the overtime pay problem, we followed a similar algorithm by first computing gross pay, then adding in overtime pay when earned.)

Data Requirements

Problem Constants

the fixed dividend rate of 4.5% (FixedRate = 0.045)

the bonus dividend rate of 0.5% (BonusRate = 0.005)

Problem Inputs

premium amount (Premium : NonNegFloat)

number of claims (NumClaims : Natural)

Problem Outputs

dividend amount (Dividend : NonNegFloat)

DESIGN

Figure 4.5 shows the structure chart for this algorithm.

Figure 4.5
Structure Chart for Insurance Dividend Problem

Figure 4.5

Algorithm

1. Display user instructions.

2. Enter premium amount and number of claims.

3. Compute basic dividend including a bonus dividend when earned.

4. Display total dividend.

Algorithm Refinements

The refinement of step 3 in this problem is similar to the refinement of step 3 in the overtime pay problem.

Step 3 Refinement

3.1. IF the basic dividend applies THEN

     3.2. Dividend gets Premium * BasicRate

ELSE

     3.3. Dividend gets basic dividend plus bonus dividend

END IF;

TEST PLAN

We leave the test plan as an exercise.

IMPLEMENTATION

The complete program is shown in Program 4.3. Because Ada possesses no % operator, decimal fractions are required. The basic dividend rate, 4.5%, is written as the decimal fraction 0.045, and the bonus rate, 0.5%, is written as the decimal fraction 0.005. All-floating point literals must begin with a digit; therefore, the zero in front of the decimal point is always required for a floating-point value less than 1.0. The IF statement at the end of the program displays an extra message to policyholders who receive a bonus dividend.

Program 4.3
Insurance Dividend Program

WITH Ada.Text_IO;
WITH Ada.Integer_Text_IO;
WITH Ada.Float_Text_IO;
PROCEDURE Dividend IS
------------------------------------------------------------------------
--| Finds and displays the insurance dividend.
--| Author: Michael B. Feldman, The George Washington University
--| Last Modified: July 1995                                     
------------------------------------------------------------------------
 
  SUBTYPE NonNegFloat IS Float RANGE 0.0 .. Float'Last;

  BasicRate : CONSTANT NonNegFloat := 0.045; -- basic dividend rate 4.5%
  BonusRate : CONSTANT NonNegFloat := 0.005; -- bonus dividend rate 0.5%
 
  Premium   : NonNegFloat;   -- input  - premium amount
  NumClaims : Natural;       -- input  - number of claims
  Dividend  : NonNegFloat;   -- output - dividend amount

BEGIN -- Dividend

  -- Enter Premium and NumClaims
  Ada.Text_IO.Put (Item => "Premium amount > $");
  Ada.Float_Text_IO.Get (Item => Premium);
  Ada.Text_IO.Put (Item => "Number of claims > ");
  Ada.Integer_Text_IO.Get (Item => NumClaims);
  Ada.Text_IO.New_Line;

  -- Compute divided using bonus rate when earned
  IF NumClaims /= 0 THEN
    Dividend := Premium * BasicRate;
  ELSE
    Dividend := (Premium * BasicRate) + (Premium * BonusRate);
  END IF;

  -- Display total dividend
  Ada.Text_IO.Put (Item => "Total dividend is $");
  Ada.Float_Text_IO.Put (Item => Dividend, Fore => 1, Aft => 2, Exp => 0);
  Ada.Text_IO.New_Line;

  IF NumClaims = 0 THEN
    Ada.Text_IO.Put
      (Item => "This includes a bonus dividend for zero claims!");
    Ada.Text_IO.New_Line;
  END IF;

END Dividend;
Sample Run
Premium amount > $1200.00
Number of claims > 0

Total dividend is $60.00
This includes a bonus dividend for zero claims!


Case Study: Given Today, Find Yesterday and Tomorrow

PROBLEM SPECIFICATION

Read the day of the week from the terminal as a three-letter abbreviation, and display yesterday and tomorrow.

ANALYSIS

Recall from Section 3.4 that the days of the week are best represented as an enumeration type, so the days can be read and displayed by an instance of Enumeration_IO. Yesterday and tomorrow can be found using the successor and predecessor attributes. Because the predecessor of the first day of the week and the successor of the last day of the week are undefined--the type does not "wrap around"--we shall need statements to check for these as special cases.

Data Requirements

Problem Data Types

Days of the week, an enumeration type:

    TYPE Days IS
        (Mon, Tue, Wed, Thu, Fri, Sat, Sun);

Problem Inputs

Today (Today : Days)

Problem Outputs

Yesterday (Yesterday: Days)

Tomorrow (Tomorrow: Days)

DESIGN

Initial Algorithm

1. Prompt the user for the current day abbreviation and read it from the keyboard.

2. Find the abbreviations for yesterday and tomorrow.

3. Display the results on the screen.

Algorithm Refinements

Step 2 Refinement

The refinement of step 2 takes into account that in Ada the enumeration types are not cyclic.

2.1. If today is the first day of the week, then yesterday is the last day of the (previous) week; otherwise yesterday is the predecessor of today.

2.2. If today is the last day of the week, then tomorrow is the first day of the (following) week; otherwise tomorrow is the successor of today.

TEST PLAN

In addition to a normal case, we need to test two special cases, namely, where today is Sunday (to be sure that tomorrow is Monday) and today is Monday (to be sure that yesterday was Sunday). Also test for invalid input that is not one of the seven day abbreviations.

IMPLEMENTATION:

Program 4.4 gives the complete solution to the problem.

Program 4.4
Finding Yesterday and Tomorrow

WITH Ada.Text_IO;
PROCEDURE Three_Days IS
------------------------------------------------------------------------
--| Finds yesterday and tomorrow, given today
--| Author: Michael B. Feldman, The George Washington University
--| Last Modified: July 1995
------------------------------------------------------------------------

  TYPE Days IS (Mon, Tue, Wed, Thu, Fri, Sat, Sun);
  PACKAGE Day_IO IS
     NEW Ada.Text_IO.Enumeration_IO (Enum => Days);
 
  Yesterday : Days;
  Today     : Days;
  Tomorrow  : Days;
     
BEGIN -- Three_Days

  -- prompt user to enter a day abbreviation
  Ada.Text_IO.Put 
    (Item => "Enter the first 3 letters of a day of the week > ");
  Day_IO.Get (Item => Today);

  -- find yesterday
  IF Today = Days'First THEN
    Yesterday := Days'Last;
  ELSE
    Yesterday := Days'Pred(Today);
  END IF;

  Ada.Text_IO.Put (Item => "Yesterday was ");
  Day_IO.Put (Item => Yesterday);
  Ada.Text_IO.New_Line;

  Ada.Text_IO.Put (Item => "Today is ");
  Day_IO.Put (Item => Today);
  Ada.Text_IO.New_Line;

  -- find tomorrow
  IF Today = Days'Last THEN
    Tomorrow := Days'First;
  ELSE
    Tomorrow := Days'Succ(Today);
  END IF;

  Ada.Text_IO.Put (Item => "Tomorrow is ");
  Day_IO.Put (Item => Tomorrow);
  Ada.Text_IO.New_Line;

END Three_Days;
Sample Run
Enter the first 3 letters of a day of the week > sat
Yesterday was FRI
Today is SAT
Tomorrow is SUN

TESTING

The sample run shows only a normal-case test. To complete the test plan, run the program for the invalid and special cases as well.


Exercises for Section 4.4

Self-Check

  1. Rewrite the algorithm for the modified payroll problem so that the computation of gross salary is performed in two steps rather than in one. Compute the base pay for all hours worked first. Then add in an extra amount only if overtime hours were worked.
  2. Refer to Program 4.3. Write the step that computes Dividend as two steps. Compute the basic dividend first and then add a bonus dividend only if there were no claims.
  3. Write a test plan for the insurance dividend algorithm.

Programming

  1. Provide the complete program for the overtime pay problem.


Previous | Next | Table of Contents | Index | Program List | Copyright

Copyright © 1996 by Addison-Wesley Publishing Company, Inc.