使用 Erlang 列出复制挑战
List replication challenge with Erlang
我正在尝试研究解决 Hackerrank 问题的 Erlang。有一个问题叫做List Replication。我完成了这样的解决方案:
-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).
但是这个解决方案有一个问题:我希望最后一行是空的(实际上最后一行是一个没有 \n
的数字)。有什么想法吗?
您将不得不关闭流的回显,io:setopts/1
-module(solution).
-export([main/0]).
process_input(Repeats)->
Line = string:strip(io:get_line(""), right, $\n),
case string:len(Line) of
0 ->
ok;
_ ->
output(Line, Repeats),
process_input(Repeats)
end.
output(_, 0)->
ok;
output(Line, Repeats)->
io:format("~s\n", [Line]),
output(Line, Repeats - 1).
main()->
{ok, [Repeats]} = io:fread("", "~d"),
io:setopts([{echo, false}]),
process_input(Repeats).
我刚刚更新了解决挑战的代码,所以我的想法是将输入保存在累加器(本例中为列表)中,最后处理列表,如果你想避免输出任何时候屏幕上正在写的内容,您都可以禁用回显,就像我在另一个答案中显示的示例
-module(solution).
-export([main/0]).
process_input(Data)->
Number = io:get_line(""),
case string:len(Number) of
1 ->
Data;
_ ->
process_input(Data ++ [Number])
end.
process_output([], _)->
ok;
process_output([H|Data], Repeats)->
print(H, Repeats),
process_output(Data, Repeats).
print(_, 0) ->
ok;
print(Element, Times) ->
io:format(Element),
print(Element, Times - 1).
main()->
{ok, [Repeats]} = io:fread("", "~d"),
Data = process_input([]),
process_output(Data, Repeats).
测试:
rorra:~/erlang > erl
Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V6.4 (abort with ^G)
1> c(solution).
{ok,solution}
2> solution:main().
3
1
2
3
4
1
1
1
2
2
2
3
3
3
4
4
4
ok
3>
我认为在缺少最后一个换行符的情况下从 io:get_line/1
处理 eof
以及处理表示输入结束的空行更容易:
-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, []).
process_input/2
函数现在接受一个累加器,它最初是一个空列表。它递归地调用自己,直到检测到输入结束,然后打印输出。它调用 io:get_line/1
并检查它 returns 是 eof
还是只是一个换行符,对于这种情况,它会反转其累加器并打印其输出。对于任何其他输入,它会去除最后的换行符,通过 lists:duplicate/2
重复输入,将结果存储在新的累加器中,并将其传递给递归调用。
output/1
函数从 process_input/2
中获取累加器,用换行符连接重复的值,然后打印结果。请注意,此版本的 solution
模块将结果的格式限制为 output/1
函数,以防您想将 process_input/2
的原始结果用于其他目的。
最后,我将你的 main/0
重命名为 start/0
因为 运行 通过 erl -s
命令行选项设置一个函数假定一个名为 start
的函数如果给出 none。
我们可以在 Unix shell 中使用 printf
来创建没有最终换行符的输入文件:
$ printf '3\n1\n2\n3\n4\n' > in
然后 运行 我们编译的 solution
模块是这样的,在这种情况下得到我们期望的三倍输出:
$ cat in | erl -noshell -s solution -s init stop
1
1
1
2
2
2
3
3
3
4
4
4
在 in
文件中添加最后一个换行符会得到相同的结果(试试看)。我们还可以创建每行包含多个字符的输入:
$ 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
对于这个 in2
文件,我们也得到了预期的双倍输出。
我自己的回答:
-module(solution).
-export([main/0]).
process_input(Repeats)->
Line = io:get_line(""),
case lists:reverse(Line) of
"\n" ++ _ -> output(Line, Repeats), process_input(Repeats);
_ -> output(Line ++ "~n" , Repeats)
end.
output(_, 0)-> ok;
output(Line, Repeats)->
io:format(Line),
output(Line, Repeats - 1).
main()->
{ok, [Repeats]} = io:fread("", "~d"),
process_input(Repeats).
这是我想出的(在上述答案的帮助下)。我正在添加我的解决方案,因为它还处理问题中所述的约束:


