在Erlang中列出和列出值操作

时间:2013-09-24 22:56:50

标签: list recursion erlang list-comprehension tail-recursion

我正在学习一些Erlang并从书中做练习,所以我被困在其中一个上面。如果我引用整个问题然后解释到目前为止我做了什么,那就更好了: “如果重复申请,正数就很高兴 达到了数字1以下的程序。 1.对数字的每个数字进行平方 2.计算所有方块的总和 例如,如果你从19开始:

 1 * 1 + 9 * 9 = 1 + 81 = 82
 8 * 8 + 2 * 2 = 64 + 4 = 68
 6 * 6 + 8 * 8 = 36 + 64 = 100
 1 * 1 + 0 * 0 + 0 * 0 = 1 + 0 + 0 = 1 

(即19是一个快乐的数字) 你怎么知道一个号码不开心的时候?其实,每个人都不高兴 数字最终将达到周期4,16,37,58,89,145,42,20,4, ...因此,在该周期(例如4)中寻找任何数字就足够了 得出结论,原始数字不满意。 编写函数happy / 1和all_happy / 2,返回 数字是否满意(真或假)和所有快乐数字 分别在N和M之间。 (提示:使用数字化和 和)。 例子:

 happy(28) → true
 happy(15) → false
 happy(5, 25) → [7, 10, 13, 19, 23]"

所以,我创建了一个数字化仪/ 1,给出一个正数N返回该数字中的数字列表:

digitize(N) -> digitize1(N, []).
digitize1(N, Acc) when N > 0 -> digitize1(N div 10, [N rem 10| Acc]);
digitize1(N, Acc) when N == 0 -> Acc.

,和/ 1:

sum(N) when  N > 0 -> N + sum(N-1);
sum(0) ->   0.

所以到目前为止我所做的快乐数字是:

happy(N) -> happy1(digitize(N), []).
happy1([], Acc) -> (Acc);
happy1([Head|Tail], Acc1) -> happy1(Tail, [Head * Head|Acc1]).

它对列表中的元素进行了平方,但是我无法想出如何对它们求和并再次递归地再次执行它直到达到1或4.任何帮助或想法? 对于第二部分(all_happy / 2),在我的非主管意见中,我应该使用列表理解,但同样,我不太确定如何实现它。谢谢你的时间。

2 个答案:

答案 0 :(得分:2)

我注意到的一件事是你的happy1循环可以直接计算总和,你不需要列表然后添加它们:

calculate([], Total)->
  Total;
calculate([First | Rest], Total) ->
  calculate(Rest, Total + (First * First)).

对于问题的要点,您可以使用模式匹配来检测您是否已达到不满意的数字,或者您是否已达到1。

我有一个有效的实施方案,但我猜你想为自己弄清楚细节。如果您要我发布,请告诉我。


这是我的解决方案:

-module(happy).

-export([happy/1]).

happy(1) ->
  happy;
happy(4) ->
  not_happy;
happy(Num) ->
  io:format("Current loop: ~p~n", [Num]),
  Digits = digitize(Num),
  happy(calculate(Digits, 0)).


digitize(N) -> digitize1(N, []).
digitize1(N, Acc) when N > 0 -> digitize1(N div 10, [N rem 10| Acc]);
digitize1(N, Acc) when N == 0 -> Acc.

calculate([], Total)->
  Total;
calculate([First | Rest], Total) ->
  calculate(Rest, Total + (First * First)).

输出:

3> happy:happy(55).
Current loop: 55
Current loop: 50
Current loop: 25
Current loop: 29
Current loop: 85
Current loop: 89
Current loop: 145
Current loop: 42
Current loop: 20
not_happy
4> happy:happy(4). 
not_happy
5> happy:happy(19).
Current loop: 19
Current loop: 82
Current loop: 68
Current loop: 100
happy
6> happy:happy(20).
Current loop: 20
not_happy
7> happy:happy(21).
Current loop: 21
Current loop: 5
Current loop: 25
Current loop: 29
Current loop: 85
Current loop: 89
Current loop: 145
Current loop: 42
Current loop: 20
not_happy

如果您对如何使用列表推导感兴趣,这里是跳过calculate方法的主要子句,并将lists:sum函数与构建列表一起使用:

happy(Num) ->
  io:format("Current loop: ~p~n", [Num]),
  Digits = [ X * X || X <- digitize(Num)],
  happy(lists:sum(Digits)).

答案 1 :(得分:0)

通过尾递归实现的另一个解决方案:

digitize(N) -> digitize1(N, [],N).
digitize1(N, Acc,M) when N > 0 -> digitize1(N div 10, [N rem 10| Acc],M);
digitize1(N, Acc,M) when N == 0 -> sum_digits(Acc,0,M).

sum_digits([],Acc,N) when Acc == 1 -> {happy,N,Acc};
sum_digits([], Acc,N) when Acc == 4 -> {unhappy,N,Acc};
sum_digits([],Acc,N) -> {digitize,Acc}, digitize1(Acc,[],N);
sum_digits([H|T],Acc,N)-> sum_digits(T,H*H+Acc,N).

使用:

1> c('test.erl').
test.erl:15: Warning: a term is constructed, but never used
{ok,test}
2> c('test.erl').
test.erl:15: Warning: a term is constructed, but never used
{ok,test}
3> c('test.erl').
test.erl:15: Warning: a term is constructed, but never used
{ok,test}
4> test:digitize(55).
{unhappy,55,4}
5> test:digitize(19).
{happy,19,1}
6> test:digitize(5). 
{unhappy,5,4}
7> test:digitize(20).
{unhappy,20,4}
8> test:digitize(21).
{unhappy,21,4}