Recursion 使用递归的Erlang素数分解

Recursion 使用递归的Erlang素数分解,recursion,erlang,factorization,Recursion,Erlang,Factorization,我试图用素数分解来计算一个数的因子。我想使用if语句来测试条件,如果factor是factor,则创建一个列表。它不起作用,我想不出任何其他可行的方法,建议 factor( N ) -> if N rem factor(N-1) == 0 -> [N|factor(N-1)]; true -> false; end. 这段代码进行分解,但我不使用if语句(在Erlang IMHO中不太常见): 我记录了一

我试图用素数分解来计算一个数的因子。我想使用if语句来测试条件,如果factor是factor,则创建一个列表。它不起作用,我想不出任何其他可行的方法,建议

factor( N ) ->
    if
        N rem factor(N-1) == 0 ->
            [N|factor(N-1)];
        true -> false;
    end.

这段代码进行分解,但我不使用if语句(在Erlang IMHO中不太常见):

我记录了一个示例的执行跟踪。请注意,decomp/3是尾部递归的,因此长返回阶段实际上是单个返回

1> help_num:decomp(70610).
++ (3) <147> decomp(70610,[],2)
++ (4) <150> decomp(35305,[2],2)
++ (5) <151> decomp(35305,[2],3)
++ (6) <152> decomp(35305,[2],5)
++ (7) <150> decomp(7061,[5,2],5)
++ (8) <152> decomp(7061,[5,2],7)
++ (9) <152> decomp(7061,[5,2],9)
++ (10) <152> decomp(7061,[5,2],11)
++ (11) <152> decomp(7061,[5,2],13)
++ (12) <152> decomp(7061,[5,2],15)
++ (13) <152> decomp(7061,[5,2],17)
++ (14) <152> decomp(7061,[5,2],19)
++ (15) <152> decomp(7061,[5,2],21)
++ (16) <152> decomp(7061,[5,2],23)
++ (17) <150> decomp(307,[23,5,2],23)
-- (17) [307,23,5,2]
-- (16) [307,23,5,2]
-- (15) [307,23,5,2]
-- (14) [307,23,5,2]
-- (13) [307,23,5,2]
-- (12) [307,23,5,2]
-- (11) [307,23,5,2]
-- (10) [307,23,5,2]
-- (9) [307,23,5,2]
-- (8) [307,23,5,2]
-- (7) [307,23,5,2]
-- (6) [307,23,5,2]
-- (5) [307,23,5,2]
-- (4) [307,23,5,2]
-- (3) [307,23,5,2]
++ (3) <147> lists:reverse([307,23,5,2])
[2,5,23,307]
2>
1>帮助编号:decomp(70610)。
++(3)反编译(70610,[],2)
++(4)反编译(35305[2],2)
++(5)反编译(35305[2],3)
++(6)反编译(35305[2],5)
++(7)反编译(7061[5,2],5)
++(8)反编译(7061[5,2],7)
++(9)反编译(7061[5,2],9)
++(10)反编译(7061[5,2],11)
++(11)反编译(7061[5,2],13)
++(12)反编译(7061[5,2],15)
++(13)反编译(7061[5,2],17)
++(14)反编译(7061[5,2],19)
++(15)反编译(7061,[5,2],21)
++(16)反编译(7061[5,2],23)
++(17)反编译(307[23,5,2],23)
-- (17) [307,23,5,2]
-- (16) [307,23,5,2]
-- (15) [307,23,5,2]
-- (14) [307,23,5,2]
-- (13) [307,23,5,2]
-- (12) [307,23,5,2]
-- (11) [307,23,5,2]
-- (10) [307,23,5,2]
-- (9) [307,23,5,2]
-- (8) [307,23,5,2]
-- (7) [307,23,5,2]
-- (6) [307,23,5,2]
-- (5) [307,23,5,2]
-- (4) [307,23,5,2]
-- (3) [307,23,5,2]
++(3)列表:反向([307,23,5,2])
[2,5,23,307]
2>

