PROGRAM Stars (Input,Output);

(* Input a 2D map of intensities (0 to 20).  
   Calculate probable stars where average of element 
   and 4 cardinal neighbors is >= 6.0 
   Output map of probable stars. *)

CONST
   MaxRows = 20;         (* Screenful of stars *)
   MaxColumns = 80;
   MaxIntensity = 20;    (* Maximum data intensity level *)
   Blank = ' ';
   Threshold = 6.0;      (* "Visibility" threshold *)

TYPE
   NumberRows = 1..MaxRows;
   NumberColumns = 1..MaxColumns;
   Intensity = 0..MaxIntensity;
   RawArray = ARRAY [NumberRows,NumberColumns] OF Intensity;
   StarArray = ARRAY [NumberRows,NumberColumns] OF Char;

VAR
   RawDataArray : RawArray;    (* Raw image data *)
   StarMap : StarArray;        (* Probable star locations *)
   Rows : NumberRows;          (* Row dimension of raw input data *)
   Columns : NumberColumns;    (* Column dimension of raw input data *)





(**********************************************************
Input the raw data from user or redirected file.
First datum is number of rows (<= MaxRows) in data.
Second datum is number of columns (<= MaxColumns) in data.
Assumes data is correct.
Intensity data follows, line by line. *)

PROCEDURE GetRawData (Var RawData : RawArray;
                      Var RowSize : NumberRows;
                      Var ColumnSize : NumberColumns);
Var
   Datum : Intensity;
   I : NumberRows;
   J : NumberColumns;

  (* Input number of rows and number of columns of raw data. *)
  PROCEDURE GetSizes (Var Rows : NumberRows;
                      Var Columns : NumberColumns);
  Begin  (* GetSizes *)
     Write('Enter number of rows: ');
     Readln(Rows);
     Write('Enter number of columns: ');
     Readln(Columns);
  End;  (* GetSizes *)

Begin  (* GetRawData *)
   GetSizes(RowSize,ColumnSize);
   FOR I := 1 TO RowSize DO
     Begin
       Writeln('Row ',i,': ');      (* Prompt for row's data *)
       FOR J := 1 TO ColumnSize DO  (* Input row's data, column by column *)
         Begin
           Read(Datum);
           IF Datum > MaxIntensity THEN  (* Reset datum > maximum value to *)
              Datum := MaxIntensity;     (* maximum value.*)
           RawData[I,J] := Datum;
         End;
       Readln;
     End;
End;   (* GetRawData *)




(*****************************************************************)
(* Initialize star map to blanks *)

PROCEDURE InitStarMap (Var StarMap : StarArray;
                       RowSize : NumberRows;
                       ColumnSize : NumberColumns);
Var
   I : NumberRows;
   J : NumberColumns;
Begin
   FOR I := 1 TO RowSize DO
      FOR J := 1 TO ColumnSize DO
         StarMap[I,J] := Blank;
End;





(***************************************************************
Search raw data for elements whose intensity averaged with its
north, south, east and west neighbors is larger than a threshold. *)

PROCEDURE StarSearch (Raw : RawArray;
                      Var StarMap : StarArray;
                      RowSize : NumberRows;
                      ColumnSize : NumberColumns);
Var
   I : NumberRows;
   J : NumberColumns;


  (* Find sum of raw data element and its four cardinal neighbors *)

  FUNCTION Sum (A : RawArray; R : NumberRows; C : NumberColumns) : Integer;
  Begin
     Sum := A[R,C] + A[R,C-1] + A[R,C+1] + A[R-1,C] + A[R+1,C];
  End;


Begin   (* StarSearch *)
   FOR I := 2 TO RowSize-1 DO      (* All rows except first and last *)
      FOR J := 2 TO ColumnSize-1 DO  (* All columns except first and last *)
         (* if average of element and its 4 neighbors > threshold *)
         IF (Sum(Raw,I,J) / 5) > Threshold THEN
            StarMap[I,J] := '*';      (* then say found a star *)
End;    (* StarSearch *)




(*************************************************************
Display the probable star map *)

PROCEDURE DisplayStars (StarMap : StarArray;
                        RowSize : NumberRows;
                        ColumnSize : NumberColumns);
Var
   I : NumberRows;
   J : NumberColumns;
Begin
   Writeln;

   FOR J := 0 TO ColumnSize DO     (* Border on top *)
      Write('-');
   Writeln('-');

   FOR I := 1 TO RowSize DO
    Begin
      Write('|');      (* Left border *)
      FOR J := 1 TO ColumnSize DO
         Write(StarMap[I,J]);      (* Blank or asterisk *)
      Writeln('|');    (* Right border *)
    End;

   FOR J := 0 TO ColumnSize DO     (* Border on bottom *)
      Write('-');
   Writeln('-');

End;




BEGIN  (* Stars *)

      GetRawData(RawDataArray,Rows,Columns);

      InitStarMap(StarMap,Rows,Columns);

      StarSearch(RawDataArray,StarMap,Rows,Columns);

      DisplayStars(StarMap,Rows,Columns);

END.   (* Stars *)
