I'm trying to study Erlang resolving Hackerrank problems. There is a problem called List Replication. I finished with a solution like this:
-module(solution).
-export([main/0]).
process_input(Repeats)->
Line = io:get_line(""),
case string:len(Line) of
1 -> ok;
_ -> output(Line, Repeats), process_input(Repeats)
end.
output(_, 0)-> ok;
output(Line, Repeats)->
io:format(Line),
output(Line, Repeats - 1).
main()->
{ok, [Repeats]} = io:fread("", "~d"),
process_input(Repeats).
But this solution has a problem: I expect the last line is empty (in fact the last line is a number without \n
). Any thoughts?
I think it's easier to handle eof
from io:get_line/1
in case of a missing final newline, as well as handling a blank line to indicate end of input:
-module(solution).
-export([start/0]).
process_input(Repeat, Acc)->
case io:get_line("") of
Done when Done == eof; Done == "\n" ->
output(lists:reverse(Acc));
Line ->
Val = string:strip(Line, right, $\n),
Str = lists:duplicate(Repeat, Val),
process_input(Repeat, [Str|Acc])
end.
output(Lines)->
Out = [string:join(L, "\n")++"\n" || L <- Lines],
io:format("~s", [Out]).
start()->
{ok, [Repeat]} = io:fread("", "~d"),
process_input(Repeat, []).
The process_input/2
function now takes an accumulator, which is initially an empty list. It calls itself recursively until it detects end of input, after which it prints the output. It calls io:get_line/1
and checks to see if it returns either eof
or just a newline, and for that case it reverses its accumulator and prints its output. For any other input, it strips the final newline, repeats the input via lists:duplicate/2
, stores the result in a new accumulator, and passes that to a recursive call.
The output/1
function takes the accumulator from process_input/2
, joins the repeated values with newlines, then prints the results. Note that this version of the solution
module restricts the formatting of the result to the output/1
function, in case you wanted to use the raw result of process_input/2
for some other purpose.
And finally, I renamed your main/0
to start/0
because running a function via the erl -s
command line option assumes a function named start
if none is given.
We can use printf
in a Unix shell to create an input file without a final newline:
$ printf '3\n1\n2\n3\n4\n' > in
and then run our compiled solution
module like this, getting the tripled output we expect in this case:
$ cat in | erl -noshell -s solution -s init stop
1
1
1
2
2
2
3
3
3
4
4
4
Adding a final newline to the in
file gives the same result (try it). We can also create input with more than a single character per line:
$ printf '2\nhey\nhey\nwhat\ncan\nI\ndo' > in2
$ cat in2 | erl -noshell -s solution -s init stop
hey
hey
hey
hey
what
what
can
can
I
I
do
do
and for this in2
file, we get the doubled output we expect as well.