erlang 入门练习 顺序编程一
- 目前只学到顺序编程, 其余个人认为真正的精髓OTP 并发,后期学习
- 找了些带有逻辑应用题来练练手,熟悉语法和erlang多用的尾递归思维
1.运动员分组
有N个人参加100米短跑比赛。跑道为8条。程序的任务是按照尽量使每组的人数相差最少的原则分组。
例如:
N=8时,分成1组即可。
N=9时,分成2组:一组5人,一组4人。
N=25时,分4组:7、6、6、6。
请编程计算分组数字。
要求从标准输入获得一个正整数(1~100之间,不必考虑输入错误的情况),表示参赛的人数。
程序输出每个组的人数。从大到小顺序输出,每个数字一行。
比如,
用户输入:25
程序输出:
7
6
6
6
trainer(Num) ->
Lines = (Num+7) div 8,
LessNum = Num div Lines,
Rest = Num rem Lines,
get_each_trainer(LessNum, Rest, Lines).
get_each_trainer(_LessNum, 0, 0) ->
io:format("");
get_each_trainer(LessNum, 0, Lines) ->
io:format("~p~n", [LessNum]),
get_each_trainer(LessNum, 0, Lines - 1);
get_each_trainer(LessNum, Rest, Lines) ->
io:format("~p~n", [LessNum+1]),
get_each_trainer(LessNum, Rest - 1, Lines-1).
2.信用卡校验
当你输入信用卡号码的时候,有没有担心输错了而造成损失呢?其实可以不必这么担心,因为并不是一个随便的信用卡号码都是合法的,它必须通过Luhn算法来验证通过。
该校验的过程:
1、从卡号最后一位数字开始,逆向将奇数位(1、3、5等等)相加。
2、从卡号最后一位数字开始,逆向将偶数位数字,先乘以2(如果乘积为两位数,则将其减去9),再求和。
3、将奇数位总和加上偶数位总和,结果应该可以被10整除。
例如,卡号是:5432123456788881
逆向奇数位为 4 2 2 4 6 8 8 1 和 = 35
逆向偶数位乘以2(有些要减去9)的结果:1 6 2 6 1 5 7 7,求和 = 35。
最后 35 + 35 = 70 可以被10整除,认定校验通过。
请编写一个程序,从标准输入获得卡号,然后判断是否校验通过。
通过显示:“成功”,否则显示“失败”。
比如,
输入:356827027232780
程序输出:成功
credit(Term) ->
L = term_to_list(Term),
io:format("~p~n", [L]),
Sum = get_card_sum(reverse(L)),
case Sum rem 10 =:= 0 of
true -> {check_OK};
false -> {check_NG}
end.
term_to_list(Term) ->
case is_number(Term) of
true -> split_term(Term);
false -> []
end.
split_term(Term) ->
split_term(Term, []).
split_term(0, L) ->
L;
split_term(Term, L) ->
split_term(Term div 10, [Term rem 10|L]).
reverse(Rev) ->
reverse(Rev, []).
reverse([], Rev) ->
Rev;
reverse([H|T], Rev) ->
reverse(T, [H|Rev]).
get_card_sum(L) ->
get_card_sum(L, 0, 0, 1).
get_card_sum([], Odd, Even, _Timers) ->
io:format("Odd=~p, Even=~p~n", [Odd, Even]),
Odd+Even;
get_card_sum([H|T], Odd, Even, Times) ->
case Times rem 2 =:= 0 of
true -> case H*2 >= 10 of
true -> get_card_sum(T, Odd, Even + H*2-9, Times + 1);
false -> get_card_sum(T, Odd, Even + H*2, Times + 1)
end;
false -> get_card_sum(T, Odd+ H, Even, Times +1)
end.
3.第39级台阶
小明刚刚看完电影《第39级台阶》,离开电影院的时候,他数了数礼堂前的台阶数,恰好是39级!
站在台阶前,他突然又想着一个问题:
如果我每一步只能迈上1个或2个台阶。先迈左脚,然后左右交替,最后一步是迈右脚,也就是说一共要走偶数步。那么,上完39级台阶,有多少种不同的上法呢?
请你利用计算机的优势,帮助小明寻找答案。
要求提交的是一个整数。
注意:不要提交解答过程,或其它的辅助说明文字。
dfs() ->
put(count, 0),
dfs(0, 0),
io:format("~p~n", [get(count)]).
dfs(39, Step) ->
case Step rem 2 == 0 of
true -> addcount();
false -> []
end;
dfs(Sum, _Step)
when Sum > 39 ->
[];
dfs(Sum, Step) ->
dfs(Sum + 1, Step + 1),
dfs(Sum + 2, Step + 1).
addcount() ->
Count = get(count),
put(count, Count+1).
4.颠倒的价牌
小李的店里专卖其它店中下架的样品电视机,可称为:样品电视专卖店。
其标价都是4位数字(即千元不等)。
小李为了标价清晰、方便,使用了预制的类似数码管的标价签,只要用颜色笔涂数字就可以了(参见p1.jpg)。
这种价牌有个特点,对一些数字,倒过来看也是合理的数字。如:1 2 5 6 8 9 0 都可以。这样一来,如果牌子挂倒了,有可能完全变成了另一个价格,比如:1958 倒着挂就是:8561,差了几千元啊!!
当然,多数情况不能倒读,比如,1110 就不能倒过来,因为0不能作为开始数字。
有一天,悲剧终于发生了。某个店员不小心把店里的某两个价格牌给挂倒了。并且这两个价格牌的电视机都卖出去了!
庆幸的是价格出入不大,其中一个价牌赔了2百多,另一个价牌却赚了8百多,综合起来,反而多赚了558元。
请根据这些信息计算:赔钱的那个价牌正确的价格应该是多少?
答案是一个4位的整数,请通过浏览器直接提交该数字。
注意:不要提交解答过程,或其它辅助说明类的内容。
9088
%% ==================== 列表推导==========
negative() ->
L1 = [0,1,2,5,6,8,9],
L2 = [0,1,2,5,9,8,6],
Pos = [A*1000+B*100+C*10+D*1 || A<-L1, B<-L1, C<-L1, D<-L1],
Neg = [I*1+J*10+K*100+L*1000 || I<-L2, J<-L2, K<-L2, L<-L2],
PN2 = getPN(Pos, Neg, 2),
PN8 = getPN(Pos, Neg, 8),
% Print = fun(P, N) -> io:format("P=~p N=~p ~p ", [P, N, P-N]) end,
% [Print(P, N) || {P, N} <- PN2],
% io:format("~n~n"),
% [Print(P, N) || {P, N} <- PN8],
[{PH2, NH2, PH8, NH8} || {PH2, NH2} <- PN2, {PH8, NH8} <- PN8, (PH2 - NH2) + (PH8 - NH8) == -558].
getPN(Pos, Neg, FindWhat) ->
getPN(Pos, Neg, FindWhat, []).
getPN([], [], _FindWhat, Res) ->
Res;
getPN([PH|PT], [NH|NT], FindWhat, Res)
when PH >= 1000, NH >= 1000 ->
if
FindWhat == 2 ->
case PH - NH >= 200 andalso PH - NH =< 299 of
true -> getPN(PT, NT, FindWhat, [{PH, NH}|Res]);
false -> getPN(PT, NT, FindWhat, Res)
end;
FindWhat == 8 ->
case PH - NH =< -800 andalso PH - NH >= -899 of
true -> getPN(PT, NT, FindWhat, [{PH, NH}|Res]);
false -> getPN(PT, NT, FindWhat, Res)
end;
true -> [{0, 0}]
end;
getPN([_PH|PT], [_NH|NT], FindWhat, Res) ->
getPN(PT, NT, FindWhat, Res).
使用erlang的列表推导的功能, 简化的实现方式。 要善用列表推倒,比拿erlang 实现for循环再套fun()函数要好用多了。
如有错误请指正。
[1]: http://blog.youkuaiyun.com/junwei_yu/article/details/21980187 原网址由Java实现