Chapter 12 Overheads

PROBLEM : HOW MANY ACCOUNTS DOES EACH CUSTOMER HAVE IN THE DOWN-THE-STREET BANK?

A NEW STATE REGULATION SAYS THAT YOUR BANK MUST SUBMIT A REPORT ON HOW MANY ACCOUNTS EACH CUSTOMER HAS. IT IS NOT IMPORTANT WHAT TYPE OF ACCOUNTS THEY ARE; WHAT THEY NEED TO KNOW IS HOW MANY ARE ASSIGNED TO THE SAME SOCIAL SECURITY NUMBER.

CAN YOU WRITE A PROGRAM TO TAKE THEIR FILES AND CREATE THE PROPER REPORT?
 
INPUT : SOCIAL SECURITY NUMBER (ssno)
BALANCE (bal)
OUTPUT : SOCIAL SECURITY NUMBER
NUMBER OF ACCOUNTS (numacts)
ACCUMULATED BALANCE (acbal)*

* The govenment doesn't need this, but the bank thinks it would be a useful by-product of the program.



DATA STRUCTURES
RECORD : SSNO :
ACBAL :
NUMACTS :
INTEGER
REAL
INTEGER
A ONE DIMENSIONAL ARRAY OF RECORDS

TOP DOWN DESIGN

LEVEL 0:
WHILE MORE ACCOUNTS
GET DATA
PROCESS DATA
SORT RECORDS*
PRINT RECORDS

* the output must be in order by social security number.



RECORDS :
TYPE ACCOUNT =
RECORD
SSNO :
ACBAL :
NUMACTS :
INTEGER;
REAL;
INTEGER;
END;
 
VAR LIST : ARRAY[1..LIMIT] OF ACCOUNT
 
LIST[I].SSNO
LIST[I].ACBAL
LIST[I].NUMACTS

This is like a two dimensional array with the values in each column being a different type.



LEVEL 1:
GET DATA
READLN( SSNO, BAL )
PROCESS DATA
IF ACCOUNT NOT ON LIST
THEN ENTER IT
ELSE UPDATE

LEVEL 2:
NOT ON LIST
SEARCH LIST FOR CURRENT SSNO BEGINNING AT 1 AND GOING TO CURRENT NUMBER ON LIST

IF YOU REACH THE END AND HAVEN'T FOUND IT, THEN ENTER IT AND INCREASE NUMBER ON LIST BY 1

IF FOUND, STOP LOOKING & UPDATE



UPDATE
NUMACTS IS WHAT IT WAS + 1
ACBAL IS WHAT IT WAS + BAL

LEVEL 1:
SORT
FOR COUNTER := 1 TO NUMBER OF ACTS
FIND MINIMUM BETWEEN COUNTER & NUMBER OF ACTS
SWAP MINIMUM & CURRENT
PRINT



PROGRAM BANK( INPUT, OUTPUT );
CONST
   LIMIT = 10000;
TYPE
   ACCOUNT = RECORD
         SSNO : INTEGER;
        ACBAL : REAL;
      NUMACTS : INTEGER
   END;

   ACCOUNTS = ARRAY [1..LIMIT] OF ACCOUNT;

VAR
   LIST : ACCOUNTS;
   NUMCUST : INTEGER

procedures

BEGIN
   PROCESS( LIST, NUMCUST );
   SORT( LIST, NUMCUST );
   PRINT( LIST, NUMCUST );
END.



PROCEDURE PROCESS( VAR LIST : ACCOUNTS; VAR NUMCUST : INTEGER );
VAR
   TEMP : ACCOUNT;
   FOUND : BOOLEAN;
   I : INTEGER;
BEGIN
   NUMCUST := 0;
   REPEAT
      READLN( TEMP.SSNO, TEMP.ACBAL );
      I := 1;
      FOUND := FALSE;
      WHILE NOT FOUND AND (I <= NUMCUST) DO
         IF TEMP.SSNO = LIST[I].SSNO
            THEN FOUND := TRUE
            ELSE I := I + 1;
      IF FOUND THEN
         BEGIN
            LIST[I].ACBAL := LIST[I].ACBAL + TEMP.ACBAL;
            LIST[I].NUMACTS := LIST[I].NUMACTS + 1;
         END
      ELSE
         BEGIN
            TEMP.NUMACTS := 1;
            LIST[I] := TEMP;
            NUMCUST := I;
         END;
   UNTIL EOF;
END;



PROCEDURE SORT( VAR LIST : ACCOUNTS; VAR NUMCUST : INTEGER );
VAR
   I : INTEGER;

(*$ NEST EXCHANGE AND MINI HERE $*)

BEGIN
   FOR I := I TO NUMCUST DO
      EXCHANGE( LIST[I], LIST[MINI( LIST, NUMCUST, I )]);
END;



PROCEDURE EXCHANGE( VAR X, Y : ACCOUNT );
VAR
   TEMP : ACCOUNT;
BEGIN
   TEMP := X;
   X := Y;
   Y := TEMP;
END;

FUNCTION MINI( VAR LIST : ACCOUNTS; NUMCUST, LL : INTEGER ) : INTEGER;
VAR
   I, K : INTEGER;
BEGIN
   K := LL
   FOR I := LL + 1 TO NUMCUST DO
      IF LIST[I].SSNO < LIST[K].SSNO
         THEN K := I;
   MINI := K;
END;



PROCEDURE PRINT( VAR INFO : ACCOUNTS; NUMCUST : INTEGER );
VAR
   I : INTEGER;
BEGIN
   FOR I := 1 TO NUMCUST DO
      WRITELN( INFO[I].SSNO, INFO[I].ACBAL, INFO[I].NUMACTS );
END;



ORDER OF PROGRAM BANK

MAIN PROGRAM declarations
PROCEDURE PROCESS entire procedure
PROCEDURE SORT declarations
FUNCTION MINI entire function
PROCEDURE EXCHANGE entire procedure
PROCEDURE SORT body
PROCEDURE PRINT entire procedure
MAIN PROGRAM body



SUMMARIZE
LINER SEARCH
WHILE NOT AT LIMIT AND NOT FOUND
RECORDS
DEFINE :
TYPE name = RECORD
   id1 : TYPE;
   id2 : TYPE;
END;
VAR id3 : name
USE :
   id3.id1 or id3.id2
ORDER OF SUBPROGRAMS
DEFINE BEFORE FIRST USE