How to resolve the algorithm Text processing/2 step by step in the Go programming language
How to resolve the algorithm Text processing/2 step by step in the Go programming language
Table of Contents
Problem Statement
The following task concerns data that came from a pollution monitoring station with twenty-four instruments monitoring twenty-four aspects of pollution in the air. Periodically a record is added to the file, each record being a line of 49 fields separated by white-space, which can be one or more space or tab characters. The fields (from the left) are: i.e. a datestamp followed by twenty-four repetitions of a floating-point instrument value and that instrument's associated integer flag. Flag values are >= 1 if the instrument is working and < 1 if there is some problem with it, in which case that instrument's value should be ignored. A sample from the full data file readings.txt, which is also used in the Text processing/1 task, follows: Data is no longer available at that link. Zipped mirror available here
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Text processing/2 step by step in the Go programming language
This program reads readings.txt
, containing data for multiple instruments in a specific format: one line per day, with the following fields:
- Date (format
yyyy-mm-dd
) - A series of
readings
pairs of numbers: reading value, and associated flag (1 if the reading is good, 0 otherwise)
It aims to determine:
- If the format of the data is valid, i.e., each line has the expected number of fields in the correct format.
- The total number of records with good readings for all instruments.
- The number of unique dates with good readings for all instruments.
The main function:
- Opens the file for reading, using
os.Open
. - Declares three variables:
allGood
: Counts records with good readings for all instruments.uniqueGood
: Counts unique dates with good readings for all instruments.m
: A map of dates (keys) to a boolean value indicating if an "all-good" record was seen for that date.
- Creates a
bufio.Scanner
to read the file line by line. - Iterates through the lines using the
Scan
method. - For each line:
- Splits the line into fields using
strings.Fields
. - Checks if the number of fields is as expected using the constant
fields
. - Parses the date field using
time.Parse
. - Iterates through the remaining fields in pairs.
- Parses the flag value and checks if it's greater than 0 (indicating a good reading).
- If the flag is good, parses the reading value.
- If any flag is not good, sets
good
tofalse
.
- Splits the line into fields using
- If all readings are good:
- Increments
allGood
.
- Increments
- Checks if the date has been seen before in the
m
map. - If the date has been seen before, prints a message indicating a duplicate date stamp.
- Updates the
m
map with the newgood
value for the date. - If
good
istrue
and the date was not previously marked as "all-good":- Increments
uniqueGood
.
- Increments
- If there was an error in reading the lines, prints an error message.
After processing all lines, it prints the results:
- Confirms data format validity.
- Displays the count of records with all good readings.
- Displays the count of unique dates with all good readings.
Source code in the go programming language
package main
import (
"bufio"
"fmt"
"log"
"os"
"strconv"
"strings"
"time"
)
const (
filename = "readings.txt"
readings = 24 // per line
fields = readings*2 + 1 // per line
dateFormat = "2006-01-02"
)
func main() {
file, err := os.Open(filename)
if err != nil {
log.Fatal(err)
}
defer file.Close()
var allGood, uniqueGood int
// map records not only dates seen, but also if an all-good record was
// seen for the key date.
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 { // value is good
_, err := strconv.ParseFloat(f[i], 64)
if err != nil {
log.Fatal(err)
}
} else { // value is bad
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.")
}
You may also check:How to resolve the algorithm State name puzzle step by step in the Python programming language
You may also check:How to resolve the algorithm Dynamic variable names step by step in the zkl programming language
You may also check:How to resolve the algorithm Sorting algorithms/Selection sort step by step in the Clojure programming language
You may also check:How to resolve the algorithm Arbitrary-precision integers (included) step by step in the Erlang programming language
You may also check:How to resolve the algorithm Constrained genericity step by step in the Swift programming language