列出Erlang的复制挑战

p4rjhz4m  于 2023-06-04  发布在  Erlang
关注(0)|答案(6)|浏览(219)

我正在学习Erlang解决Hackerrank问题。有一个叫做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的数字)。有什么想法吗

tvmytwxo

tvmytwxo1#

我认为在缺少最后一个换行符的情况下,从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并检查它是否返回eof或只是一个换行符,对于这种情况,它反转其累加器并打印其输出。对于任何其他输入,它剥离最后一个换行符,通过lists:duplicate/2重复输入,将结果存储在新的累加器中,并将其传递给递归调用。
output/1函数从process_input/2获取累加器,用换行符连接重复的值,然后打印结果。请注意,此版本的solution模块将结果的格式限制为output/1函数,以防您希望将process_input/2的原始结果用于其他目的。
最后,我将您的main/0重命名为start/0,因为通过erl -s命令行选项运行函数时,如果没有给出任何函数,则会假定名称为start的函数。
我们可以在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文件,我们也得到了预期的双倍输出。

bf1o4zei

bf1o4zei2#

您必须使用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).
ckx4rj1h

ckx4rj1h3#

我刚刚更新了解决这个问题的代码,所以我的想法是,你把输入保存在一个累加器中(在这个例子中是一个列表),最后你处理这个列表,如果你想避免在任何时候输出屏幕上写的东西,你可以禁用echo,就像我在另一个答案中展示的例子一样。

-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>
toiithl6

toiithl64#

我自己的回答:

-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).
fcipmucu

fcipmucu5#

这是我的想法(在上面答案的帮助下)。我添加我的解决方案是因为它也处理问题中陈述的约束:

-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还很陌生,所以如果这是混乱/低效的,请原谅我!

hrirmatl

hrirmatl6#

-module(solution).
-export([main/0]).    
main() ->
    {ok, [N]} = io:fread("", "~d"),
    Numbers = loop([]),
    InOrder = lists:reverse(Numbers),
    lists:map(
        fun(El) ->
            lists:map(
                fun(_) ->
                    io:format("~p~n", [El])
                end,
                lists:seq(1, N)
            )
        end,
        InOrder
    ),
    ok.

loop(L) ->
    case io:get_line("") of
        eof ->
            L;
        "\n" ->
            L;
        Num ->
            {N, _} = string:to_integer(Num),
            loop([N | L])
    end.

相关问题