【问题标题】:List replication challenge with Erlang使用 Erlang 列出复制挑战
【发布时间】:2015-09-10 19:51:19
【问题描述】:

我正在尝试研究解决 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 的数字)。有什么想法吗?

【问题讨论】:

    标签: erlang


    【解决方案1】:

    你必须关闭流的回声,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).
    

    【讨论】:

      【解决方案2】:

      我刚刚更新了解决挑战的代码,所以想法是将输入保存在累加器中(在本例中为列表),最后处理列表,如果你想避免输出什么随时在屏幕上写入,您可以禁用回声,就像我在另一个答案中显示的示例一样

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

      【讨论】:

        【解决方案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 并检查它是否返回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 文件,我们也得到了预期的双倍输出。

        【讨论】:

        • 感谢您的回答。在下面添加了我自己的解决方案
        【解决方案4】:

        我自己的回答:

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

        【讨论】:

          【解决方案5】:

          这是我想出的(在上述答案的帮助下)。我正在添加我的解决方案,因为它还处理问题中所述的约束:

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

          【讨论】:

            猜你喜欢
            • 2011-12-11
            • 1970-01-01
            • 2016-08-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-10-09
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多