Task: Text processing_2




Go: package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"
	"time"
)

const (
	filename   = "readings.txt"
	readings   = 24             
	fields     = readings*2 + 1 
	dateFormat = "2006-01-02"
)

func main() {
	file, err := os.Open(filename)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()
	var allGood, uniqueGood int
	
	
	m := make(map[time.Time]bool)
	s := bufio.NewScanner(file)
	for s.Scan() {
		f := strings.Fields(s.Text())
		if len(f) != fields {
			log.Fatal("unexpected format,", len(f), "fields.")
		}
		ts, err := time.Parse(dateFormat, f[0])
		if err != nil {
			log.Fatal(err)
		}
		good := true
		for i := 1; i < fields; i += 2 {
			flag, err := strconv.Atoi(f[i+1])
			if err != nil {
				log.Fatal(err)
			}
			if flag > 0 { 
				_, err := strconv.ParseFloat(f[i], 64)
				if err != nil {
					log.Fatal(err)
				}
			} else { 
				good = false
			}
		}
		if good {
			allGood++
		}
		previouslyGood, seen := m[ts]
		if seen {
			fmt.Println("Duplicate datestamp:", f[0])
		}
		m[ts] = previouslyGood || good
		if !previouslyGood && good {
			uniqueGood++
		}
	}
	if err := s.Err(); err != nil {
		log.Fatal(err)
	}

	fmt.Println("\nData format valid.")
	fmt.Println(allGood, "records with good readings for all instruments.")
	fmt.Println(uniqueGood,
		"unique dates with good readings for all instruments.")
}






COBOL:        IDENTIFICATION DIVISION.
       PROGRAM-ID. text-processing-2.

       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT readings ASSIGN Input-File-Path
               ORGANIZATION LINE SEQUENTIAL
               FILE STATUS file-status.
       
       DATA DIVISION.
       FILE SECTION.
       FD  readings.
       01  reading-record.
           03  date-stamp          PIC X(10).
           03  FILLER              PIC X.
           03  input-data          PIC X(300).

       LOCAL-STORAGE SECTION.
       78  Input-File-Path         VALUE "readings.txt".
       78  Num-Data-Points         VALUE 48.

       01  file-status             PIC XX.

       01  current-line            PIC 9(5).

       01  num-date-stamps-read    PIC 9(5).
       01  read-date-stamps-area.
           03  read-date-stamps    PIC X(10) OCCURS 1 TO 10000 TIMES
                                   DEPENDING ON num-date-stamps-read
                                   INDEXED BY date-stamp-idx.

       01  offset                  PIC 999.
       01  data-len                PIC 999.
       01  data-flag               PIC X.
           88  data-not-found      VALUE "N".

       01  data-field              PIC X(25).

       01  i                       PIC 99.

       01  num-good-readings       PIC 9(5).

       01  reading-flag            PIC X.
           88 bad-reading          VALUE "B".

       01  delim                   PIC X.

       PROCEDURE DIVISION.
       DECLARATIVES.
       readings-error SECTION.
           USE AFTER ERROR ON readings

           DISPLAY "An error occurred while using " Input-File-Path
           DISPLAY "Error code " file-status
           DISPLAY "The program will terminate."

           CLOSE readings
           GOBACK
           .
       END DECLARATIVES.

       main-line.
           OPEN INPUT readings

           
           PERFORM FOREVER
               READ readings
                   AT END
                       EXIT PERFORM
               END-READ

               ADD 1 TO current-line

               IF reading-record = SPACES
                   DISPLAY "Line " current-line " is blank."
                   EXIT PERFORM CYCLE
               END-IF

               PERFORM check-duplicate-date-stamp

               
               
               INITIALIZE offset, reading-flag, data-flag
               PERFORM VARYING i FROM 1 BY 1 UNTIL Num-Data-Points < i
                   PERFORM get-next-field
                   IF data-not-found
                       DISPLAY "Line " current-line " has missing "
                           "fields."
                       SET bad-reading TO TRUE
                       EXIT PERFORM
                   END-IF

                   
                   IF FUNCTION MOD(i, 2) = 0 AND NOT bad-reading
                       IF FUNCTION NUMVAL(data-field) <= 0
                           SET bad-reading TO TRUE
                       END-IF
                   END-IF

                   ADD data-len TO offset
               END-PERFORM

               IF NOT bad-reading
                   ADD 1 TO num-good-readings
               END-IF
           END-PERFORM

           CLOSE readings

           
           DISPLAY SPACE
           DISPLAY current-line " lines read."
           DISPLAY num-good-readings " have good readings for all "
               "instruments."

           GOBACK
           .
       check-duplicate-date-stamp.
           SEARCH read-date-stamps
               AT END
                   ADD 1 TO num-date-stamps-read
                   MOVE date-stamp
                       TO read-date-stamps (num-date-stamps-read)

               WHEN read-date-stamps (date-stamp-idx) = date-stamp
                   DISPLAY "Date " date-stamp " is duplicated at "
                       "line " current-line "."
           END-SEARCH
           .
       get-next-field.
           INSPECT input-data (offset:) TALLYING offset
               FOR LEADING X"09"

           
           MOVE X"09" TO delim
           PERFORM find-num-chars-before-delim

           
           IF FUNCTION SUM(data-len, offset) > 300
               
               
               MOVE SPACE TO delim
               PERFORM find-num-chars-before-delim

               IF FUNCTION SUM(data-len, offset) > 300
                   SET data-not-found TO TRUE
                   EXIT PARAGRAPH
               END-IF
           END-IF

           IF data-len = 0
               SET data-not-found TO TRUE
               EXIT PARAGRAPH
           END-IF

           MOVE input-data (offset:data-len) TO data-field
           .
       find-num-chars-before-delim.
           INITIALIZE data-len
           INSPECT input-data (offset:) TALLYING data-len
               FOR CHARACTERS BEFORE delim
           .