all tasks

This commit is contained in:
Ingy döt Net 2013-04-11 01:07:29 -07:00
parent b83f433714
commit 68f8f3e56b
14735 changed files with 178959 additions and 0 deletions

View file

@ -0,0 +1,34 @@
{{Template:clarify task}}
Often data is produced by one program, in the wrong format for later use by another program or person. In these situations another program can be written to parse and transform the original data into a format useful to the other. The term "Data Munging" is [http://www.google.co.uk/search?q=%22data+munging%22 often] used in programming circles for this task.
A [http://groups.google.co.uk/group/comp.lang.awk/msg/0ecba3a3fbf247d8?hl=en request] on the comp.lang.awk newsgroup lead to a typical data munging task:
<pre>I have to analyse data files that have the following format:
Each row corresponds to 1 day and the field logic is: $1 is the date,
followed by 24 value/flag pairs, representing measurements at 01:00,
02:00 ... 24:00 of the respective day. In short:
<date> <val1> <flag1> <val2> <flag2> ... <val24> <flag24>
Some test data is available at:
... (nolonger available at original location)
I have to sum up the values (per day and only valid data, i.e. with
flag>0) in order to calculate the mean. That's not too difficult.
However, I also need to know what the "maximum data gap" is, i.e. the
longest period with successive invalid measurements (i.e values with
flag<=0)</pre>
The data is [http://www.eea.europa.eu/help/eea-help-centre/faqs/how-do-i-obtain-eea-reports free to download and use] and is of this format:
<pre style="height:20ex;overflow:scroll">
1991-03-30 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1
1991-03-31 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 10.000 1 20.000 1 20.000 1 20.000 1 35.000 1 50.000 1 60.000 1 40.000 1 30.000 1 30.000 1 30.000 1 25.000 1 20.000 1 20.000 1 20.000 1 20.000 1 20.000 1 35.000 1
1991-03-31 40.000 1 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2 0.000 -2
1991-04-01 0.000 -2 13.000 1 16.000 1 21.000 1 24.000 1 22.000 1 20.000 1 18.000 1 29.000 1 44.000 1 50.000 1 43.000 1 38.000 1 27.000 1 27.000 1 24.000 1 23.000 1 18.000 1 12.000 1 13.000 1 14.000 1 15.000 1 13.000 1 10.000 1
1991-04-02 8.000 1 9.000 1 11.000 1 12.000 1 12.000 1 12.000 1 27.000 1 26.000 1 27.000 1 33.000 1 32.000 1 31.000 1 29.000 1 31.000 1 25.000 1 25.000 1 24.000 1 21.000 1 17.000 1 14.000 1 15.000 1 12.000 1 12.000 1 10.000 1
1991-04-03 10.000 1 9.000 1 10.000 1 10.000 1 9.000 1 10.000 1 15.000 1 24.000 1 28.000 1 24.000 1 18.000 1 14.000 1 12.000 1 13.000 1 14.000 1 15.000 1 14.000 1 15.000 1 13.000 1 13.000 1 13.000 1 12.000 1 10.000 1 10.000 1
</pre>
Only a sample of the data showing its format is given above. The full example file may be downloaded [http://rosettacode.org/resources/readings.zip here].
Structure your program to show statistics for each line of the file, (similar to the original Python, Perl, and AWK examples below), followed by summary statistics for the file. When showing example output just show a few line statistics and the full end summary.

View file

@ -0,0 +1,2 @@
---
note: Text processing

View file

@ -0,0 +1,95 @@
INT no data := 0; # Current run of consecutive flags<0 in lines of file #
INT no data max := -1; # Max consecutive flags<0 in lines of file #
FLEX[0]STRING no data max line; # ... and line number(s) where it occurs #
REAL tot file := 0; # Sum of file data #
INT num file := 0; # Number of file data items with flag>0 #
# CHAR fs = " "; #
INT nf = 24;
INT upb list := nf;
FORMAT list repr = $n(upb list-1)(g", ")g$;
PROC exception = ([]STRING args)VOID:(
putf(stand error, ($"Exception"$, $", "g$, args, $l$));
stop
);
PROC raise io error = (STRING message)VOID:exception(("io error", message));
OP +:= = (REF FLEX []STRING rhs, STRING append)REF FLEX[]STRING: (
HEAP [UPB rhs+1]STRING out rhs;
out rhs[:UPB rhs] := rhs;
out rhs[UPB rhs+1] := append;
rhs := out rhs;
out rhs
);
INT upb opts = 3; # these are "a68g" "./Data_Munging.a68" & "-" #
[argc - upb opts]STRING in files;
FOR arg TO UPB in files DO in files[arg] := argv(upb opts + arg) OD;
MODE FIELD = STRUCT(REAL data, INT flag);
FORMAT field repr = $2(g)$;
FOR index file TO UPB in files DO
STRING file name = in files[index file], FILE file;
IF open(file, file name, stand in channel) NE 0 THEN
raise io error("Cannot open """+file name+"""") FI;
on logical file end(file, (REF FILE f)BOOL: logical file end done);
REAL tot line, INT num line;
# make term(file, ", ") for CSV data #
STRING date;
DO
tot line := 0; # sum of line data #
num line := 0; # number of line data items with flag>0 #
# extract field info #
[nf]FIELD data;
getf(file, ($10a$, date, field repr, data, $l$));
FOR key TO UPB data DO
FIELD field = data[key];
IF flag OF field<1 THEN
no data +:= 1
ELSE
# check run of data-absent data #
IF no data max = no data AND no data>0 THEN
no data max line +:= date FI;
IF no data max<no data AND no data>0 THEN
no data max := no data;
no data max line := date FI;
# re-initialise run of no data counter #
no data := 0;
# gather values for averaging #
tot line +:= data OF field;
num line +:= 1
FI
OD;
# totals for the file so far #
tot file +:= tot line;
num file +:= num line;
printf(($"Line: "g" Reject: "g(-2)" Accept: "g(-2)" Line tot: "g(-14, 3)" Line avg: "g(-14, 3)l$,
date,
UPB(data) -num line,
num line, tot line,
IF num line>0 THEN tot line/num line ELSE 0 FI))
OD;
logical file end done:
close(file)
OD;
FORMAT plural = $b(" ", "s")$,
p = $b("", "s")$;
upb list := UPB in files;
printf(($l"File"f(plural)" = "$, upb list = 1, list repr, in files, $l$,
$"Total = "g(-0, 3)l$, tot file,
$"Readings = "g(-0)l$, num file,
$"Average = "g(-0, 3)l$, tot file / num file));
upb list := UPB no data max line;
printf(($l"Maximum run"f(p)" of "g(-0)" consecutive false reading"f(p)" ends at line starting with date"f(p)": "$,
upb list = 1, no data max, no data max = 0, upb list = 1, list repr, no data max line, $l$))

View file

@ -0,0 +1,63 @@
BEGIN{
nodata = 0; # Current run of consecutive flags<0 in lines of file
nodata_max=-1; # Max consecutive flags<0 in lines of file
nodata_maxline="!"; # ... and line number(s) where it occurs
}
FNR==1 {
# Accumulate input file names
if(infiles){
infiles = infiles "," infiles
} else {
infiles = FILENAME
}
}
{
tot_line=0; # sum of line data
num_line=0; # number of line data items with flag>0
# extract field info, skipping initial date field
for(field=2; field<=NF; field+=2){
datum=$field;
flag=$(field+1);
if(flag<1){
nodata++
}else{
# check run of data-absent fields
if(nodata_max==nodata && (nodata>0)){
nodata_maxline=nodata_maxline ", " $1
}
if(nodata_max<nodata && (nodata>0)){
nodata_max=nodata
nodata_maxline=$1
}
# re-initialise run of nodata counter
nodata=0;
# gather values for averaging
tot_line+=datum
num_line++;
}
}
# totals for the file so far
tot_file += tot_line
num_file += num_line
printf "Line: %11s Reject: %2i Accept: %2i Line_tot: %10.3f Line_avg: %10.3f\n", \
$1, ((NF -1)/2) -num_line, num_line, tot_line, (num_line>0)? tot_line/num_line: 0
# debug prints of original data plus some of the computed values
#printf "%s %15.3g %4i\n", $0, tot_line, num_line
#printf "%s\n %15.3f %4i %4i %4i %s\n", $0, tot_line, num_line, nodata, nodata_max, nodata_maxline
}
END{
printf "\n"
printf "File(s) = %s\n", infiles
printf "Total = %10.3f\n", tot_file
printf "Readings = %6i\n", num_file
printf "Average = %10.3f\n", tot_file / num_file
printf "\nMaximum run(s) of %i consecutive false readings ends at line starting with date(s): %s\n", nodata_max, nodata_maxline
}

View file

@ -0,0 +1,76 @@
with Ada.Text_IO; use Ada.Text_IO;
with Strings_Edit; use Strings_Edit;
with Strings_Edit.Floats; use Strings_Edit.Floats;
with Strings_Edit.Integers; use Strings_Edit.Integers;
procedure Data_Munging is
Syntax_Error : exception;
type Gap_Data is record
Count : Natural := 0;
Line : Natural := 0;
Pointer : Integer;
Year : Integer;
Month : Integer;
Day : Integer;
end record;
File : File_Type;
Max : Gap_Data;
This : Gap_Data;
Current : Gap_Data;
Count : Natural := 0;
Sum : Float := 0.0;
begin
Open (File, In_File, "readings.txt");
loop
declare
Line : constant String := Get_Line (File);
Pointer : Integer := Line'First;
Flag : Integer;
Data : Float;
begin
Current.Line := Current.Line + 1;
Get (Line, Pointer, SpaceAndTab);
Get (Line, Pointer, Current.Year);
Get (Line, Pointer, Current.Month);
Get (Line, Pointer, Current.Day);
while Pointer <= Line'Last loop
Get (Line, Pointer, SpaceAndTab);
Current.Pointer := Pointer;
Get (Line, Pointer, Data);
Get (Line, Pointer, SpaceAndTab);
Get (Line, Pointer, Flag);
if Flag < 0 then
if This.Count = 0 then
This := Current;
end if;
This.Count := This.Count + 1;
else
if This.Count > 0 and then Max.Count < This.Count then
Max := This;
end if;
This.Count := 0;
Count := Count + 1;
Sum := Sum + Data;
end if;
end loop;
exception
when End_Error =>
raise Syntax_Error;
end;
end loop;
exception
when End_Error =>
Close (File);
if This.Count > 0 and then Max.Count < This.Count then
Max := This;
end if;
Put_Line ("Average " & Image (Sum / Float (Count)) & " over " & Image (Count));
if Max.Count > 0 then
Put ("Max. " & Image (Max.Count) & " false readings start at ");
Put (Image (Max.Line) & ':' & Image (Max.Pointer) & " stamped ");
Put_Line (Image (Max.Year) & Image (Max.Month) & Image (Max.Day));
end if;
when others =>
Close (File);
Put_Line ("Syntax error at " & Image (Current.Line) & ':' & Image (Max.Pointer));
end Data_Munging;

View file

@ -0,0 +1,48 @@
integer bads, count, max_bads;
file f;
list l;
real s;
text bad_day, worst_day;
f_affix(f, "/dev/stdin");
max_bads = 0;
count = 0;
bads = 0;
s = 0;
while (f_list(f, l, 0) ^ -1) {
integer e, i;
i = 2;
while (i < 49) {
e = atoi(l_q_text(l, i));
if (0 < e) {
count += 1;
s += atof(l_q_text(l, i - 1));
if (max_bads < bads) {
max_bads = bads;
worst_day = bad_day;
}
bads = 0;
} else {
if (!bads) {
bad_day = l_q_text(l, 0);
}
bads += 1;
}
i += 2;
}
}
o_text("Averaged ");
o_real(3, s / count);
o_text(" over ");
o_integer(count);
o_text(" readings.\n");
o_text("Longest bad run ");
o_integer(max_bads);
o_text(", started ");
o_text(worst_day);
o_text(".\n");

View file

@ -0,0 +1,74 @@
# Author AlephX Aug 17 2011
SetFormat, float, 4.2
SetFormat, FloatFast, 4.2
data = %A_scriptdir%\readings.txt
result = %A_scriptdir%\results.txt
totvalid := 0
totsum := 0
totavg:= 0
Loop, Read, %data%, %result%
{
sum := 0
Valid := 0
Couples := 0
Lines := A_Index
Loop, parse, A_LoopReadLine, %A_Tab%
{
;MsgBox, Field number %A_Index% is %A_LoopField%
if A_index = 1
{
Date := A_LoopField
Counter := 0
}
else
{
Counter++
couples := Couples + 0.5
if Counter = 1
{
value := A_LoopField / 1
}
else
{
if A_loopfield > 0
{
Sum := Sum + value
Valid++
if (wrong > maxwrong)
{
maxwrong := wrong
lastwrongdate := currwrongdate
startwrongdate := firstwrongdate
startoccurrence := firstoccurrence
lastoccurrence := curroccurrence
}
wrong := 0
}
else
{
wrong++
currwrongdate := date
curroccurrence := (A_index-1) / 2
if (wrong = 1)
{
firstwrongdate := date
firstoccurrence := curroccurrence
}
}
Counter := 0
}
}
}
avg := sum / valid
TotValid := Totvalid+valid
TotSum := Totsum+sum
FileAppend, Day: %date% sum: %sum% avg: %avg% Readings: %valid%/%couples%`n
}
Totavg := TotSum / TotValid
FileAppend, `n`nDays %Lines%`nMaximal wrong readings: %maxwrong% from %startwrongdate% at %startoccurrence% to %lastwrongdate% at %lastoccurrence%`n`n, %result%
FileAppend, Valid readings: %TotValid%`nTotal Value: %TotSUm%`nAverage: %TotAvg%, %result%

View file

@ -0,0 +1,43 @@
file% = OPENIN("readings.txt")
IF file% = 0 THEN PRINT "Could not open test data file" : END
Total = 0
Count% = 0
BadMax% = 0
bad% = 0
WHILE NOT EOF#file%
text$ = GET$#file%
IF text$<>"" THEN
tab% = INSTR(text$, CHR$(9))
date$ = LEFT$(text$, tab% - 1)
acc = 0
cnt% = 0
FOR field% = 1 TO 24
dval = VALMID$(text$, tab%+1)
tab% = INSTR(text$, CHR$(9), tab%+1)
flag% = VALMID$(text$, tab%+1)
tab% = INSTR(text$, CHR$(9), tab%+1)
IF flag% > 0 THEN
acc += dval
cnt% += 1
bad% = 0
ELSE
bad% += 1
IF bad% > BadMax% BadMax% = bad% : BadDate$ = date$
ENDIF
NEXT field%
@% = &90A
PRINT "Date: " date$ " Good = "; cnt%, " Bad = "; 24-cnt%, ;
@% = &20308
IF cnt% THEN PRINT " Total = " acc " Mean = " acc / cnt% ;
PRINT
Total += acc
Count% += cnt%
ENDIF
ENDWHILE
CLOSE #file%
PRINT ' "Grand total = " ; Total
PRINT "Number of valid readings = " ; STR$(Count%)
PRINT "Overall mean = " ; Total / Count%
@% = &90A
PRINT '"Longest run of bad readings = " ; BadMax% " ending " BadDate$

View file

@ -0,0 +1,67 @@
@echo off
setlocal ENABLEDELAYEDEXPANSION
set maxrun= 0
set maxstart=
set maxend=
set notok=0
set inputfile=%1
for /F "tokens=1,*" %%i in (%inputfile%) do (
set date=%%i
call :processline %%j
)
echo\
echo max false: %maxrun% from %maxstart% until %maxend%
goto :EOF
:processline
set sum=0000
set count=0
set hour=1
:loop
if "%1"=="" goto :result
set num=%1
if "%2"=="1" (
if "%notok%" NEQ "0" (
set notok= !notok!
if /I "!notok:~-5!" GTR "%maxrun%" (
set maxrun=!notok:~-5!
set maxstart=%nok0date% %nok0hour%
set maxend=%nok1date% %nok1hour%
)
set notok=0
)
set /a sum+=%num:.=%
set /a count+=1
) else (
if "%notok%" EQU "0" (
set nok0date=%date%
set nok0hour=%hour%
) else (
set nok1date=%date%
set nok1hour=%hour%
)
set /a notok+=1
)
shift
shift
set /a hour+=1
goto :loop
:result
if "%count%"=="0" (
set mean=0
) else (
set /a mean=%sum%/%count%
)
if "%mean%"=="0" set mean=0000
if "%sum%"=="0" set sum=0000
set mean=%mean:~0,-3%.%mean:~-3%
set sum=%sum:~0,-3%.%sum:~-3%
set count= %count%
set sum= %sum%
set mean= %mean%
echo Line: %date% Accept: %count:~-3% tot: %sum:~-8% avg: %mean:~-8%
goto :EOF

View file

@ -0,0 +1,67 @@
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <iomanip>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
using std::cout;
using std::endl;
const int NumFlags = 24;
int main()
{
std::fstream file("readings.txt");
int badCount = 0;
std::string badDate;
int badCountMax = 0;
while(true)
{
std::string line;
getline(file, line);
if(!file.good())
break;
std::vector<std::string> tokens;
boost::algorithm::split(tokens, line, boost::is_space());
if(tokens.size() != NumFlags * 2 + 1)
{
cout << "Bad input file." << endl;
return 0;
}
double total = 0.0;
int accepted = 0;
for(size_t i = 1; i < tokens.size(); i += 2)
{
double val = boost::lexical_cast<double>(tokens[i]);
int flag = boost::lexical_cast<int>(tokens[i+1]);
if(flag > 0)
{
total += val;
++accepted;
badCount = 0;
}
else
{
++badCount;
if(badCount > badCountMax)
{
badCountMax = badCount;
badDate = tokens[0];
}
}
}
cout << tokens[0];
cout << " Reject: " << std::setw(2) << (NumFlags - accepted);
cout << " Accept: " << std::setw(2) << accepted;
cout << " Average: " << std::setprecision(5) << total / accepted << endl;
}
cout << endl;
cout << "Maximum number of consecutive bad readings is " << badCountMax << endl;
cout << "Ends on date " << badDate << endl;
}

View file

@ -0,0 +1,85 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int badHrs, maxBadHrs;
static double hrsTot = 0.0;
static int rdgsTot = 0;
char bhEndDate[40];
int mungeLine( char *line, int lno, FILE *fout )
{
char date[40], *tkn;
int dHrs, flag, hrs2, hrs;
double hrsSum;
int hrsCnt = 0;
double avg;
tkn = strtok(line, ".");
if (tkn) {
int n = sscanf(tkn, "%s %d", &date, &hrs2);
if (n<2) {
printf("badly formated line - %d %s\n", lno, tkn);
return 0;
}
hrsSum = 0.0;
while( tkn= strtok(NULL, ".")) {
n = sscanf(tkn,"%d %d %d", &dHrs, &flag, &hrs);
if (n>=2) {
if (flag > 0) {
hrsSum += 1.0*hrs2 + .001*dHrs;
hrsCnt += 1;
if (maxBadHrs < badHrs) {
maxBadHrs = badHrs;
strcpy(bhEndDate, date);
}
badHrs = 0;
}
else {
badHrs += 1;
}
hrs2 = hrs;
}
else {
printf("bad file syntax line %d: %s\n",lno, tkn);
}
}
avg = (hrsCnt > 0)? hrsSum/hrsCnt : 0.0;
fprintf(fout, "%s Reject: %2d Accept: %2d Average: %7.3f\n",
date, 24-hrsCnt, hrsCnt, hrsSum/hrsCnt);
hrsTot += hrsSum;
rdgsTot += hrsCnt;
}
return 1;
}
int main()
{
FILE *infile, *outfile;
int lineNo = 0;
char line[512];
const char *ifilename = "readings.txt";
outfile = fopen("V0.txt", "w");
infile = fopen(ifilename, "rb");
if (!infile) {
printf("Can't open %s\n", ifilename);
exit(1);
}
while (NULL != fgets(line, 512, infile)) {
lineNo += 1;
if (0 == mungeLine(line, lineNo, outfile))
printf("Bad line at %d",lineNo);
}
fclose(infile);
fprintf(outfile, "File: %s\n", ifilename);
fprintf(outfile, "Total: %.3f\n", hrsTot);
fprintf(outfile, "Readings: %d\n", rdgsTot);
fprintf(outfile, "Average: %.3f\n", hrsTot/rdgsTot);
fprintf(outfile, "\nMaximum number of consecutive bad readings is %d\n", maxBadHrs);
fprintf(outfile, "Ends on date %s\n", bhEndDate);
fclose(outfile);
return 0;
}

View file

@ -0,0 +1,101 @@
(defstruct (measurement
(:conc-name "MEASUREMENT-")
(:constructor make-measurement (counter line date flag value)))
(counter 0 :type (integer 0))
(line 0 :type (integer 0))
(date nil :type symbol)
(flag 0 :type integer)
(value 0 :type real))
(defun measurement-valid-p (m)
(> (measurement-flag m) 0))
(defun map-data-stream (function stream)
(flet ((scan (&optional (errorp t)) (read stream errorp nil)))
(loop
:with global-count = 0
:for date = (scan nil) :then (scan nil)
:for line-number :upfrom 1
:while date
:do (loop
:for count :upfrom 0 :below 24
:do (let* ((value (scan)) (flag (scan)))
(funcall function (make-measurement global-count line-number date flag value))
(incf global-count)))
:finally (return global-count))))
(defun map-data-file (function pathname)
(with-open-file (stream pathname
:element-type 'character
:direction :input
:if-does-not-exist :error)
(map-data-stream function stream)))
(defmacro do-data-stream ((variable stream) &body body)
`(map-data-stream
(lambda (,variable) ,@body)
,stream))
(defmacro do-data-file ((variable file) &body body)
`(map-data-file
(lambda (,variable) ,@body)
,file))
(let ((current-day nil)
(current-line 0)
(beginning-of-misreadings nil)
(current-length 0)
(worst-beginning nil)
(worst-length 0)
(sum-of-day 0)
(count-of-day 0))
(flet ((write-end-of-day-report ()
(when current-day
(format t "Line ~5D Date ~A: Accepted ~2D Total ~8,3F Average ~8,3F~%"
current-line current-day count-of-day sum-of-day
(if (> count-of-day 0) (/ sum-of-day count-of-day) sum-of-day)))))
(do-data-file (m #P"D:/Scratch/data.txt")
(let* ((date (measurement-date m))
(line-number (measurement-line m))
(validp (measurement-valid-p m))
(day-changed-p (/= current-line line-number))
(value (measurement-value m)))
(when day-changed-p
(write-end-of-day-report)
(setf current-day date)
(setf current-line line-number)
(setf sum-of-day 0)
(setf count-of-day 0))
(if (not validp)
(if beginning-of-misreadings
(incf current-length)
(progn
(setf beginning-of-misreadings m)
(setf current-length 1)))
(progn
(when beginning-of-misreadings
(if (> current-length worst-length)
(progn
(setf worst-beginning beginning-of-misreadings)
(setf worst-length current-length))
(progn
(setf beginning-of-misreadings nil)
(setf current-length 0))))
(incf sum-of-day value)
(incf count-of-day)))))
(when (and beginning-of-misreadings (> current-length worst-length))
(setf worst-beginning beginning-of-misreadings)
(setf worst-length current-length))
(write-end-of-day-report))
(format t "Worst run started ~A (~D) and has length ~D~%"
(measurement-date worst-beginning)
(measurement-counter worst-beginning)
worst-length))

View file

@ -0,0 +1,75 @@
import std.stdio, std.conv, std.string;
void main(string[] args) {
/*const*/ auto fileNames = (args.length == 1) ? ["readings.txt"] :
args[1 .. $];
int noData, noDataMax = -1;
string[] noDataMaxLine;
double fileTotal = 0.0;
int fileValues;
foreach (fileName; fileNames) {
foreach (char[] line; File(fileName).byLine()) {
double lineTotal = 0.0;
int lineValues;
// Extract field info
const parts = line.split();
const date = parts[0];
const fields = parts[1 .. $];
assert(fields.length % 2 == 0,
format("Expected even number of fields, not %d.",
fields.length));
for (int i; i < fields.length; i += 2) {
immutable value = to!double(fields[i]);
immutable flag = to!int(fields[i + 1]);
if (flag < 1) {
noData++;
continue;
}
// Check run of data-absent fields
if (noDataMax == noData && noData > 0)
noDataMaxLine ~= date.idup;
if (noDataMax < noData && noData > 0) {
noDataMax = noData;
noDataMaxLine.length = 1;
noDataMaxLine[0] = date.idup;
}
// Re-initialise run of noData counter
noData = 0;
// Gather values for averaging
lineTotal += value;
lineValues++;
}
// Totals for the file so far
fileTotal += lineTotal;
fileValues += lineValues;
writefln("Line: %11s Reject: %2d Accept: %2d" ~
" Line_tot: %10.3f Line_avg: %10.3f",
date,
fields.length / 2 - lineValues,
lineValues,
lineTotal,
(lineValues > 0) ? lineTotal / lineValues : 0.0);
}
}
writeln("\nFile(s) = ", fileNames.join(", "));
writefln("Total = %10.3f", fileTotal);
writefln("Readings = %6d", fileValues);
writefln("Average = %10.3f", fileTotal / fileValues);
writefln("\nMaximum run(s) of %d consecutive false " ~
"readings ends at line starting with date(s): %s",
noDataMax, join(noDataMaxLine, ", "));
}

View file

@ -0,0 +1,93 @@
\ data munging
\ 1991-03-30[\t10.000\t[-]1]*24
\ 1. mean of valid (flag > 0) values per day and overall
\ 2. length of longest run of invalid values, and when it happened
fvariable day-sum
variable day-n
fvariable total-sum
variable total-n
10 constant date-size \ yyyy-mm-dd
create cur-date date-size allot
create bad-date date-size allot
variable bad-n
create worst-date date-size allot
variable worst-n
: split ( buf len char -- buf' l2 buf l1 ) \ where buf'[0] = char, l1 = len-l2
>r 2dup r> scan
2swap 2 pick - ;
: next-sample ( buf len -- buf' len' fvalue flag )
#tab split >float drop 1 /string
#tab split snumber? drop >r 1 /string r> ;
: ok? 0> ;
: add-sample ( value -- )
day-sum f@ f+ day-sum f!
1 day-n +! ;
: add-day
day-sum f@ total-sum f@ f+ total-sum f!
day-n @ total-n +! ;
: add-bad-run
bad-n @ 0= if
cur-date bad-date date-size move
then
1 bad-n +! ;
: check-worst-run
bad-n @ worst-n @ > if
bad-n @ worst-n !
bad-date worst-date date-size move
then
0 bad-n ! ;
: hour ( buf len -- buf' len' )
next-sample ok? if
add-sample
check-worst-run
else
fdrop
add-bad-run
then ;
: .mean ( sum count -- ) 0 d>f f/ f. ;
: day ( line len -- )
2dup + #tab swap c! 1+ \ append tab for parsing
#tab split cur-date swap move 1 /string \ skip date
0e day-sum f!
0 day-n !
24 0 do hour loop 2drop
cur-date date-size type ." mean = "
day-sum f@ day-n @ .mean cr
add-day ;
stdin value input
: main
s" input.txt" r/o open-file throw to input
0e total-sum f!
0 total-n !
0 worst-n !
begin pad 512 input read-line throw
while pad swap day
repeat
input close-file throw
worst-n @ if
." Longest interruption: " worst-n @ .
." hours starting " worst-date date-size type cr
then
." Total mean = "
total-sum f@ total-n @ .mean cr ;
main bye

View file

@ -0,0 +1,101 @@
package main
import (
"bufio"
"fmt"
"io"
"os"
"strconv"
"strings"
)
var fn = "readings.txt"
func main() {
f, err := os.Open(fn)
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
var (
badRun, maxRun int
badDate, maxDate string
fileSum float64
fileAccept int
)
for lr := bufio.NewReader(f); ; {
line, pref, err := lr.ReadLine()
if err == io.EOF {
break
}
if err != nil {
fmt.Println(err)
return
}
if pref {
fmt.Println("Unexpected long line.")
return
}
f := strings.Fields(string(line))
if len(f) != 49 {
fmt.Println("unexpected format,", len(f), "fields.")
return
}
var accept int
var sum float64
for i := 1; i < 49; i += 2 {
flag, err := strconv.Atoi(f[i+1])
if err != nil {
fmt.Println(err)
return
}
if flag > 0 { // value is good
if badRun > 0 { // terminate bad run
if badRun > maxRun {
maxRun = badRun
maxDate = badDate
}
badRun = 0
}
value, err := strconv.ParseFloat(f[i], 64)
if err != nil {
fmt.Println(err)
return
}
sum += value
accept++
} else { // value is bad
if badRun == 0 {
badDate = f[0]
}
badRun++
}
}
fmt.Printf("Line: %s Reject %2d Accept: %2d Line_tot:%9.3f",
f[0], 24-accept, accept, sum)
if accept > 0 {
fmt.Printf(" Line_avg:%8.3f\n", sum/float64(accept))
} else {
fmt.Println("")
}
fileSum += sum
fileAccept += accept
}
fmt.Println("\nFile =", fn)
fmt.Printf("Total = %.3f\n", fileSum)
fmt.Println("Readings = ", fileAccept)
if fileAccept > 0 {
fmt.Printf("Average = %.3f\n", fileSum/float64(fileAccept))
}
if badRun > 0 && badRun > maxRun {
maxRun = badRun
maxDate = badDate
}
if maxRun == 0 {
fmt.Println("\nAll data valid.")
} else {
fmt.Printf("\nMax data gap = %d, beginning on line %s.\n",
maxRun, maxDate)
}
}

View file

@ -0,0 +1,47 @@
import Data.List
import Numeric
import Control.Arrow
import Control.Monad
import Text.Printf
import System.Environment
import Data.Function
type Date = String
type Value = Double
type Flag = Bool
readFlg :: String -> Flag
readFlg = (> 0).read
readNum :: String -> Value
readNum = fst.head.readFloat
take2 = takeWhile(not.null).unfoldr (Just.splitAt 2)
parseData :: [String] -> (Date,[(Value,Flag)])
parseData = head &&& map(readNum.head &&& readFlg.last).take2.tail
sumAccs :: (Date,[(Value,Flag)]) -> (Date, ((Value,Int),[Flag]))
sumAccs = second (((sum &&& length).concat.uncurry(zipWith(\v f -> [v|f])) &&& snd).unzip)
maxNAseq :: [Flag] -> [(Int,Int)]
maxNAseq = head.groupBy((==) `on` fst).sortBy(flip compare)
. concat.uncurry(zipWith(\i (r,b)->[(r,i)|not b]))
. first(init.scanl(+)0). unzip
. map ((fst &&& id).(length &&& head)). group
main = do
file:_ <- getArgs
f <- readFile file
let dat :: [(Date,((Value,Int),[Flag]))]
dat = map (sumAccs. parseData. words).lines $ f
summ = ((sum *** sum). unzip *** maxNAseq.concat). unzip $ map snd dat
totalFmt = "\nSummary\t\t accept: %d\t total: %.3f \taverage: %6.3f\n\n"
lineFmt = "%8s\t accept: %2d\t total: %11.3f \taverage: %6.3f\n"
maxFmt = "Maximum of %d consecutive false readings, starting on line /%s/ and ending on line /%s/\n"
-- output statistics
putStrLn "\nSome lines:\n"
mapM_ (\(d,((v,n),_)) -> printf lineFmt d n v (v/fromIntegral n)) $ take 4 $ drop 2200 dat
(\(t,n) -> printf totalFmt n t (t/fromIntegral n)) $ fst summ
mapM_ ((\(l, d1,d2) -> printf maxFmt l d1 d2)
. (\(a,b)-> (a,(fst.(dat!!).(`div`24))b,(fst.(dat!!).(`div`24))(a+b)))) $ snd summ

View file

@ -0,0 +1 @@
*Main> :main ["./RC/readings.txt"]

View file

@ -0,0 +1,51 @@
record badrun(count,fromdate,todate) # record to track bad runs
procedure main()
return mungetask1("readings1-input.txt","readings1-output.txt")
end
procedure mungetask1(fin,fout)
fin := open(fin) | stop("Unable to open input file ",fin)
fout := open(fout,"w") | stop("Unable to open output file ",fout)
F_tot := F_acc := F_rej := 0 # data set totals
rejmax := badrun(-1) # longest reject runs
rejcur := badrun(0) # current reject runs
while line := read(fin) do {
line ? {
ldate := tab(many(&digits ++ '-')) # date (poorly checked)
fields := tot := rej := 0 # record counters & totals
while tab(many(' \t')) do { # whitespace before every pair
value := real(tab(many(&digits++'-.'))) | stop("Bad value in ",ldate)
tab(many(' \t'))
flag := integer(tab(many(&digits++'-'))) | stop("Bad flag in ",ldate)
fields +:= 1
if flag > 0 then { # good data, ends a bad run
if rejcur.count > rejmax.count then rejmax := rejcur
rejcur := badrun(0)
tot +:= value
}
else { # bad (flagged) data
if rejcur.count = 0 then rejcur.fromdate := ldate
rejcur.todate := ldate
rejcur.count +:= 1
rej +:= 1
}
}
}
F_tot +:= tot
F_acc +:= acc := fields - rej
F_rej +:= rej
write(fout,"Line: ",ldate," Reject: ", rej," Accept: ", acc," Line_tot: ",tot," Line_avg: ", if acc > 0 then tot / acc else 0)
}
write(fout,"\nTotal = ",F_tot,"\nReadings = ",F_acc,"\nRejects = ",F_rej,"\nAverage = ",F_tot / F_acc)
if rejmax.count > 0 then
write(fout,"Maximum run of bad data was ",rejmax.count," readings from ",rejmax.fromdate," to ",rejmax.todate)
else
write(fout,"No bad runs of data")
end

View file

@ -0,0 +1,14 @@
load 'files'
parseLine=: 10&({. ,&< (_99&".;._1)@:}.) NB. custom parser
summarize=: # , +/ , +/ % # NB. count,sum,mean
filter=: #~ 0&< NB. keep valid measurements
'Dates dat'=: |: parseLine;._2 CR -.~ fread jpath '~temp/readings.txt'
Vals=: (+: i.24){"1 dat
Flags=: (>: +: i.24){"1 dat
DailySummary=: Vals summarize@filter"1 Flags
RunLengths=: ([: #(;.1) 0 , }. *. }:) , 0 >: Flags
]MaxRun=: >./ RunLengths
589
]StartDates=: Dates {~ (>:@I.@e.&MaxRun (24 <.@%~ +/)@{. ]) RunLengths
1993-03-05

View file

@ -0,0 +1,11 @@
formatDailySumry=: dyad define
labels=. , ];.2 'Line: Accept: Line_tot: Line_avg: '
labels , x ,. 7j0 10j3 10j3 ": y
)
formatFileSumry=: dyad define
labels=. ];.2 'Total: Readings: Average: '
sumryvals=. (, %/) 1 0{ +/y
out=. labels ,. 12j3 12j0 12j3 ":&> sumryvals
'maxrun dates'=. x
out=. out,LF,'Maximum run(s) of ',(": maxrun),' consecutive false readings ends at line(s) starting with date(s): ',dates
)

View file

@ -0,0 +1,13 @@
(_4{.Dates) formatDailySumry _4{. DailySummary
Line: Accept: Line_tot: Line_avg:
2004-12-28 23 77.800 3.383
2004-12-29 23 56.300 2.448
2004-12-30 23 65.300 2.839
2004-12-31 23 47.300 2.057
(MaxRun;StartDates) formatFileSumry DailySummary
Total: 1358393.400
Readings: 129403
Average: 10.497
Maximum run(s) of 589 consecutive false readings ends at line(s) starting with date(s): 1993-03-05

View file

@ -0,0 +1,69 @@
var filename = 'readings.txt';
var show_lines = 5;
var file_stats = {
'num_readings': 0,
'total': 0,
'reject_run': 0,
'reject_run_max': 0,
'reject_run_date': ''
};
var fh = new ActiveXObject("Scripting.FileSystemObject").openTextFile(filename, 1); // 1 = for reading
while ( ! fh.atEndOfStream) {
var line = fh.ReadLine();
line_stats(line, (show_lines-- > 0));
}
fh.close();
WScript.echo(
"\nFile(s) = " + filename + "\n" +
"Total = " + dec3(file_stats.total) + "\n" +
"Readings = " + file_stats.num_readings + "\n" +
"Average = " + dec3(file_stats.total / file_stats.num_readings) + "\n\n" +
"Maximum run of " + file_stats.reject_run_max +
" consecutive false readings ends at " + file_stats.reject_run_date
);
function line_stats(line, print_line) {
var readings = 0;
var rejects = 0;
var total = 0;
var fields = line.split('\t');
var date = fields.shift();
while (fields.length > 0) {
var value = parseFloat(fields.shift());
var flag = parseInt(fields.shift(), 10);
readings++;
if (flag <= 0) {
rejects++;
file_stats.reject_run++;
}
else {
total += value;
if (file_stats.reject_run > file_stats.reject_run_max) {
file_stats.reject_run_max = file_stats.reject_run;
file_stats.reject_run_date = date;
}
file_stats.reject_run = 0;
}
}
file_stats.num_readings += readings - rejects;
file_stats.total += total;
if (print_line) {
WScript.echo(
"Line: " + date + "\t" +
"Reject: " + rejects + "\t" +
"Accept: " + (readings - rejects) + "\t" +
"Line_tot: " + dec3(total) + "\t" +
"Line_avg: " + ((readings == rejects) ? "0.0" : dec3(total / (readings - rejects)))
);
}
}
// round a number to 3 decimal places
function dec3(value) {
return Math.round(value * 1e3) / 1e3;
}

View file

@ -0,0 +1,49 @@
filename = "readings.txt"
io.input( filename )
file_sum, file_cnt_data, file_lines = 0, 0, 0
max_rejected, n_rejected = 0, 0
max_rejected_date, rejected_date = "", ""
while true do
data = io.read("*line")
if data == nil then break end
date = string.match( data, "%d+%-%d+%-%d+" )
if date == nil then break end
val = {}
for w in string.gmatch( data, "%s%-*%d+[%.%d]*" ) do
val[#val+1] = tonumber(w)
end
sum, cnt = 0, 0
for i = 1, #val, 2 do
if val[i+1] > 0 then
sum = sum + val[i]
cnt = cnt + 1
n_rejected = 0
else
if n_rejected == 0 then
rejected_date = date
end
n_rejected = n_rejected + 1
if n_rejected > max_rejected then
max_rejected = n_rejected
max_rejected_date = rejected_date
end
end
end
file_sum = file_sum + sum
file_cnt_data = file_cnt_data + cnt
file_lines = file_lines + 1
print( string.format( "%s:\tRejected: %d\tAccepted: %d\tLine_total: %f\tLine_average: %f", date, #val/2-cnt, cnt, sum, sum/cnt ) )
end
print( string.format( "\nFile:\t %s", filename ) )
print( string.format( "Total:\t %f", file_sum ) )
print( string.format( "Readings: %d", file_lines ) )
print( string.format( "Average: %f", file_sum/file_cnt_data ) )
print( string.format( "Maximum %d consecutive false readings starting at %s.", max_rejected, max_rejected_date ) )

View file

@ -0,0 +1,16 @@
FileName = "Readings.txt"; data = Import[FileName,"TSV"];
Scan[(a=Position[#[[3;;All;;2]],1];
Print["Line:",#[[1]] ,"\tReject:", 24 - Length[a], "\t Accept:", Length[a], "\tLine_tot:",
Total@Part[#, Flatten[2*a]] , "\tLine_avg:", Total@Part[#, Flatten[2*a]]/Length[a]])&, data]
GlobalSum = Nb = Running = MaxRunRecorded = 0; MaxRunTime = {};
Scan[ For[i = 3, i < 50, i = i + 2,
If[#[[i]] == 1,
Running=0; GlobalSum += #[[i-1]]; Nb++;,
Running ++; If[MaxRunRecorded < Running, MaxRunRecorded = Running;MaxRunTime={ #[[1]]}; ];
]] &, data ]
Print["\nFile(s) : ",FileName,"\nTotal : ",AccountingForm@GlobalSum,"\nReadings : ",Nb,
"\nAverage : ",GlobalSum/Nb,"\n\nMaximum run(s) of ",MaxRunRecorded,
" consecutive false readings ends at line starting with date(s):",MaxRunTime]

View file

@ -0,0 +1,67 @@
let input_line ic =
try Some(input_line ic)
with End_of_file -> None
let fold_input f ini ic =
let rec fold ac =
match input_line ic with
| Some line -> fold (f ac line)
| None -> ac
in
fold ini
let ic = open_in "readings.txt"
let scan line =
Scanf.sscanf line "%s\
\t%f\t%d\t%f\t%d\t%f\t%d\t%f\t%d\t%f\t%d\t%f\t%d\
\t%f\t%d\t%f\t%d\t%f\t%d\t%f\t%d\t%f\t%d\t%f\t%d\
\t%f\t%d\t%f\t%d\t%f\t%d\t%f\t%d\t%f\t%d\t%f\t%d\
\t%f\t%d\t%f\t%d\t%f\t%d\t%f\t%d\t%f\t%d\t%f\t%d"
(fun date
v1 f1 v2 f2 v3 f3 v4 f4 v5 f5 v6 f6
v7 f7 v8 f8 v9 f9 v10 f10 v11 f11 v12 f12
v13 f13 v14 f14 v15 f15 v16 f16 v17 f17 v18 f18
v19 f19 v20 f20 v21 f21 v22 f22 v23 f23 v24 f24 ->
(date),
[ (v1, f1 ); (v2, f2 ); (v3, f3 ); (v4, f4 ); (v5, f5 ); (v6, f6 );
(v7, f7 ); (v8, f8 ); (v9, f9 ); (v10, f10); (v11, f11); (v12, f12);
(v13, f13); (v14, f14); (v15, f15); (v16, f16); (v17, f17); (v18, f18);
(v19, f19); (v20, f20); (v21, f21); (v22, f22); (v23, f23); (v24, f24); ])
let tot_file, num_file, _, nodata_max, nodata_maxline =
fold_input
(fun (tot_file, num_file, nodata, nodata_max, nodata_maxline) line ->
let date, datas = scan line in
let _datas = List.filter (fun (_, flag) -> flag > 0) datas in
let ok = List.length _datas in
let tot = List.fold_left (fun ac (value, _) -> ac +. value) 0.0 _datas in
let nodata, nodata_max, nodata_maxline =
List.fold_left
(fun (nodata, nodata_max, nodata_maxline) (_, flag) ->
if flag <= 0
then (succ nodata, nodata_max, nodata_maxline)
else
if nodata_max = nodata && nodata > 0
then (0, nodata_max, date::nodata_maxline)
else if nodata_max < nodata && nodata > 0
then (0, nodata, [date])
else (0, nodata_max, nodata_maxline)
)
(nodata, nodata_max, nodata_maxline) datas in
Printf.printf "Line: %s" date;
Printf.printf " Reject: %2d Accept: %2d" (24 - ok) ok;
Printf.printf "\tLine_tot: %8.3f" tot;
Printf.printf "\tLine_avg: %8.3f\n" (tot /. float ok);
(tot_file +. tot, num_file + ok, nodata, nodata_max, nodata_maxline))
(0.0, 0, 0, 0, [])
ic ;;
close_in ic ;;
Printf.printf "Total = %f\n" tot_file;
Printf.printf "Readings = %d\n" num_file;
Printf.printf "Average = %f\n" (tot_file /. float num_file);
Printf.printf "Maximum run(s) of %d consecutive false readings \
ends at line starting with date(s): %s\n"
nodata_max (String.concat ", " nodata_maxline);

View file

@ -0,0 +1,54 @@
text1: procedure options (main); /* 13 May 2010 */
declare line character (2000) varying;
declare 1 pairs(24),
2 value fixed (10,4),
2 flag fixed;
declare date character (12) varying;
declare no_items fixed decimal (10);
declare (nv, sum, line_no, ndud_values, max_ndud_values) fixed;
declare (i, k) fixed binary;
declare in file input;
open file (in) title ('/TEXT1.DAT,TYPE(TEXT),RECSIZE(2000)' );
on endfile (in) go to finish_up;
line_no = 0;
loop:
do forever;
get file (in) edit (line) (L);
/* put skip list (line); */
line = translate(line, ' ', '09'x);
line_no = line_no + 1;
line = trim(line);
no_items = tally(line, ' ') - tally(line, ' ') + 1;
if no_items ^= 49 then
do; put skip list ('There are not 49 items on this line'); iterate loop; end;
k = index(line, ' '); /* Find the first blank in the line. */
date = substr(line, 1, k);
line = substr(line, k) || ' ';
on conversion go to loop;
get string (line) list (pairs);
sum, nv, ndud_values, max_ndud_values = 0;
do i = 1 to 24;
if flag(i) > 0 then
do; sum = sum + value(i); nv = nv + 1;
ndud_values = 0; /* reset the counter of dud values */
end;
else
do; /* we have a dud reading. */
ndud_values = ndud_values + 1;
if ndud_values > max_ndud_values then
max_ndud_values = ndud_values;
end;
end;
if nv = 0 then iterate;
put skip list ('Line ' || trim(line_no) || ' average=', divide(sum, nv, 10,4) );
if max_ndud_values > 0 then
put skip list ('Maximum run of dud readings =', max_ndud_values);
end;
finish_up:
end text1;

View file

@ -0,0 +1,33 @@
my @gaps;
my $previous = 'valid';
for $*IN.lines -> $line {
my ($date, @readings) = split /\s+/, $line;
my @valid;
my $hour = 0;
for @readings -> $reading, $flag {
if $flag > 0 {
@valid.push($reading);
if $previous eq 'invalid' {
@gaps[*-1]{'end'} = "$date $hour:00";
$previous = 'valid';
}
}
else
{
if $previous eq 'valid' {
@gaps.push( {start => "$date $hour:00"} );
}
@gaps[*-1]{'count'}++;
$previous = 'invalid';
}
$hour++;
}
say "$date: { ( +@valid ?? ( ( [+] @valid ) / +@valid ).fmt("%.3f") !! 0 ).fmt("%8s") }",
" mean from { (+@valid).fmt("%2s") } valid.";
};
my $longest = @gaps.sort({-$^a<count>})[0];
say "Longest period of invalid readings was {$longest<count>} hours,\n",
"from {$longest<start>} till {$longest<end>}."

View file

@ -0,0 +1,59 @@
use strict;
use warnings;
my $nodata = 0; # Current run of consecutive flags<0 in lines of file
my $nodata_max = -1; # Max consecutive flags<0 in lines of file
my $nodata_maxline = "!"; # ... and line number(s) where it occurs
my $infiles = join ", ", @ARGV;
my $tot_file = 0;
my $num_file = 0;
while (<>) {
chomp;
my $tot_line = 0; # sum of line data
my $num_line = 0; # number of line data items with flag>0
my $rejects = 0;
# extract field info, skipping initial date field
my ($date, @fields) = split;
while (@fields and my ($datum, $flag) = splice @fields, 0, 2) {
if ($flag+1 < 2) {
$nodata++;
$rejects++;
next;
}
# check run of data-absent fields
if($nodata_max == $nodata and $nodata > 0){
$nodata_maxline = "$nodata_maxline, $date";
}
if($nodata_max < $nodata and $nodata > 0){
$nodata_max = $nodata;
$nodata_maxline = $date;
}
# re-initialise run of nodata counter
$nodata = 0;
# gather values for averaging
$tot_line += $datum;
$num_line++;
}
# totals for the file so far
$tot_file += $tot_line;
$num_file += $num_line;
printf "Line: %11s Reject: %2i Accept: %2i Line_tot: %10.3f Line_avg: %10.3f\n",
$date, $rejects, $num_line, $tot_line, ($num_line>0)? $tot_line/$num_line: 0;
}
printf "\n";
printf "File(s) = %s\n", $infiles;
printf "Total = %10.3f\n", $tot_file;
printf "Readings = %6i\n", $num_file;
printf "Average = %10.3f\n", $tot_file / $num_file;
printf "\nMaximum run(s) of %i consecutive false readings ends at line starting with date(s): %s\n",
$nodata_max, $nodata_maxline;

View file

@ -0,0 +1,115 @@
use strict;
use warnings;
use constant RESULT_TEMPLATE => "%-19s = %12.3f / %-6u = %.3f\n";
my $parser = Parser->new;
# parse lines and print results
printf RESULT_TEMPLATE, $parser->parse(split)
while <>;
$parser->finish;
# print total and summary
printf "\n".RESULT_TEMPLATE."\n", $parser->result;
printf "the maximum of %u consecutive bad values was reached %u time(s)\n",
$parser->bad_max, scalar $parser->bad_ranges;
# print bad ranges
print for map { ' '.join(' - ', @$_)."\n" } $parser->bad_ranges;
BEGIN {
package main::Parser;
sub new {
my $obj = {
SUM => 0,
COUNT => 0,
CURRENT_DATE => undef,
BAD_DATE => undef,
BAD_RANGES => [],
BAD_MAX => 0,
BAD_COUNT => 0
};
return bless $obj;
}
sub _average {
my ($sum, $count) = @_;
return ($sum, $count, $count && $sum / $count);
}
sub _push_bad_range_if_necessary {
my ($parser) = @_;
my ($count, $max) = @$parser{qw(BAD_COUNT BAD_MAX)};
return if $count < $max;
if ($count > $max) {
$parser->{BAD_RANGES} = [];
$parser->{BAD_MAX} = $count;
}
push @{$parser->{BAD_RANGES}}, [ @$parser{qw(BAD_DATE CURRENT_DATE)} ];
}
sub _check {
my ($parser, $flag) = @_;
if ($flag <= 0) {
++$parser->{BAD_COUNT};
$parser->{BAD_DATE} = $parser->{CURRENT_DATE}
unless defined $parser->{BAD_DATE};
return 0;
}
else {
$parser->_push_bad_range_if_necessary;
$parser->{BAD_COUNT} = 0;
$parser->{BAD_DATE} = undef;
return 1;
}
}
sub bad_max {
my ($parser) = @_;
return $parser->{BAD_MAX}
}
sub bad_ranges {
my ($parser) = @_;
return @{$parser->{BAD_RANGES}}
}
sub parse {
my $parser = shift;
my $date = shift;
$parser->{CURRENT_DATE} = $date;
my $sum = 0;
my $count = 0;
while (my ($value, $flag) = splice @_, 0, 2) {
next unless $parser->_check($flag);
$sum += $value;
++$count;
}
$parser->{SUM} += $sum;
$parser->{COUNT} += $count;
return ("average($date)", _average($sum, $count));
}
sub result {
my ($parser) = @_;
return ('total-average', _average(@$parser{qw(SUM COUNT)}));
}
sub finish {
my ($parser) = @_;
$parser->_push_bad_range_if_necessary
}
}

View file

@ -0,0 +1,43 @@
#!/usr/bin/picolisp /usr/lib/picolisp/lib.l
(let (NoData 0 NoDataMax -1 NoDataMaxline "!" TotFile 0 NumFile 0)
(let InFiles
(glue ","
(mapcar
'((File)
(in File
(while (split (line) "^I")
(let (Len (length @) Date (car @) TotLine 0 NumLine 0)
(for (L (cdr @) L (cddr L))
(if (> 1 (format (cadr L)))
(inc 'NoData)
(when (gt0 NoData)
(when (= NoDataMax NoData)
(setq NoDataMaxline (pack NoDataMaxline ", " Date)) )
(when (> NoData NoDataMax)
(setq NoDataMax NoData NoDataMaxline Date) ) )
(zero NoData)
(inc 'TotLine (format (car L) 3))
(inc 'NumLine) ) )
(inc 'TotFile TotLine)
(inc 'NumFile NumLine)
(tab (-7 -12 -7 3 -9 3 -11 11 -11 11)
"Line:" Date
"Reject:" (- (/ (dec Len) 2) NumLine)
" Accept:" NumLine
" Line_tot:" (format TotLine 3)
" Line_avg:"
(and (gt0 NumLine) (format (*/ TotLine @) 3)) ) ) ) )
File )
(argv) ) )
(prinl)
(prinl "File(s) = " InFiles)
(prinl "Total = " (format TotFile 3))
(prinl "Readings = " NumFile)
(prinl "Average = " (format (*/ TotFile NumFile) 3))
(prinl)
(prinl
"Maximum run(s) of " NoDataMax
" consecutive false readings ends at line starting with date(s): " NoDataMaxline ) ) )
(bye)

View file

@ -0,0 +1,47 @@
#TASK="Text processing/1"
Define File$, InLine$, Part$, i, Out$, ErrEnds$, Errcnt, ErrMax
Define lsum.d, tsum.d, rejects, val.d, readings
File$=OpenFileRequester(#TASK,"readings.txt","",0)
If OpenConsole() And ReadFile(0,File$)
While Not Eof(0)
InLine$=ReadString(0)
For i=1 To 1+2*24
Part$=StringField(InLine$,i,#TAB$)
If i=1 ; Date
Out$=Part$: lsum=0: rejects=0
ElseIf i%2=0 ; Recorded value
val=ValD(Part$)
Else ; Status part
If Val(Part$)>0
Errcnt=0 : readings+1
lsum+val : tsum+val
Else
rejects+1: Errcnt+1
If Errcnt>ErrMax
ErrMax=Errcnt
ErrEnds$=Out$
EndIf
EndIf
EndIf
Next i
Out$+" Rejects: " + Str(rejects)
Out$+" Accepts: " + Str(24-rejects)
Out$+" Line_tot: "+ StrD(lsum,3)
If rejects<24
Out$+" Line_avg: "+StrD(lsum/(24-rejects),3)
Else
Out$+" Line_avg: N/A"
EndIf
PrintN("Line: "+Out$)
Wend
PrintN(#CRLF$+"File = "+GetFilePart(File$))
PrintN("Total = "+ StrD(tsum,3))
PrintN("Readings = "+ Str(readings))
PrintN("Average = "+ StrD(tsum/readings,3))
Print(#CRLF$+"Maximum of "+Str(ErrMax))
PrintN(" consecutive false readings, ends at "+ErrEnds$)
CloseFile(0)
;
Print("Press ENTER to exit"): Input()
EndIf

View file

@ -0,0 +1,56 @@
import fileinput
import sys
nodata = 0; # Current run of consecutive flags<0 in lines of file
nodata_max=-1; # Max consecutive flags<0 in lines of file
nodata_maxline=[]; # ... and line number(s) where it occurs
tot_file = 0 # Sum of file data
num_file = 0 # Number of file data items with flag>0
infiles = sys.argv[1:]
for line in fileinput.input():
tot_line=0; # sum of line data
num_line=0; # number of line data items with flag>0
# extract field info
field = line.split()
date = field[0]
data = [float(f) for f in field[1::2]]
flags = [int(f) for f in field[2::2]]
for datum, flag in zip(data, flags):
if flag<1:
nodata += 1
else:
# check run of data-absent fields
if nodata_max==nodata and nodata>0:
nodata_maxline.append(date)
if nodata_max<nodata and nodata>0:
nodata_max=nodata
nodata_maxline=[date]
# re-initialise run of nodata counter
nodata=0;
# gather values for averaging
tot_line += datum
num_line += 1
# totals for the file so far
tot_file += tot_line
num_file += num_line
print "Line: %11s Reject: %2i Accept: %2i Line_tot: %10.3f Line_avg: %10.3f" % (
date,
len(data) -num_line,
num_line, tot_line,
tot_line/num_line if (num_line>0) else 0)
print ""
print "File(s) = %s" % (", ".join(infiles),)
print "Total = %10.3f" % (tot_file,)
print "Readings = %6i" % (num_file,)
print "Average = %10.3f" % (tot_file / num_file,)
print "\nMaximum run(s) of %i consecutive false readings ends at line starting with date(s): %s" % (
nodata_max, ", ".join(nodata_maxline))

View file

@ -0,0 +1,9 @@
#Read in data from file
dfr <- read.delim("readings.txt")
#Calculate daily means
flags <- as.matrix(dfr[,seq(3,49,2)])>0
vals <- as.matrix(dfr[,seq(2,49,2)])
daily.means <- rowSums(ifelse(flags, vals, 0))/rowSums(flags)
#Calculate time between good measurements
times <- strptime(dfr[1,1], "%Y-%m-%d", tz="GMT") + 3600*seq(1,24*nrow(dfr),1)
hours.between.good.measurements <- diff(times[t(flags)])/3600

View file

@ -0,0 +1,72 @@
/*REXX program to process instrument data from a data file. */
numeric digits 20 /*allow for bigger numbers. */
ifid='READINGS.TXT' /*the input file. */
ofid='READINGS.OUT' /*the outut file. */
grandSum=0 /*grand sum of whole file. */
grandflg=0 /*grand num of flagged data. */
grandOKs=0
longFlag=0 /*longest period of flagged data.*/
contFlag=0 /*longest continous flagged data.*/
w=16 /*width of fields when displayed.*/
do recs=1 while lines(ifid)\==0 /*read until finished. */
rec=linein(ifid) /*read the next record (line). */
parse var rec datestamp Idata /*pick off the dateStamp & data. */
sum=0
flg=0
OKs=0
do j=1 until Idata='' /*process the instrument data. */
parse var Idata data.j flag.j Idata
if flag.j>0 then do /*if good data, ... */
OKs=OKs+1
sum=sum+data.j
if contFlag>longFlag then do
longdate=datestamp
longFlag=contFlag
end
contFlag=0
end
else do /*flagged data ... */
flg=flg+1
contFlag=contFlag+1
end
end /*j*/
if OKs\==0 then avg=format(sum/OKs,,3)
else avg='[n/a]'
grandOKs=grandOKs+OKs
_=right(comma(avg),w)
grandSum=grandSum+sum
grandFlg=grandFlg+flg
if flg==0 then call sy datestamp ' average='_
else call sy datestamp ' average='_ ' flagged='right(flg,2)
end /*recs*/
recs=recs-1 /*adjust for reading end-of-file.*/
if grandOKs\==0 then Gavg=format(grandsum/grandOKs,,3)
else Gavg='[n/a]'
call sy
call sy copies('',60)
call sy ' records read:' right(comma(recs),w)
call sy ' grand sum:' right(comma(grandSum),w+4)
call sy ' grand average:' right(comma(Gavg),w+4)
call sy ' grand OK data:' right(comma(grandOKs),w)
call sy ' grand flagged:' right(comma(grandFlg),w)
if longFlag\==0 then
call sy ' longest flagged:' right(comma(longFlag),w) " ending at " longdate
call sy copies('',60)
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────SY subroutine───────────────────────*/
sy: procedure; parse arg stuff; say stuff
if 1==0 then call lineout ofid,stuff
return
/*──────────────────────────────────COMMA subroutine────────────────────*/
comma: procedure; parse arg _,c,p,t;arg ,cu;c=word(c ",",1)
if cu=='BLANK' then c=' ';o=word(p 3,1);p=abs(o);t=word(t 999999999,1)
if \datatype(p,'W')|\datatype(t,'W')|p==0|arg()>4 then return _;n=_'.9'
#=123456789;k=0;if o<0 then do;b=verify(_,' ');if b==0 then return _
e=length(_)-verify(reverse(_),' ')+1;end;else do;b=verify(n,#,"M")
e=verify(n,#'0',,verify(n,#"0.",'M'))-p-1;end
do j=e to b by -p while k<t;_=insert(c,_,j);k=k+1;end;return _

View file

@ -0,0 +1,54 @@
#lang racket
;; Use SRFI 48 to make %n.nf formats convenient.
(require (prefix-in srfi/48: srfi/48)) ; SRFI 48: Intermediate Format Strings
;; Parameter allows us to used exact decimal strings
(read-decimal-as-inexact #f)
;; files to read is a sequence, so it could be either a list or vector of files
(define (text-processing/1 files-to-read)
(define (print-line-info d r a t)
(srfi/48:format #t "Line: ~11F Reject: ~2F Accept: ~2F Line_tot: ~10,3F Line_avg: ~10,3F~%"
d r a t (if (zero? a) +nan.0 (/ t a))))
;; returns something that can be used as args to an apply
(define (handle-and-tag-max consecutive-false tag max-consecutive-false max-false-tags)
(let ((consecutive-false+1 (add1 consecutive-false)))
(list consecutive-false+1
(max max-consecutive-false consecutive-false+1)
(cond ((= consecutive-false+1 max-consecutive-false) (cons tag max-false-tags))
((= consecutive-false max-consecutive-false) (list tag))
(else max-false-tags)))))
(define (sub-t-p/1 N sum consecutive-false max-consecutive-false max-false-tags)
(for/fold ((N N) (sum sum) (consecutive-false consecutive-false) (max-consecutive-false max-consecutive-false) (max-false-tags max-false-tags))
((l (in-lines)))
(match l
[(app string-split `(,tag ,(app string->number vs.ss) ...))
(let get-line-pairs
((vs.ss vs.ss) (line-N 0) (reject 0) (line-sum 0) (consecutive-false consecutive-false)
(max-consecutive-false max-consecutive-false) (max-false-tags max-false-tags))
(match vs.ss
['()
(print-line-info tag reject line-N line-sum)
(values (+ N line-N) (+ sum line-sum) consecutive-false max-consecutive-false max-false-tags)]
[(list-rest v (? positive?) tl)
(get-line-pairs tl (add1 line-N) reject (+ line-sum v) 0 max-consecutive-false max-false-tags)]
[(list-rest _ _ tl)
(apply get-line-pairs tl line-N (add1 reject) line-sum
(handle-and-tag-max consecutive-false tag max-consecutive-false max-false-tags))]))]
(x (fprintf (current-error-port) "mismatch ~s~%" x)
(values N sum consecutive-false max-consecutive-false max-false-tags)))))
(for/fold ((N 0) (sum 0) (consecutive-false 0) (max-consecutive-false 0) (max-false-tags null))
((f files-to-read))
(with-input-from-file f
(lambda () (sub-t-p/1 N sum consecutive-false max-consecutive-false max-false-tags)))))
(let ((files (vector->list (current-command-line-arguments))))
(let-values (([N sum consecutive-false max-consecutive-false max-false-tags] (text-processing/1 files)))
(srfi/48:format #t "~%File(s) = ~a~%Total = ~10,3F~%Readings = ~6F~%" (string-join files) sum N)
(unless (zero? N) (srfi/48:format #t "Average = ~10,3F~%" (/ sum N)))
(srfi/48:format #t "~%Maximum run(s) of ~a consecutive false readings ends at line starting with date(s): ~a~%"
max-consecutive-false (string-join max-false-tags))))

View file

@ -0,0 +1,43 @@
filename = "readings.txt"
total = { "num_readings" => 0, "num_good_readings" => 0, "sum_readings" => 0.0 }
invalid_count = 0
max_invalid_count = 0
invalid_run_end = ""
File.new(filename).each do |line|
num_readings = 0
num_good_readings = 0
sum_readings = 0.0
fields = line.split
fields[1..-1].each_slice(2) do |reading, flag|
num_readings += 1
if Integer(flag) > 0
num_good_readings += 1
sum_readings += Float(reading)
invalid_count = 0
else
invalid_count += 1
if invalid_count > max_invalid_count
max_invalid_count = invalid_count
invalid_run_end = fields[0]
end
end
end
printf "Line: %11s Reject: %2d Accept: %2d Line_tot: %10.3f Line_avg: %10.3f\n",
fields[0], num_readings - num_good_readings, num_good_readings, sum_readings,
num_good_readings > 0 ? sum_readings/num_good_readings : 0.0
total["num_readings"] += num_readings
total["num_good_readings"] += num_good_readings
total["sum_readings"] += sum_readings
end
puts ""
puts "File(s) = #{filename}"
printf "Total = %.3f\n", total['sum_readings']
puts "Readings = #{total['num_good_readings']}"
printf "Average = %.3f\n", total['sum_readings']/total['num_good_readings']
puts ""
puts "Maximum run(s) of #{max_invalid_count} consecutive false readings ends at #{invalid_run_end}"

View file

@ -0,0 +1,58 @@
object DataMunging {
import scala.io.Source
def spans[A](list: List[A]) = list.tail.foldLeft(List((list.head, 1))) {
case ((a, n) :: tail, b) if a == b => (a, n + 1) :: tail
case (l, b) => (b, 1) :: l
}
type Flag = ((Boolean, Int), String)
type Flags = List[Flag]
type LineIterator = Iterator[Option[(Double, Int, Flags)]]
val pattern = """^(\d+-\d+-\d+)""" + """\s+(\d+\.\d+)\s+(-?\d+)""" * 24 + "$" r;
def linesIterator(file: java.io.File) = Source.fromFile(file).getLines().map(
pattern findFirstMatchIn _ map (
_.subgroups match {
case List(date, rawData @ _*) =>
val dataset = (rawData map (_ toDouble) iterator) grouped 2 toList;
val valid = dataset filter (_.last > 0) map (_.head)
val validSize = valid length;
val validSum = valid sum;
val flags = spans(dataset map (_.last > 0)) map ((_, date))
println("Line: %11s Reject: %2d Accept: %2d Line_tot: %10.3f Line_avg: %10.3f" format
(date, 24 - validSize, validSize, validSum, validSum / validSize))
(validSum, validSize, flags)
}
)
)
def totalizeLines(fileIterator: LineIterator) =
fileIterator.foldLeft(0.0, 0, List[Flag]()) {
case ((totalSum, totalSize, ((flag, size), date) :: tail), Some((validSum, validSize, flags))) =>
val ((firstFlag, firstSize), _) = flags.last
if (firstFlag == flag) {
(totalSum + validSum, totalSize + validSize, flags.init ::: ((flag, size + firstSize), date) :: tail)
} else {
(totalSum + validSum, totalSize + validSize, flags ::: ((flag, size), date) :: tail)
}
case ((_, _, Nil), Some(partials)) => partials
case (totals, None) => totals
}
def main(args: Array[String]) {
val files = args map (new java.io.File(_)) filter (file => file.isFile && file.canRead)
val lines = files.iterator flatMap linesIterator
val (totalSum, totalSize, flags) = totalizeLines(lines)
val ((_, invalidCount), startDate) = flags.filter(!_._1._1).max
val report = """|
|File(s) = %s
|Total = %10.3f
|Readings = %6d
|Average = %10.3f
|
|Maximum run(s) of %d consecutive false readings began at %s""".stripMargin
println(report format (files mkString " ", totalSum, totalSize, totalSum / totalSize, invalidCount, startDate))
}
}

View file

@ -0,0 +1,42 @@
object AltDataMunging {
def main(args: Array[String]) {
var totalSum = 0.0
var totalSize = 0
var maxInvalidDate = ""
var maxInvalidCount = 0
var invalidDate = ""
var invalidCount = 0
val files = args map (new java.io.File(_)) filter (file => file.isFile && file.canRead)
files.iterator flatMap (file => Source fromFile file getLines ()) map (_.trim split "\\s+") foreach {
case Array(date, rawData @ _*) =>
val dataset = (rawData map (_ toDouble) iterator) grouped 2 toList;
val valid = dataset filter (_.last > 0) map (_.head)
val flags = spans(dataset map (_.last > 0)) map ((_, date))
println("Line: %11s Reject: %2d Accept: %2d Line_tot: %10.3f Line_avg: %10.3f" format
(date, 24 - valid.size, valid.size, valid.sum, valid.sum / valid.size))
totalSum += valid.sum
totalSize += valid.size
dataset foreach {
case _ :: flag :: Nil if flag > 0 =>
if (invalidCount > maxInvalidCount) {
maxInvalidDate = invalidDate
maxInvalidCount = invalidCount
}
invalidCount = 0
case _ =>
if (invalidCount == 0) invalidDate = date
invalidCount += 1
}
}
val report = """|
|File(s) = %s
|Total = %10.3f
|Readings = %6d
|Average = %10.3f
|
|Maximum run(s) of %d consecutive false readings began at %s""".stripMargin
println(report format (files mkString " ", totalSum, totalSize, totalSum / totalSize, maxInvalidCount, maxInvalidDate))
}
}

View file

@ -0,0 +1,41 @@
set max_invalid_run 0
set max_invalid_run_end ""
set tot_file 0
set num_file 0
set linefmt "Line: %11s Reject: %2d Accept: %2d Line_tot: %10.3f Line_avg: %10.3f"
set filename readings.txt
set fh [open $filename]
while {[gets $fh line] != -1} {
set tot_line [set count [set num_line 0]]
set fields [regexp -all -inline {\S+} $line]
set date [lindex $fields 0]
foreach {val flag} [lrange $fields 1 end] {
incr count
if {$flag > 0} {
incr num_line
incr num_file
set tot_line [expr {$tot_line + $val}]
set invalid_run_count 0
} else {
incr invalid_run_count
if {$invalid_run_count > $max_invalid_run} {
set max_invalid_run $invalid_run_count
set max_invalid_run_end $date
}
}
}
set tot_file [expr {$tot_file + $tot_line}]
puts [format $linefmt $date [expr {$count - $num_line}] $num_line $tot_line \
[expr {$num_line > 0 ? $tot_line / $num_line : 0}]]
}
close $fh
puts ""
puts "File(s) = $filename"
puts "Total = [format %.3f $tot_file]"
puts "Readings = $num_file"
puts "Average = [format %.3f [expr {$tot_file / $num_file}]]"
puts ""
puts "Maximum run(s) of $max_invalid_run consecutive false readings ends at $max_invalid_run_end"

View file

@ -0,0 +1,21 @@
#import std
#import nat
#import flo
parsed_data = ^|A(~&,* ^|/%ep@iNC ~&h==`1)*htK27K28pPCS (sep 9%cOi&)*FyS readings_dot_txt
daily_stats =
* ^|A(~&,@rFlS ^/length ^/plus:-0. ||0.! ~&i&& mean); mat` + <.
~&n,
'accept: '--+ @ml printf/'%7.0f'+ float,
'total: '--+ @mrl printf/'%10.1f',
'average: '--+ @mrr printf/'%7.3f'>
long_run =
-+
~&i&& ^|TNC('maximum of '--@h+ %nP,' consecutive false readings ending on line '--),
@nmrSPDSL -&~&,leql$^; ^/length ~&zn&-@hrZPF+ rlc both ~&rZ+-
main = ^T(daily_stats^lrNCT/~& @mSL 'summary ':,long_run) parsed_data

View file

@ -0,0 +1,68 @@
#50 = Buf_Num // Current edit buffer (source data)
File_Open("output.txt")
#51 = Buf_Num // Edit buffer for output file
Buf_Switch(#50)
#10 = 0 // total sum of file data
#11 = 0 // number of valid data items in file
#12 = 0 // Current run of consecutive flags<0 in lines of file
#13 = -1 // Max consecutive flags<0 in lines of file
Reg_Empty(15) // ... and date tag(s) at line(s) where it occurs
While(!At_EOF) {
#20 = 0 // sum of line data
#21 = 0 // number of line data items with flag>0
#22 = 0 // number of line data items with flag<0
Reg_Copy_Block(14, Cur_Pos, Cur_Pos+10) // date field
// extract field info, skipping initial date field
Repeat(ALL) {
Search("|{|T,|N}", ADVANCE+ERRBREAK) // next Tab or Newline
if (Match_Item==2) { Break } // end of line
#30 = Num_Eval(ADVANCE) * 1000 // #30 = value
Char // fixed point, 3 decimal digits
#30 += Num_Eval(ADVANCE+SUPPRESS)
#31 = Num_Eval(ADVANCE) // #31 = flag
if (#31 < 1) { // not valid field?
#12++
#22++
} else { // valid field
// check run of data-absent fields
if(#13 == #12 && #12 > 0) {
Reg_Set(15, ", ", APPEND)
Reg_Set(15, @14, APPEND)
}
if(#13 < #12 && #12 > 0) {
#13 = #12
Reg_Set(15, @14)
}
// re-initialise run of nodata counter
#12 = 0
// gather values for averaging
#20 += #30
#21++
}
}
// totals for the file so far
#10 += #20
#11 += #21
Buf_Switch(#51) // buffer for output data
IT("Line: ") Reg_Ins(14)
IT(" Reject:") Num_Ins(#22, COUNT, 3)
IT(" Accept:") Num_Ins(#21, COUNT, 3)
IT(" Line tot:") Num_Ins(#20, COUNT, 8) Char(-3) IC('.') EOL
IT(" Line avg:") Num_Ins((#20+#21/2)/#21, COUNT, 7) Char(-3) IC('.') EOL IN
Buf_Switch(#50) // buffer for input data
}
Buf_Switch(#51) // buffer for output data
IN
IT("Total: ") Num_Ins(#10, FORCE+NOCR) Char(-3) IC('.') EOL IN
IT("Readings: ") Num_Ins(#11, FORCE)
IT("Average: ") Num_Ins((#10+#11/2)/#11, FORCE+NOCR) Char(-3) IC('.') EOL IN
IN
IT("Maximum run(s) of ") Num_Ins(#13, LEFT+NOCR)
IT(" consecutive false readings ends at line starting with date(s): ") Reg_Ins(15)
IN