我希望根据Erlang中的Head或Middle递归对数字进行分解。该函数称为fact,取1个参数,fact / 1。结果将返回作为数字因子的数字列表。
24返回以下内容:[1,2,3,4,6,8,12,24]
有没有人有任何想法我会怎么做?
答案 0 :(得分:2)
我建议你这个解决方案。我首先搜索素因子中的分解,然后构建除数列表。我认为平均来说应该更有效率。
divlist(N) -> automult([1|decomp(N)]).
decomp(N) when is_integer(N), (N > 0) ->
lists:reverse(decomp(N,[],2)).
decomp(N,R,I) when I*I > N -> [N|R];
decomp(N,R,I) when (N rem I) =:= 0 -> decomp(N div I,[I|R],I);
decomp(N,R,2) -> decomp(N,R,3);
decomp(N,R,I) -> decomp(N,R,I+2).
automult(L=[H]) when is_number(H)-> L;
automult([H|Q]) when is_number(H)->
L1 = automult(Q),
L2 = [H*X || X <- L1],
lists:usort([H|L1]++L2).
@ Zoukaye和@P_A和我提出的解决方案给出了相同的结果,但是他们的解决方案都具有O(n)的复杂性。我的建议评估起来比较复杂,因为它分为两部分。搜索或素数分解主要由0(log(n)),第二部分取决于第一部分的结果,有趣的是,它不是两个部分的最坏情况:
最后一句话,@ Zoukaye使用整数的中间列表。如果你打算将它用于looooong整数,那么这是一个坏主意,因为只有构建这个列表才会因内存不足而崩溃。
我做了一个性能测试,比较了我创建一个小于Max的N个随机数列表的解决方案,评估每个解决方案的整个执行时间,验证它们是等效的还是返回时间。结果是
数量少于10 000的10000次测试:
我的:63ms,P_A:788ms,Zoukaye:1383ms10 000次测试,数量少于10万:
我的:80ms,P_A:9240ms,Zoukaye:13594ms数量少于1000 000的10000次测试:
我的:105ms,P_A:101001ms,Zoukaye:137145ms以下是我使用的代码:
-module (test).
-compile((export_all)).
test(Nbtest,Max) ->
random:seed(erlang:now()),
L = [random:uniform(Max) || _ <- lists:seq(1,Nbtest)],
F1 = fun() -> [{X,divlist(X)} || X <- L] end,
F2 = fun() -> [{X,fact_comp(X)} || X <- L] end,
F3 = fun() -> [{X,fact_rec(X)} || X <- L] end,
{T1,R} = timer:tc(F1),
{T2,R} = timer:tc(F2),
{T3,R} = timer:tc(F3),
{T1,T2,T3}.
% Method1
divlist(N) -> automult([1|decomp(N)]).
decomp(N) when is_integer(N), (N > 0) ->
lists:reverse(decomp(N,[],2)).
decomp(N,R,I) when I*I > N -> [N|R];
decomp(N,R,I) when (N rem I) =:= 0 -> decomp(N div I,[I|R],I);
decomp(N,R,2) -> decomp(N,R,3);
decomp(N,R,I) -> decomp(N,R,I+2).
automult(L=[H]) when is_number(H)-> L;
automult([H|Q]) when is_number(H)->
L1 = automult(Q),
L2 = [H*X || X <- L1],
lists:usort([H|L1]++L2).
% Method 2
fact_comp(N) ->
if N > 0 ->
[ V || V <- lists:seq(1, N div 2), N rem V =:= 0 ] ++ [ N ];
N < 0 ->
Na = 0 - N,
[ V || V <- lists:seq(1, Na div 2), Na rem V =:= 0 ] ++ [ Na ];
N =:= 0 -> []
end.
% Method 3
fact_rec(N) ->
fact_rec(N, 1, []).
fact_rec(N, I, Acc) when I =< trunc(N/2) ->
case N rem I of
0 -> fact_rec(N, I+1, [I | Acc]);
_ -> fact_rec(N, I+1, Acc)
end;
fact_rec(N, _I, Acc) -> lists:reverse(Acc) ++ [N].
答案 1 :(得分:0)
这样的东西?
Object.first.created_at
答案 2 :(得分:0)
使用列表理解
fact_comp(N) ->
if N > 0 ->
[ V || V <- lists:seq(1, N div 2), N rem V =:= 0 ] ++ [ N ];
N < 0 ->
Na = 0 - N,
[ V || V <- lists:seq(1, Na div 2), Na rem V =:= 0 ] ++ [ Na ];
N =:= 0 -> []
end.