【问题标题】:Erlang distributed reverse stringErlang 分布式反向字符串
【发布时间】:2019-05-01 00:14:35
【问题描述】:

我是 erlang 新手,我不知道如何解决这个问题。
我需要通过将长字符串划分为 N 个子字符串来反转一个长字符串,反转单个子字符串,然后将它们连接起来以获得原始字符串的反转。 每个子字符串都需要通过不同的进程进行反转。

我的问题是:
1) 如何将字符串拆分为 N 个大小相等的子字符串?
2) 如何加入其他进程收到的字符串?

谁能给我一个示例代码?这是我所做的,但缺少主要部分:

% This function should split the string, spawn the processes
% and recombine the results
reverse(Str, N) -> % ...

sub_reverse() ->
    receive
        { From, SubStr } -> From ! { self(), lists:reverse(SubStr) }
    end.

【问题讨论】:

    标签: erlang


    【解决方案1】:

    试试这样的。

    -module(stackoverflow).
    -export([reverse/2, join/0, sub_reverse/2]).
    
    reverse(Str, N) ->
        % A process joining the reversed substrings.
        JoinPID = spawn(stackoverflow, join, []),
    
        % The step size is the length of Str divided by N.
        % TODO Handle remainder.
        Step = string:length(Str) div N,
    
        % The split points are calculated from end to start of Str.
        SplitPoints = lists:seq(string:length(Str) - Step, 0, -Step),
    
        % For each split point, spwan a process that reverts the substring for the
        % split point.
        lists:foreach(fun(From) ->
                        Substr = string:slice(Str, From, Step),
                        spawn(stackoverflow, sub_reverse, [JoinPID, Substr])
                      end,
                      SplitPoints).
    
    join() ->
        receive
            {reverse_str, ReverseStr} ->
                io:format("~s", [ReverseStr]),
                join()
        end.
    
    sub_reverse(JoinPID, SubStr) ->
        JoinPID ! {reverse_str, lists:reverse(SubStr)}.
    

    编辑

    这种方法有效,但取决于生成进程的顺序。如果他们返回乱序,join() 会收到乱序的零件。因此,一个可能的改进可能是用From 标记每个部分,以便join() 可以按正确的顺序加入它们。这留给读者作为练习。

    【讨论】:

    • 谢谢,我在考虑纯递归方法,但使用 stdlib 函数要容易得多。为了完整起见,我已经发布了我的版本。
    【解决方案2】:

    这是我回答后的版本:

    -module(reverse).
    -export([reverse/1, join/3, sub_reverse/3]).
    
    reverse("") -> "";
    reverse(Str) ->
        Step = ceil(string:length(Str) / 10),
        SplitPoints = lists:seq(0, string:length(Str) - 1, Step),
    
        JoinPid = spawn(reverse, join, [self(), [], length(SplitPoints)]),
    
        lists:foreach(
            fun (Start) ->
                IndexPos = Start div Step,
                SubStr = string:slice(Str, Start, Step),
                spawn(reverse, sub_reverse, [JoinPid, IndexPos, SubStr])
            end,
        SplitPoints),
    
        receive
            { joined, ReversedStr } -> io:format("~p", [ReversedStr])
        end.
    
    join(ReversePid, Acc, N) ->
        case length(Acc) of
            N ->
                Parts = lists:sort(fun ({A, _}, {B, _}) -> A > B end, Acc),
                Str = string:join(lists:map(fun ({_, SubStr}) -> SubStr end, Parts), ""),
                ReversePid ! { joined, Str };
            _ ->
                receive
                    {reversed, X} -> join(ReversePid, [X | Acc], N)
                end
        end.
    
    
    sub_reverse(JoinPid, IndexPos, SubStr) ->
        JoinPid ! {reversed, { IndexPos, string:reverse(SubStr) } }.
    

    【讨论】:

      猜你喜欢
      • 2012-04-30
      • 2013-02-26
      • 1970-01-01
      • 1970-01-01
      • 2014-10-31
      • 2021-03-15
      • 2011-12-03
      • 1970-01-01
      • 2010-12-13
      相关资源
      最近更新 更多