-module(solution).
-export([main/0]).
main() -> get_input([]).
print_list(_,[_|[]]) -> ok;
print_list(NumTimes,[_|List]) ->
Number = hd(List),
print_list_number(NumTimes,Number),
print_list(NumTimes,List).
print_list_number(NumTimes,Number)
when
(NumTimes > 0)
and
(Number >= 1)
and
(Number =< 100)
->
io:fwrite("~B~n",[Number]),
print_list_number(NumTimes - 1,Number);
print_list_number(_,_) -> ok.
get_input(Acc) ->
case io:get_line("") of
Done when
Done == eof;
Done == "\n"
->
NumTimes = hd(Acc),
%% Make sure we only run this when the List length isn't greater than 10
if
(length(Acc) - 1 =< 10)
and
(NumTimes =< 100)
->
print_list(NumTimes,Acc);
true -> ok
end;
Line ->
{NumInt,_} = string:to_integer(Line),
List = Acc ++ [NumInt],
get_input(List)
end.
我是 Erlang 的新手,如果这很混乱/效率低下,请原谅我!
我正在尝试研究解决 Hackerrank 问题的 Erlang。有一个问题叫做List Replication。我完成了这样的解决方案:
-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).
但是这个解决方案有一个问题:我希望最后一行是空的(实际上最后一行是一个没有 \n
的数字)。有什么想法吗?
您将不得不关闭流的回显,io:setopts/1
-module(solution).
-export([main/0]).
process_input(Repeats)->
Line = string:strip(io:get_line(""), right, $\n),
case string:len(Line) of
0 ->
ok;
_ ->
output(Line, Repeats),
process_input(Repeats)
end.
output(_, 0)->
ok;
output(Line, Repeats)->
io:format("~s\n", [Line]),
output(Line, Repeats - 1).
main()->
{ok, [Repeats]} = io:fread("", "~d"),
io:setopts([{echo, false}]),
process_input(Repeats).
我刚刚更新了解决挑战的代码,所以我的想法是将输入保存在累加器(本例中为列表)中,最后处理列表,如果你想避免输出任何时候屏幕上正在写的内容,您都可以禁用回显,就像我在另一个答案中显示的示例
-module(solution).
-export([main/0]).
process_input(Data)->
Number = io:get_line(""),
case string:len(Number) of
1 ->
Data;
_ ->
process_input(Data ++ [Number])
end.
process_output([], _)->
ok;
process_output([H|Data], Repeats)->
print(H, Repeats),
process_output(Data, Repeats).
print(_, 0) ->
ok;
print(Element, Times) ->
io:format(Element),
print(Element, Times - 1).
main()->
{ok, [Repeats]} = io:fread("", "~d"),
Data = process_input([]),
process_output(Data, Repeats).
测试:
rorra:~/erlang > erl
Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V6.4 (abort with ^G)
1> c(solution).
{ok,solution}
2> solution:main().
3
1
2
3
4
1
1
1
2
2
2
3
3
3
4
4
4
ok
3>
我认为在缺少最后一个换行符的情况下从 io:get_line/1
处理 eof
以及处理表示输入结束的空行更容易:
-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, []).
process_input/2
函数现在接受一个累加器,它最初是一个空列表。它递归地调用自己,直到检测到输入结束,然后打印输出。它调用 io:get_line/1
并检查它 returns 是 eof
还是只是一个换行符,对于这种情况,它会反转其累加器并打印其输出。对于任何其他输入,它会去除最后的换行符,通过 lists:duplicate/2
重复输入,将结果存储在新的累加器中,并将其传递给递归调用。
output/1
函数从 process_input/2
中获取累加器,用换行符连接重复的值,然后打印结果。请注意,此版本的 solution
模块将结果的格式限制为 output/1
函数,以防您想将 process_input/2
的原始结果用于其他目的。
最后,我将你的 main/0
重命名为 start/0
因为 运行 通过 erl -s
命令行选项设置一个函数假定一个名为 start
的函数如果给出 none。
我们可以在 Unix shell 中使用 printf
来创建没有最终换行符的输入文件:
$ printf '3\n1\n2\n3\n4\n' > in
然后 运行 我们编译的 solution
模块是这样的,在这种情况下得到我们期望的三倍输出:
$ cat in | erl -noshell -s solution -s init stop
1
1
1
2
2
2
3
3
3
4
4
4
在 in
文件中添加最后一个换行符会得到相同的结果(试试看)。我们还可以创建每行包含多个字符的输入:
$ 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
对于这个 in2
文件,我们也得到了预期的双倍输出。
我自己的回答:
-module(solution).
-export([main/0]).
process_input(Repeats)->
Line = io:get_line(""),
case lists:reverse(Line) of
"\n" ++ _ -> output(Line, Repeats), process_input(Repeats);
_ -> output(Line ++ "~n" , Repeats)
end.
output(_, 0)-> ok;
output(Line, Repeats)->
io:format(Line),
output(Line, Repeats - 1).
main()->
{ok, [Repeats]} = io:fread("", "~d"),
process_input(Repeats).
这是我想出的(在上述答案的帮助下)。我正在添加我的解决方案,因为它还处理问题中所述的约束:
-module(solution).
-export([main/0]).
main() -> get_input([]).
print_list(_,[_|[]]) -> ok;
print_list(NumTimes,[_|List]) ->
Number = hd(List),
print_list_number(NumTimes,Number),
print_list(NumTimes,List).
print_list_number(NumTimes,Number)
when
(NumTimes > 0)
and
(Number >= 1)
and
(Number =< 100)
->
io:fwrite("~B~n",[Number]),
print_list_number(NumTimes - 1,Number);
print_list_number(_,_) -> ok.
get_input(Acc) ->
case io:get_line("") of
Done when
Done == eof;
Done == "\n"
->
NumTimes = hd(Acc),
%% Make sure we only run this when the List length isn't greater than 10
if
(length(Acc) - 1 =< 10)
and
(NumTimes =< 100)
->
print_list(NumTimes,Acc);
true -> ok
end;
Line ->
{NumInt,_} = string:to_integer(Line),
List = Acc ++ [NumInt],
get_input(List)
end.
我是 Erlang 的新手,如果这很混乱/效率低下,请原谅我!