乍看之下,我发现代码中有两件事不起作用:

  • 函数应该返回一个列表。因此,测试“N rem factor(N-1)==0”将计算列表的剩余部分除以一个数字,这毫无意义。不能对列表执行除法

  • if-guard中有一个递归调用,这是不受支持的


  • 除非您更详细地解释代码应该如何工作,否则我认为我无法提供更好的帮助。

    这里有一个实现示例。你不必关注
    下一步\u可能是\u prime/2
    。您可以使用simple
    Old+2
    。这只是优化

    -module(factor).
    
    -export([factor/1, make_wheels/0]).
    
    factor(X) when is_integer(X), X > 0 ->
        factor(X, 2, first_primes_steps()).
    
    factor(X, X, _) -> [X];
    factor(X, Prime, Wheel) when X rem Prime =:= 0 ->
        [Prime|factor(X div Prime, Prime, Wheel)];
    factor(X, Old, Wheel) when Old*Old < X ->
        {MayBePrime, Wheel2} = next_may_be_prime(Old, Wheel),
        factor(X, MayBePrime, Wheel2);
    factor(X, _, _) -> [X].
    
    %%% Prime candidates generator
    
    next_may_be_prime(X, [Add|T]) ->
        {X+Add, case T of [] -> wheel(); _ -> T end}.
    
    first_primes_steps() -> [1,2,2,4,2].
    
    wheel() ->
        [4,2,4,6,2,6,4,2,4,6,6,2,6,4,2,6,4,6,8,4,2,4,2,4,14,4,6,2,
         10,2,6,6,4,2,4,6,2,10,2,4,2,12,10,2,4,2,4,6,2,6,4,6,6,6,2,6,
         4,2,6,4,6,8,4,2,4,6,8,6,10,2,4,6,2,6,6,4,2,4,6,2,6,4,2,6,10,
         2,10,2,4,2,4,6,8,4,2,4,12,2,6,4,2,6,4,6,12,2,4,2,4,8,6,4,6,
         2,4,6,2,6,10,2,4,6,2,6,4,2,4,2,10,2,10,2,4,6,6,2,6,6,4,6,6,
         2,6,4,2,6,4,6,8,4,2,6,4,8,6,4,6,2,4,6,8,6,4,2,10,2,6,4,2,4,
         2,10,2,10,2,4,2,4,8,6,4,2,4,6,6,2,6,4,8,4,6,8,4,2,4,2,4,8,6,
         4,6,6,6,2,6,6,4,2,4,6,2,6,4,2,4,2,10,2,10,2,6,4,6,2,6,4,2,4,
         6,6,8,4,2,6,10,8,4,2,4,2,4,8,10,6,2,4,8,6,6,4,2,4,6,2,6,4,6,
         2,10,2,10,2,4,2,4,6,2,6,4,2,4,6,6,2,6,6,6,4,6,8,4,2,4,2,4,8,
         6,4,8,4,6,2,6,6,4,2,4,6,8,4,2,4,2,10,2,10,2,4,2,4,6,2,10,2,
         4,6,8,6,4,2,6,4,6,8,4,6,2,4,8,6,4,6,2,4,6,2,6,6,4,6,6,2,6,6,
         4,2,10,2,10,2,4,2,4,6,2,6,4,2,10,6,2,6,4,2,6,4,6,8,4,2,4,2,
         12,6,4,6,2,4,6,2,12,4,2,4,8,6,4,2,4,2,10,2,10,6,2,4,6,2,6,4,
         2,4,6,6,2,6,4,2,10,6,8,6,4,2,4,8,6,4,6,2,4,6,2,6,6,6,4,6,2,
         6,4,2,4,2,10,12,2,4,2,10,2,6,4,2,4,6,6,2,10,2,6,4,14,4,2,4,
         2,4,8,6,4,6,2,4,6,2,6,6,4,2,4,6,2,6,4,2,4,12,2,12].
    
    %%% Auxiliary functions for making prime wheels
    
    make_wheels() ->
        %%%%%%%%%%%%%%%%
        Primes = [2,3,5,7,11],
        Next = 13,
        %%%%%%%%%%%%%%%%
        Period = lists:foldl(fun(X, A) -> X*A end, 1, Primes),
        Max = Period + Next,
        F = fun(X, A) -> array:set(X, false, A) end,
        G = fun(X, A) -> lists:foldl(F, A, lists:seq(X, Max, X)) end,
        Sieve = lists:foldl(G, array:new([{default, true}]), Primes),
        {
            diffs(Primes ++ [Next]),
            diffs([ X || X <- lists:seq(Next, Max), array:get(X, Sieve)])
            }.
    
    diffs([H|T]) ->
        diffs(H, T).
    
    diffs(_, []) -> [];
    diffs(A, [B|T]) -> [B-A|diffs(B, T)].
    
    -模块(系数)。
    -出口([系数/1,制造车轮/0])。
    因子(X)为_整数(X),X>0->
    因子(X,2,first_primes_steps())。
    因子(X,X,ux)->[X];
    当X rem Prime=:=0->
    [Prime |因子(X div Prime,Prime,Wheel)];
    旧*旧
    {MayBePrime,Wheel2}=下一个可能是(旧的,Wheel),
    因子(X,可能是素数,轮2);
    因子(X,,-->[X]。
    %%%素候选者生成器
    下一个可能是素数(X,[Add | T])->
    {X+Add,[]->wheel();u->T end}的案例T。
    第一个素数步骤()->[1,2,2,4,2]。
    轮子()->
    [4,2,4,6,2,6,4,2,4,6,6,2,6,4,2,6,4,6,8,4,2,4,2,4,14,4,6,2,
    10,2,6,6,4,2,4,6,2,10,2,4,2,12,10,2,4,2,4,6,2,6,4,6,6,6,2,6,
    4,2,6,4,6,8,4,2,4,6,8,6,10,2,4,6,2,6,6,4,2,4,6,2,6,4,2,6,10,
    2,10,2,4,2,4,6,8,4,2,4,12,2,6,4,2,6,4,6,12,2,4,2,4,8,6,4,6,
    2,4,6,2,6,10,2,4,6,2,6,4,2,4,2,10,2,10,2,4,6,6,2,6,6,4,6,6,
    2,6,4,2,6,4,6,8,4,2,6,4,8,6,4,6,2,4,6,8,6,4,2,10,2,6,4,2,4,
    2,10,2,10,2,4,2,4,8,6,4,2,4,6,6,2,6,4,8,4,6,8,4,2,4,2,4,8,6,
    4,6,6,6,2,6,6,4,2,4,6,2,6,4,2,4,2,10,2,10,2,6,4,6,2,6,4,2,4,
    6,6,8,4,2,6,10,8,4,2,4,2,4,8,10,6,2,4,8,6,6,4,2,4,6,2,6,4,6,
    2,10,2,10,2,4,2,4,6,2,6,4,2,4,6,6,2,6,6,6,4,6,8,4,2,4,2,4,8,
    6,4,8,4,6,2,6,6,4,2,4,6,8,4,2,4,2,10,2,10,2,4,2,4,6,2,10,2,
    4,6,8,6,4,2,6,4,6,8,4,6,2,4,8,6,4,6,2,4,6,2,6,6,4,6,6,2,6,6,
    4,2,10,2,10,2,4,2,4,6,2,6,4,2,10,6,2,6,4,2,6,4,6,8,4,2,4,2,
    12,6,4,6,2,4,6,2,12,4,2,4,8,6,4,2,4,2,10,2,10,6,2,4,6,2,6,4,
    2,4,6,6,2,6,4,2,10,6,8,6,4,2,4,8,6,4,6,2,4,6,2,6,6,6,4,6,2,
    6,4,2,4,2,10,12,2,4,2,10,2,6,4,2,4,6,6,2,10,2,6,4,14,4,2,4,
    2,4,8,6,4,6,2,4,6,2,6,6,4,2,4,6,2,6,4,2,4,12,2,12].
    %%%制造主轮的辅助功能
    制造车轮()->
    %%%%%%%%%%%%%%%%
    素数=[2,3,5,7,11],
    下一个=13,
    %%%%%%%%%%%%%%%%
    周期=列表:foldl(乐趣(X,A)->X*A结束,1,素数),
    最大值=周期+下一个,
    F=fun(X,A)->array:set(X,false,A)end,
    G=fun(X,A)->列表:foldl(F,A,列表:seq(X,Max,X))结束,
    Sieve=list:foldl(G,数组:new([{default,true}]),Primes),
    {
    diff(Primes++[Next]),
    差异([X | | X
    差分(H,T)。
    差异(u,[])->[];
    微分(A[B | T])->[B-A |微分(B,T)]。
    
    我想使用一个N数,并返回一个所有N的因子列表。我想做的是让每个数小于N,然后用N除以该数,循环生成它们。例如,如果我有3,我会得到(N-1)=2…3/2…不会除法,所以我将转到下一个数字。您可以在
    if
    语句中进行递归。没有这样的限制。在if语句的子句体中,是的。在保护表达式中,不是。有这样的限制。与
    if
    语句无关,所有保护都不能包含用户函数。相同的缺点train对于函数子句卫士和case语句子句卫士也是有效的。为什么最初要反转列表?列表反转是在分解求值结束时完成的,这只是因为当我执行此函数时,我希望得到从最小到最大排序的素因子。算法这是构建列表的常用方法,因为它避免了在每一步都创建一个新的副本;最后进行反向操作的成本比那些多个副本要低。
    -module(factor).
    
    -export([factor/1, make_wheels/0]).
    
    factor(X) when is_integer(X), X > 0 ->
        factor(X, 2, first_primes_steps()).
    
    factor(X, X, _) -> [X];
    factor(X, Prime, Wheel) when X rem Prime =:= 0 ->
        [Prime|factor(X div Prime, Prime, Wheel)];
    factor(X, Old, Wheel) when Old*Old < X ->
        {MayBePrime, Wheel2} = next_may_be_prime(Old, Wheel),
        factor(X, MayBePrime, Wheel2);
    factor(X, _, _) -> [X].
    
    %%% Prime candidates generator
    
    next_may_be_prime(X, [Add|T]) ->
        {X+Add, case T of [] -> wheel(); _ -> T end}.
    
    first_primes_steps() -> [1,2,2,4,2].
    
    wheel() ->
        [4,2,4,6,2,6,4,2,4,6,6,2,6,4,2,6,4,6,8,4,2,4,2,4,14,4,6,2,
         10,2,6,6,4,2,4,6,2,10,2,4,2,12,10,2,4,2,4,6,2,6,4,6,6,6,2,6,
         4,2,6,4,6,8,4,2,4,6,8,6,10,2,4,6,2,6,6,4,2,4,6,2,6,4,2,6,10,
         2,10,2,4,2,4,6,8,4,2,4,12,2,6,4,2,6,4,6,12,2,4,2,4,8,6,4,6,
         2,4,6,2,6,10,2,4,6,2,6,4,2,4,2,10,2,10,2,4,6,6,2,6,6,4,6,6,
         2,6,4,2,6,4,6,8,4,2,6,4,8,6,4,6,2,4,6,8,6,4,2,10,2,6,4,2,4,
         2,10,2,10,2,4,2,4,8,6,4,2,4,6,6,2,6,4,8,4,6,8,4,2,4,2,4,8,6,
         4,6,6,6,2,6,6,4,2,4,6,2,6,4,2,4,2,10,2,10,2,6,4,6,2,6,4,2,4,
         6,6,8,4,2,6,10,8,4,2,4,2,4,8,10,6,2,4,8,6,6,4,2,4,6,2,6,4,6,
         2,10,2,10,2,4,2,4,6,2,6,4,2,4,6,6,2,6,6,6,4,6,8,4,2,4,2,4,8,
         6,4,8,4,6,2,6,6,4,2,4,6,8,4,2,4,2,10,2,10,2,4,2,4,6,2,10,2,
         4,6,8,6,4,2,6,4,6,8,4,6,2,4,8,6,4,6,2,4,6,2,6,6,4,6,6,2,6,6,
         4,2,10,2,10,2,4,2,4,6,2,6,4,2,10,6,2,6,4,2,6,4,6,8,4,2,4,2,
         12,6,4,6,2,4,6,2,12,4,2,4,8,6,4,2,4,2,10,2,10,6,2,4,6,2,6,4,
         2,4,6,6,2,6,4,2,10,6,8,6,4,2,4,8,6,4,6,2,4,6,2,6,6,6,4,6,2,
         6,4,2,4,2,10,12,2,4,2,10,2,6,4,2,4,6,6,2,10,2,6,4,14,4,2,4,
         2,4,8,6,4,6,2,4,6,2,6,6,4,2,4,6,2,6,4,2,4,12,2,12].
    
    %%% Auxiliary functions for making prime wheels
    
    make_wheels() ->
        %%%%%%%%%%%%%%%%
        Primes = [2,3,5,7,11],
        Next = 13,
        %%%%%%%%%%%%%%%%
        Period = lists:foldl(fun(X, A) -> X*A end, 1, Primes),
        Max = Period + Next,
        F = fun(X, A) -> array:set(X, false, A) end,
        G = fun(X, A) -> lists:foldl(F, A, lists:seq(X, Max, X)) end,
        Sieve = lists:foldl(G, array:new([{default, true}]), Primes),
        {
            diffs(Primes ++ [Next]),
            diffs([ X || X <- lists:seq(Next, Max), array:get(X, Sieve)])
            }.
    
    diffs([H|T]) ->
        diffs(H, T).
    
    diffs(_, []) -> [];
    diffs(A, [B|T]) -> [B-A|diffs(B, T)].