67 lines
2.9 KiB
Erlang
67 lines
2.9 KiB
Erlang
-module( text_processing ).
|
|
|
|
-export( [file_contents/1, main/1] ).
|
|
|
|
-record( acc, {failed={"", 0, 0}, files=[], ok=0, total=0} ).
|
|
|
|
file_contents( Name ) ->
|
|
{ok, Binary} = file:read_file( Name ),
|
|
[line_contents(X) || X <- binary:split(Binary, <<"\r\n">>, [global]), X =/= <<>>].
|
|
|
|
main( Files ) ->
|
|
Acc = lists:foldl( fun file/2, #acc{}, Files ),
|
|
{Failed_date, Failed, _Continuation} = Acc#acc.failed,
|
|
io:fwrite( "~nFile(s)=~p~nTotal=~.2f~nReadings=~p~nAverage=~.2f~n~nMaximum run(s) of ~p consecutive false readings ends at line starting with date(s): ~p~n",
|
|
[lists:reverse(Acc#acc.files), Acc#acc.total, Acc#acc.ok, Acc#acc.total / Acc#acc.ok, Failed, Failed_date] ).
|
|
|
|
|
|
|
|
file( Name, #acc{files=Files}=Acc ) ->
|
|
try
|
|
Line_contents = file_contents( Name ),
|
|
lists:foldl( fun file_content_line/2, Acc#acc{files=[Name | Files]}, Line_contents )
|
|
|
|
catch
|
|
_:Error ->
|
|
io:fwrite( "Error: Failed to read ~s: ~p~n", [Name, Error] ),
|
|
Acc
|
|
end.
|
|
|
|
file_content_line( {Date, Value_flags}, #acc{failed=Failed, ok=Ok, total=Total}=Acc ) ->
|
|
New_failed = file_content_line_failed( Value_flags, Date, Failed ),
|
|
{Sum, Oks, Average} = file_content_line_oks_0( [X || {X, ok} <- Value_flags] ),
|
|
io:fwrite( "Line=~p\tRejected=~p\tAccepted=~p\tLine total=~.2f\tLine average=~.2f~n", [Date, erlang:length(Value_flags) - Oks, Oks, Sum, Average] ),
|
|
Acc#acc{failed=New_failed, ok=Ok + Oks, total=Total + Sum}.
|
|
|
|
file_content_line_failed( [], Date, {_Failed_date, Failed, Acc} ) when Acc > Failed ->
|
|
{Date, Acc, Acc};
|
|
file_content_line_failed( [], _Date, Failed ) ->
|
|
Failed;
|
|
file_content_line_failed( [{_V, error} | T], Date, {Failed_date, Failed, Acc} ) ->
|
|
file_content_line_failed( T, Date, {Failed_date, Failed, Acc + 1} );
|
|
file_content_line_failed( [_H | T], Date, {_Failed_date, Failed, Acc} ) when Acc > Failed ->
|
|
file_content_line_failed( T, Date, {Date, Acc, 0} );
|
|
file_content_line_failed( [_H | T], Date, {Failed_date, Failed, _Acc} ) ->
|
|
file_content_line_failed( T, Date, {Failed_date, Failed, 0} ).
|
|
|
|
file_content_line_flag( N ) when N > 0 -> ok;
|
|
file_content_line_flag( _N ) -> error.
|
|
|
|
file_content_line_oks_0( [] ) -> {0.0, 0, 0.0};
|
|
file_content_line_oks_0( Ok_value_flags ) ->
|
|
Sum = lists:sum( Ok_value_flags ),
|
|
Oks = erlang:length( Ok_value_flags ),
|
|
{Sum, Oks, Sum / Oks}.
|
|
|
|
file_content_line_value_flag( Binary, {[], Acc} ) ->
|
|
Flag = file_content_line_flag( erlang:list_to_integer(binary:bin_to_list(Binary)) ),
|
|
{[Flag], Acc};
|
|
file_content_line_value_flag( Binary, {[Flag], Acc} ) ->
|
|
Value = erlang:list_to_float( binary:bin_to_list(Binary) ),
|
|
{[], [{Value, Flag} | Acc]}.
|
|
|
|
line_contents( Line ) ->
|
|
[Date_binary | Rest] = binary:split( Line, <<"\t">>, [global] ),
|
|
{_Previous, Value_flags} = lists:foldr( fun file_content_line_value_flag/2, {[], []}, Rest ), % Preserve order
|
|
{binary:bin_to_list( Date_binary ), Value_flags}.
|