Erlang 分布式反向字符串
Erlang distributed reverse string
我是 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.
尝试这样的事情。
-module(Whosebug).
-export([reverse/2, join/0, sub_reverse/2]).
reverse(Str, N) ->
% A process joining the reversed substrings.
JoinPID = spawn(Whosebug, 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(Whosebug, 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)}.
编辑
此方法有效,但取决于 spawend 进程的顺序。如果他们 return 出现故障,join()
收到的部件也会出现故障。因此,一个可能的改进是用 From
标记每个部分,这样 join()
就可以按正确的顺序加入它们。这是留给 reader.
的练习
这是我回答后的版本:
-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) } }.
我是 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.
尝试这样的事情。
-module(Whosebug).
-export([reverse/2, join/0, sub_reverse/2]).
reverse(Str, N) ->
% A process joining the reversed substrings.
JoinPID = spawn(Whosebug, 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(Whosebug, 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)}.
编辑
此方法有效,但取决于 spawend 进程的顺序。如果他们 return 出现故障,join()
收到的部件也会出现故障。因此,一个可能的改进是用 From
标记每个部分,这样 join()
就可以按正确的顺序加入它们。这是留给 reader.
这是我回答后的版本:
-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) } }.