Richard O'Keefe <>
Tue Nov 13 00:39:48 CET 2012

```On 9/11/2012, at 8:31 PM, Lucky Khoza wrote:

> Hi,
>
> May you kindly help with the exercise below using Erlang [I am new Erlang Development]:

I'm familiar with the Hollinberry problem.
I contributed an AWK solution to it.

It's actually a pretty trivial problem that repays careful
files and date calculations.

If you read a CSV file as a single string, then you can
use this code adapted from Victor Moroz:

parse(Data) -> parse(Data, [], [], []).

parse([\$\r|Data], Field, Fields, Lines) -> parse_r(Data, Field, Fields, Lines);
parse([\$\n|Data], Field, Fields, Lines) -> parse_l(Data, Field, Fields, Lines);
parse([\$,|Data], Field, Fields, Lines)  -> parse(Data, [], f(Field, Fields), Lines);
parse([\$"|Data], [], Fields, Lines)     -> parse_q(Data, [], Fields, Lines);
parse([C|Data], Field, Fields, Lines)   -> parse(Data, [C|Field], Fields, Lines);
parse([], [], [], Lines)                -> lists:reverse(Lines);
parse([], Field, Fields, Lines)         -> parse_l([], Field, Fields, Lines).

f(Field, Fields) -> [lists:reverse(Field) | Fields].

l(Line,  Lines)  -> [lists:reverse(Line)  | Lines ].

parse_r([\$\n|Data], Field, Fields, Lines) -> parse_l(Data, Field, Fields, Lines);
parse_r(     Data,  Field, Fields, Lines) -> parse_l(Data, Field, Fields, Lines).

parse_l(Data, Field, Fields, Lines) -> parse(Data, [], [], l(f(Field, Fields), Lines)).

parse_q([\$"|Data], Field, Fields, Lines) -> parse_qq(Data, Field, Fields, Lines);
parse_q([C|Data], Field, Fields, Lines)  -> parse_q(Data, [C|Field], Fields, Lines).

parse_qq([\$"|Data], Field, Fields, Lines) -> parse_q(Data, [\$"|Field], Fields, Lines);
parse_qq(    Data , Field, Fields, Lines) -> parse(Data, Field, Fields, Lines).

This is just a finite state automaton, maintaining four things:
Data   = the characters yet to be scanned
Field  = the current field *reversed*
Fields = the fields before the current field on the current line;
each field is in its right order, but Fields is reversed
Lines  = the lines before the current line;
each line is in its right order, but Lines is reversed.
As soon as we finish building each Field (line of fields, file of lines)
we reverse it, to maintain this invariant.

(This code has been tested on the Hollingberrys' "produce.csv".)

For date calculations, use the stdlib 'calendar' module.

```