erlang練習題

文章目錄

資料

erlong 中文手冊

闊以用來查找erlong的庫函數的用法:erlong 中文手冊

一些不同(keng)

1

好像if後面的判斷條件(guard關卡)不能是函數,case後的就行

1、將列表中的integer,float,atom轉成字符串並合併成一個字個字符串:[1,a,4.9,“sdfds”] 結果:“1a4.9sdfds”(禁用++ – append concat實現)

erl文件

-module(lpfmerge).
-export([getstr/1,to_string/1]).

getstr([])->"";
getstr([H|T])->
	if
		is_atom(H)->[atom_to_list(H)|getstr(T)];
		is_integer(H)->[integer_to_list(H)|getstr(T)];
		is_float(H)->[float_to_list(H,[{decimals,1}])|getstr(T)];	%注意這裏小數點保留一位
		is_list(H)->[H|getstr(T)]
	end.
	
to_string(L)->binary_to_list(list_to_binary(getstr(L))).

最後一句就是先轉換成 二進制文件 然後再轉換回list,不然就會成下面第四個運行代碼那樣是分開的

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\1> erl

Eshell V8.3  (abort with ^G)
1> c(lpfmerge).
{ok,lpfmerge}
2> L=[1,a,4.9,"sdfds"].
[1,a,4.9,"sdfds"]
3> lpfmerge:to_string(L).
"1a4.9sdfds"
4> lpfmerge:getstr(L).
["1","a","4.9","sdfds"]
5>

2、得到列表或元組中的指定位的元素 {a,g,c,e} 第1位a [a,g,c,e] 第1位a(禁用erlang lists API實現)

erl文件

先用2個參數的把元組都統一弄成列表 然後再處理

-module(q2).
-export([getPosVal/2]).

getPosVal([],Pos)->[];		%列表爲空
getPosVal({},Pos)->{};		%元組爲空
getPosVal(L,Pos)->
	if
		is_tuple(L)->
			getPosVal(tuple_to_list(L),Pos);	%如果是元組,就先轉換成列表
		true->
			getPosVal(L,Pos,1)
	end.
	
getPosVal([H|T],Pos,Index)when Pos==Index->H;
getPosVal([H|T],Pos,Index)->getPosVal(T,Pos,Index+1).

輸入erlong shell測試

PS D:\lpf\lpf練習題\已完成\2> erl
Eshell V10.7  (abort with ^G)
1> c(q2).
q2.erl:4: Warning: variable 'Pos' is unused
q2.erl:5: Warning: variable 'Pos' is unused
q2.erl:14: Warning: variable 'T' is unused
q2.erl:15: Warning: variable 'H' is unused
{ok,q2}
2> L=[10,20,30,40,50,60].
[10,20,30,40,50,60]
3> q2:getPosVal(L,3).
30
4>

3、根據偶數奇數過淲列表或元組中的元素(禁用API實現)

erl文件

-module(lpffilter).
-export([filter/1]).


filter([])->[];
filter({})->{};
filter([H|T])->
	if
		is_tuple(H)
			->filter(tuple_to_list(H)); %之前寫成  ->filter([tuple_to_list(H)|T]);就不對,爲啥喃?
	 
		(H rem 2)=:=0 
			->[H|filter(T)];
	true 
		->filter(T)
	end.

輸入erlong shell測試

PS D:\lpf\lpf練習題\已完成\3> erl
Eshell V8.3  (abort with ^G)
1> c(lpffilter).
{ok,lpffilter}
2> L=[1,2,3,4,5,6,7,8,{9,10,11,12},13,14,15,16].
[1,2,3,4,5,6,7,8,{9,10,11,12},13,14,15,16]
3> lpffilter:filter(L).
[2,4,6,8,10,12]
4>

4、便用匿名函數對列表奇數或偶數過淲

erl文件

-module(q4).
-export([filter/2]).
	
filter(F,[H|T])->
	case F(H) of
		true->[H|filter(F,T)];
		false->filter(F,T)
	end;
filter(F,[])->[].

輸入erlong shell測試

PS D:\lpf\lpf練習題\已完成\4> erl
Eshell V10.7  (abort with ^G)
1> c(q4).
q4.erl:16: Warning: variable 'F' is unused
{ok,q4}
2> L=[1,2,3,4,5,6,7,8].
[1,2,3,4,5,6,7,8]
3> F=fun(X)->(X rem 2) =:=0 end.
#Fun<erl_eval.7.126501267>
4> q4:filter(F,L).
[2,4,6,8]
5>

5、計算數字列表[1,2,3,4,5,6,7,8,9]索引N到M的和

erl文件

我是寫的for循環來做的,計算的是[I,J)[I,J) 左閉右開區間的和

用if判斷:

-module(lpffor).
-export([for/4]).

for(Index,I,J,[H|T])->
	if 
		(Index>=I) and (Index<J)
			->H+for(Index+1,I,J,T);
	true 
		->for(Index+1,I,J,T)
	end;
for(Index,I,J,[])->0.

用 when 判斷:

-module(lpffor).
-export([for/4]).

for(Index,I,J,[H|T]) when (Index>=I) , (Index<J)
	->H+for(Index+1,I,J,T);
for(Index,I,J,[H|T]) 
	->for(Index+1,I,J,T);
for(Index,I,J,[])
	->0.

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\5> erl
Eshell V8.3  (abort with ^G)
1> c(lpffor).
lpffor.erl:11: Warning: variable 'I' is unused
lpffor.erl:11: Warning: variable 'Index' is unused
lpffor.erl:11: Warning: variable 'J' is unused
{ok,lpffor}
2> L=[10,20,30,40,50,60,70,80,90].
[10,20,30,40,50,60,70,80,90]
3> lpffor:for(1,2,7,L).
200
4>

6、查詢List1是爲List2的前綴(禁用string API實現)

erl文件

這是看的別人的代碼,原來export中只寫在外面調用的函數就行,裏面用到的其他函數可以不寫,比如這裏用了is_prefix2

還有就是,要想對列表操作的話,參數就要寫成,(H|T)這種,這樣寫的話又不能表示整體的這個列表了,所以這裏要弄兩個

-module(q6).
-export([is_prefix/2]).

is_prefix([], L2) -> false;
is_prefix([], []) -> false;
is_prefix(L1, L2) ->
	if
		length(L1) >= length(L2) 
			-> false;
		true 
			-> is_prefix2(L1,L2)
end.

is_prefix2([H1|T1],[H2|T2]) ->
	if
		(H1 == H2 andalso T1 == [] ) 
			-> true;
		H1 == H2  
			-> is_prefix2(T1,T2);
		H1 /= H2 
			-> false;
		T1 == [] 
			-> true
	end.

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\6> erl
Eshell V8.3  (abort with ^G)
1> c(q6).
q6.erl:4: Warning: variable 'L2' is unused
q6.erl:5: Warning: this clause cannot match because a previous clause at line 4 always matches
{ok,q6}
2> L1=[1,2,3].
[1,2,3]
3> L2=[1,2,3,4,5].
[1,2,3,4,5]
4> L3=[2,3,4].
[2,3,4]
5> q6:is_prefix(L1,L2).
true
6>

7、逆轉列表或元組(禁用lists API實現)

erl文件

-module(lpfReverse).
-export([lpfreverse/1,lpfreverse/2]).

lpfreverse(L)->lpfreverse(L,[]).
lpfreverse([H|T],Reversed)->lpfreverse(T,[H|Reversed]);
lpfreverse([],Reversed)->Reversed.

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\7> erl
Eshell V8.3  (abort with ^G)
1> c(lpfReverse).
{ok,lpfReverse}
2> L=[1,3,5,7,9].
[1,3,5,7,9]
3> lpfReverse:lpfreverse(L).
[9,7,5,3,1]
4>

8、對列表進行排序

erl文件

書上的快排例子,erlong寫快排好簡潔呀ヽ( ̄▽ ̄)ノ

-module(lpfsort).
-export([sort/1]).

sort([])->[];
sort([Mid|T])
	->sort([X||X<-T , X<Mid]) ++ [Mid] ++ sort([X||X<-T , X>=Mid]).

9、對數字列表進行求和再除以指定的參數,得到商餘

erl文件

-module(q9).
-export([get_sum_rem/2]).

get_sum_rem(L,Num)
	->{sum(L)/Num,sum(L) rem Num}.

sum([H|T])->H+sum(T);
sum([])->0.


輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\9> erl
Eshell V8.3  (abort with ^G)
1> c(q9).
q9.erl: no such file or directory
error
2> c(q9).
{ok,q9}
3> L=[10,20,30,40,50].
[10,20,30,40,50]
4> q9:get_sum_rem(L,7).
{21.428571428571427,3}
5> 150/7.
21.428571428571427
6>

10、獲得當前的堆棧???

這個是直接在shell裏寫

大概就是寫一個會產生錯誤的函數,比如 generate_exception(1),因爲看下面錯誤信息的第一行 shell_undef ,意思是沒有定義這個函數

然後就會報錯,調用get_stacktrace()就能得到棧的信息了

PS D:\lpf\lpf練習題\未完成\10> erl
Eshell V8.3  (abort with ^G)
1> try generate_exception(1)
catch
error:X->
{X,erlang:get_stacktrace()}

end.
{{shell_undef,generate_exception,1,[]},
 [{shell,shell_undef,2,[{file,"shell.erl"},{line,1061}]},
  {erl_eval,local_func,6,[{file,"erl_eval.erl"},{line,562}]},
  {erl_eval,try_clauses,8,[{file,"erl_eval.erl"},{line,904}]},
  {shell,exprs,7,[{file,"shell.erl"},{line,686}]},
  {shell,eval_exprs,7,[{file,"shell.erl"},{line,641}]},
  {shell,eval_loop,3,[{file,"shell.erl"},{line,626}]}]}
2>

好像是必須要error一哈才得行,直接用這個函數沒得反應得
在這裏插入圖片描述

11、獲得列表或元組中的最大最小值(禁用API實現)

這裏是最大值最小值分開的:

erl文件

-module(lpfMaxMin).
-export([lpfmax/1,lpfmin/1]).

lpfmax([H|T])->lpfmax(T,H).				%這裏爲啥要用. 因爲是調用2個參數的lpfmax了,不屬於原來的了

lpfmax([],Res)->Res;					%只剩一個
lpfmax([H|T],Res)when H>Res->lpfmax(T,H);	%比Res大就選他
lpfmax([H|T],Res)->lpfmax(T,Res).			%不然不選


lpfmin([H|T])->lpfmin(T,H).

lpfmin([],Res)->Res;
lpfmin([H|T],Res)when H<Res->lpfmin(T,H);
lpfmin([H|T],Res)->lpfmin(T,Res). 

輸入erlong shell測試

PS D:\lpf\lpf練習題\已完成\11> erl
Eshell V8.3  (abort with ^G)
1> c(lpfMaxMin).
lpfMaxMin.erl:8: Warning: variable 'H' is unused
lpfMaxMin.erl:17: Warning: variable 'H' is unused
{ok,lpfMaxMin}
2> L=[5,9,8,7,25,3,2,1].
[5,9,8,7,25,3,2,1]
3> lpfMaxMin:lpfmax(L).
25
4> lpfMaxMin:lpfmin(L).
1
5>

然後是一起返回的寫法:

erl文件

-module(q11).
-export([max_min/1]).

max_min([H|T])->max_min([H|T],H,H). %最開始寫成max_min(L)->max_min(L,Max,Min) 會報錯說 :variable 'Max' is unbound以及variable 'Min' is unbound

max_min([],Max,Min)->{Max,Min};
max_min([H|T],Max,Min)->
	if
		(H>Max) and (H<min)
			->max_min(T,H,H);
		(H>Max)
			->max_min(T,H,Min);
		(H<Min)
			->max_min(T,Max,H);
		true
			->max_min(T,Max,Min)
	end.

輸入erlong shell測試

PS D:\lpf\lpf練習題\已完成\11> erl
Eshell V8.3  (abort with ^G)
1> c(q11).
q11.erl:4: variable 'Max' is unbound
q11.erl:4: variable 'Min' is unbound
error
2> c(q11).
{ok,q11}
3> L=[5,9,8,7,25,3,2,1].
[5,9,8,7,25,3,2,1]
4> q11:max_min(L).
{25,1}
5>

12、查找元素在元組或列表中的位置

erl文件

-module(q12).
-export([get_index/2]).

get_index(L, Tofind) ->get_index(L, Tofind, 1).	%調用3個參數的get_index

get_index([],Tofind,Index)->null;						%遞歸邊界
get_index([H|T],Tofind,Index)->
	if H==Tofind
			->Index;
		true
			->get_index(T,Tofind,Index+1)
	end.

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\12> erl
Eshell V8.3  (abort with ^G)
1> c(q12).
q12.erl:6: Warning: variable 'Index' is unused
q12.erl:6: Warning: variable 'Tofind' is unused
{ok,q12}
2> L=[10,20,{33,34,35},40,50].
[10,20,{33,34,35},40,50]
3> q12:get_index(L,{33,34,35}).
3
4>
q12:get_index(L,40).
4
5>

14、判斷A列表([3,5,7,3])是否在B列表([8,3,5,3,5,7,3,9,3,5,6,3])中出現,出現則輸出在B列表第幾位開始

erl文件

-module(q14).
-export([is_in/2]).

is_in(L1,L2)->is_in(L1,L2,1,1).

is_in([],L2,Index1,Index2)->false;
is_in(L1,[],Index1,Index2)->false;
is_in([H1|T1],[H2|T2],Index1,Index2)->
	if
		(H1==H2) and (T1==[])
			->{true,Index2-Index1+1};			%完全匹配成功
		H1==H2
			->is_in(T1,T2,Index1+1,Index2+1);	%部分匹配成功
		true
			->is_in([H1|T1],T2,Index1,Index2+1)	%沒有匹配成功
	end.

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\14> erl
Eshell V8.3  (abort with ^G)
1>
c(q14).
q14.erl:6: Warning: variable 'Index1' is unused
q14.erl:6: Warning: variable 'Index2' is unused
q14.erl:6: Warning: variable 'L2' is unused
q14.erl:7: Warning: variable 'Index1' is unused
q14.erl:7: Warning: variable 'Index2' is unused
q14.erl:7: Warning: variable 'L1' is unused
{ok,q14}
2> L1=[3,5,7,3].
[3,5,7,3]
3> L2=[8,3,5,3,5,7,3,9,3,5,6,3].
[8,3,5,3,5,7,3,9,3,5,6,3]
4> q14:is_in(L1,L2).
{true,4}
5> q14:is_in(L2,L1).
false
6>

15、{8,5,2,9,6,4,3,7,1} 將此元組中的奇數進行求和後除3的商(得值A),並將偶數求和後剩3(得值B),然後求A+B結果

erl文件

-module(q15).
-export([lpfsum/1]).

lpfsum(L)->lpfsum(tuple_to_list(L),0,0). %注意輸入進來的是元組,還要轉換成列表

lpfsum([],Odd,Even)->(Odd/3+Even*3);
lpfsum([H|T],Odd,Even)->
	if 
		(H rem 2)==1
			->lpfsum(T,Odd+H,Even);
		true
			->lpfsum(T,Odd,Even+H)
	end.

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\15> erl
Eshell V8.3  (abort with ^G)
1> c(q15).
{ok,q15}
2> L={8,5,2,9,6,4,3,7,1}.
{8,5,2,9,6,4,3,7,1}
3> q15:lpfsum(L).
68.33333333333333
4>

16、在shell中將unicode碼顯示爲中文???

17、傳入列表L1=[K|]、L2=[V|]、L3=[{K,V}|_],L1和L2一一對應,L1爲鍵列表,L2爲值列表,L3存在重複鍵,把L3對應鍵的值加到L2???

思路還是用的庫函數 proplists:append_values 來從L3中找重複的鍵值

erl文件

-module(q17).
-export([key_val/3]).



key_val(L1,L2,L3)->key_val(L1,L2,L3,[]).

key_val([],[],L3,Res)->io:format("Res=~w~n",[Res]),Res;	%這裏不懂爲什麼,都已經得到最後的答案Res了,但是爲啥返回的Res是個奇怪的東西"<61"
key_val([H1|T1],[H2|T2],L3,Res)->
	
	TP1=proplists:append_values(H1,L3),		%用庫函數從L3中查找這個key並且得到所有的值
	TP2=lists:sum(TP1),						%返回的是列表,所以要求和
	%io:format("TP2=~w~n",[TP2]),			%試着打印出來看對不對
	key_val(T1,T2,L3,lists:append(Res,[H2+TP2])).			%加上L2中的值
	

輸入erlong shell測試

不知道爲啥會有個奇怪的返回值 “<61”

PS D:\lpf\lpf練習題\未完成\17> erl
Eshell V10.7  (abort with ^G)
1> c(q17).
q17.erl:8: Warning: variable 'L3' is unused
{ok,q17}
2> L1=[a,b,c].
[a,b,c]
3> L2=[10,20,30].
[10,20,30]
4> L3=[{a,23},{b,34},{a,27},{c,78}].
[{a,23},{b,34},{a,27},{c,78}]
5> q17:key_val(L1,L2,L3).
Res=[60,54,108]
"<6l"
6>

18、刪除或查詢元組中第N個位置的值等於Key的tuple(禁用lists API實現)

erl文件

-module(q18).
-export([select/3,delete/3]).

select(L,N,Key)->select(L,N,Key,1).
select([{K,V}|T],N,Key,Index)->
	if
		(K==Key) and (Index==N)->
			{K,V};
		(K==Key)->
			select(T,N,Key,Index+1);
		true->
			select(T,N,Key,Index)
	end.
	
delete(L,N,Key)->delete(L,N,Key,1).
delete([{K,V}|T],N,Key,Index)->
	if
		(K==Key) and (Index==N)->
			T;								%找到就返回後面的列表,當前的數不要了
		(K==Key)->
			[{K,V}|delete(T,N,Key,Index+1)];
		true->
			[{K,V}|delete(T,N,Key,Index)]
	end.

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\18> erl
Eshell V10.7  (abort with ^G)
1> c(q18).
{ok,q18}
2> L=[{a,10},{b,21},{a,10},{b,22},{b,23},{c,30}].
[{a,10},{b,21},{a,10},{b,22},{b,23},{c,30}]
3> q18:select(L,3,b).
{b,23}
4> q18:delete(L,3,b).
[{a,10},{b,21},{a,10},{b,22},{c,30}]
5>

19、對一個字符串按指定符字劈分(禁用string API實現)

erl文件

-module(q19).
-export([string_div/2]).

string_div(Str,[X])->string_div(Str,[X],[],[]).


%假如調用函數的時候是:
%string_div("abcabcabc","b")
%此時"abcabcabc"=[97,98,99,97,98,99,97,98,99]
%"b"=[98]
%所以H和X纔是同樣類型的才能比較
string_div([H|T],[X],Res1,Res2)->		%Res1是保存最後的答案,Res2是保存沒有逗號連着的字符串
	if H/=X->
		string_div(T,[X],Res1,Res2++[H]);
	true->
		string_div(T,[X],Res1++[Res2],[])
	end;
string_div([],[X],Res1,Res2)->			%遞歸邊界
	Res1++[Res2].

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\19> erl
Eshell V10.7  (abort with ^G)
1> c(q19).
q19.erl:20: Warning: variable 'X' is unused
{ok,q19}
2> q19:string_div("abcabcabc","b").
["a","ca","ca","c"]
3>

對字符串的理解

PS D:\lpf\lpf練習題\未完成\19> erl
Eshell V10.7  (abort with ^G)
1>
L1=["ab","c"].
["ab","c"]
2> L2=["de"].
["de"]
3>

[L3]=L2.				%把列表L2裏的元素取出來,放到L3中
["de"]
4> L3.					%L3就不是列表了
"de"
5>


L1++L2.					%列表與列表相++,直接會用逗號相隔開
["ab","c","de"]
6>

L1++L3.					%由於L3不是列表了,所以看成列表與單個的元素相++
["ab","c",100,101]
7>

看一個列表++不同的數的效果
L1++100
L1++[100]
L1++[[100]]
L1++[[[100]]]

L1=["ab","c"].
["ab","c"]
14>

L1++100.
["ab","c"|100]			%++的不是列表,只是單個的元素
15>

L1++[100].
["ab","c",100]			%++的是列表,正常操作
16>

L1++[[100]].
["ab","c","d"]			%誒~多弄一層括號就變成字符串了
17>

L1++[[[100]]].
["ab","c",["d"]]		%再多弄一層就沒效果了

20> L1++[100,101].
["ab","c",100,101]

21> L1++[[100,101]].	%這樣"d","e"就能連起了
["ab","c","de"]

22> L1++[[100],[101]].	%這樣"d","e"就不會連起
["ab","c","d","e"]

函數中字符串列表

在函數中好像又不一樣了
Res++H
Res++[H]
Res++[[H]]
這三者的不同之處:

-module(strtest).
-export([str1/1,str2/1,str3/1]).
str1(Str)->str1(Str,[]).

str1([],Res)->Res;
str1([H|T],Res)->
	str1(T,Res++H).				%H是個元素,不能直接與列表++
%輸出結果:
% ** exception error: bad argument
     % in operator  ++/2
        % called as 97 ++ 98
     % in call from strtest:str1/2 (strtest.erl, line 7)



	 
str2(Str)->str2(Str,[]).

str2([],Res)->Res;
str2([H|T],Res)->
	str2(T,Res++[H]).			%[H]就變成了單元素的列表,可以++
%輸出結果:"abcde"
	
	
	
	
	
	
str3(Str)->str3(Str,[]).

str3([],Res)->Res;
str3([H|T],Res)->
	str3(T,Res++[[H]]).			%這。。。。。
%輸出結果:["a","b","c","d","e"]

PS D:\lpf\lpf練習題\未完成\19> erl
Eshell V10.7  (abort with ^G)
1> c(strtest).
{ok,strtest}
2> Str="abcde".
"abcde"
3>

strtest:str1(Str).
** exception error: bad argument
     in operator  ++/2
        called as 97 ++ 98
     in call from strtest:str1/2 (strtest.erl, line 7)
4>

strtest:str2(Str).
"abcde"
5>

strtest:str3(Str).
["a","b","c","d","e"]
6>

20、合併多個列表或元組

21、{5,1,8,7,3,9,2,6,4} 將偶數剩以它在此元組中的偶數位數, 比如,8所在此元組中的偶數位數爲1,2所在此元組中的偶數位數爲2

erl文件

-module(q21).
-export([multiEven/1]).

multiEven(L)->binary_to_list(list_to_binary(multiEven(L,1))).	%不轉成二進制再轉回來的話就會有很多中括號,我也不知道該怎麼辦

multiEven([],Index)->[];
multiEven([H|T],Index)->
	if
		(H rem 2)==0
			->[H*Index,multiEven(T,Index+1)];
		true
			->multiEven(T,Index)
	end.

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\21> erl
Eshell V8.3  (abort with ^G)
1> c(q21).
q21.erl:6: Warning: variable 'Index' is unused
{ok,q21}
2> L=[5,1,8,7,3,9,2,6,4].
[5,1,8,7,3,9,2,6,4]
3> q21:multiEven(L).
[8,4,18,16]
4>

22、排序[{“a”,5},{“b”,1},{“c”,8},{“d”,7},{“e”,3},{“f”,9},{“g”,2},{“h”,6},{“i”,4}], 以元組的值進行降序 優先用API

erl文件

-module(q22).
-export([sort/1]).

sort(L)->lists:keysort(2,L).	%用lists裏面的keysort,好像只能升序

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\22> erl
Eshell V8.3  (abort with ^G)
1>
c(q22).
{ok,q22}
2> L=[{"a",5},{"b",1},{"c",8},{"d",7},{"e",3},{"f",9},{"g",2},{"h",6},{"i",4}].
[{"a",5},
 {"b",1},
 {"c",8},
 {"d",7},
 {"e",3},
 {"f",9},
 {"g",2},
 {"h",6},
 {"i",4}]
3> q22:sort(L).
[{"b",1},
 {"g",2},
 {"e",3},
 {"i",4},
 {"a",5},
 {"h",6},
 {"d",7},
 {"c",8},
 {"f",9}]
4>

23、{8,5,2,9,6,4,3,7,1} 將此元組中的奇數進行求和

erl文件

-module(q23).
-export([sumT/1]).

sumT(L)->sum(tuple_to_list(L)).	%元組換成列表
sum([])->0;
sum([H|T])->
	if
		(H rem 2)==1
			->H+sum(T);
		true
			->sum(T)
	end.

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\23> erl
Eshell V8.3  (abort with ^G)
1> c(q23).
{ok,q23}
2> L={8,5,2,9,6,4,3,7,1}.
{8,5,2,9,6,4,3,7,1}
3> q23:sumT(L).
25
4>

25、刪除列表或元組中全部符合指定鍵的元素

erl文件

%lists:keydelete 是刪除某一個,這個函數是刪除所有的,就是遍歷一哈嘛
-module(q25).
-export([key_delete_all/2]).
key_delete_all(L,Key)->key_delete_all(L,Key,L).

key_delete_all([],Key,L)->L;
key_delete_all([{K,V}|T],Key,L)->
	if
		K==Key->
			key_delete_all(T,Key,lists:keydelete(Key,1,L));
		true->
			key_delete_all(T,Key,L)
	end.

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\25> erl
Eshell V10.7  (abort with ^G)
1> c(q25).
q25.erl:6: Warning: variable 'Key' is unused
q25.erl:7: Warning: variable 'V' is unused
{ok,q25}
2> T = [{a, 1}, {b, 2},{b,2}, {c, 3}, {d, 4}].
[{a,1},{b,2},{b,2},{c,3},{d,4}]
3> q25:key_delete_all(T,b).
[{a,1},{c,3},{d,4}]
4>

26、替換列表或元組中第一個符合指定鍵的元素

erl文件

%這個難道不是直接用庫函數 lists:keyreplace 嘛???
-module(q26).
-export([replace_one/2]).
replace_one(L,{K,V})->lists:keyreplace(K,1,L,{K,V}).

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\26> erl
Eshell V10.7  (abort with ^G)
1> c(q26).
{ok,q26}
2> T = [{a, 1}, {b, 2},{b,2}, {c, 3}, {d, 4}].
[{a,1},{b,2},{b,2},{c,3},{d,4}]
3> q26:replace_one(T,{b,99}).
[{a,1},{b,99},{b,2},{c,3},{d,4}]
4>

27、將指定的元素插入到列表中指定的位置,列表中後面的元素依次向後挪動

erl文件

-module(q27).
-export([insert/3]).

insert(L,Pos,Val)->insert(1,[],L,Pos,Val).

insert(Index,Pre,[H|T],Pos,Val)->
	if 
		Pos==0->
			[Val]++[H]++T;						%加在最前面
		Index==Pos->
			Pre++[H]++[Val]++T;					%這裏H和Val都是一個元素,所以要加中括號表示列表才能使用++操作
		true->
			insert(Index+1,Pre++[H],T,Pos,Val)	%這裏的H同樣
	end.

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\27> erl
Eshell V10.7  (abort with ^G)
1> c(q27).
{ok,q27}
2> L=[1,2,3,4,5].
[1,2,3,4,5]
3> q27:insert(L,0,99).
[99,1,2,3,4,5]
4> q27:insert(L,3,99).
[1,2,3,99,4,5]
5>

28、對[6,4,5,7,1,8,2,3,9]進行排序(降序–冒泡排序)或API排序

選擇排序

erl文件

-module(q28).
-export([sort/1]).

sort(L) ->sort([], L).

sort(NewList,[]) ->NewList;	
sort(NewList, L) ->sort(NewList ++ [lists:min(L)], lists:delete(lists:min(L), L)).%選擇最小的放在前面

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\28> erl
Eshell V10.7  (abort with ^G)
1> c(q28).
{ok,q28}
2> L=[6,4,5,7,1,8,2,3,9].
[6,4,5,7,1,8,2,3,9]
3> q28:sort(L).
[1,2,3,4,5,6,7,8,9]
4>

冒泡排序

erl文件

-module(q28).
-export([sort/1]).
sort(L)->for1(L,length(L)).

for1(L,0)->L;
for1(L,N)->for1(for2(L),N-1).	%調用N次for2,相當於第一層循環

for2([L])->[L];					%這句就是隻有一個元素的時候哇
for2([H1,H2|T])->
	if
		H1>H2->
			[H2|for2([H1|T])];
		true->
			[H1|for2([H2|T])]
	end.

30、移除元組或列表中指定位置的元素

erl文件

-module(q30).
-export([delete/2]).

delete(L,Pos)->delete(L,Pos,1).

delete([H|T],Pos,Index)->
	if
		Pos==Index->
			T;			%這裏的T是個列表,如果寫成[T],答案就變成[1,2,[4,5,6]],就會多中括號
		true->
			[H|delete(T,Pos,Index+1)]
	end.

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\30> erl
Eshell V10.7  (abort with ^G)
1> c(q30).
{ok,q30}
2> L=[1,2,3,4,5,6].
[1,2,3,4,5,6]
3> q30:delete(L,3).
[1,2,4,5,6]
4>

31、指定列表第幾位之後的數據進行反轉。如:指定[2,3,5,6,7,2]第3位後進行反轉(謝絕一切API(lists:concat,lists:reverse等)、++、–方法)

erl文件

-module(q31).
-export([reverse/2]).

reverse(L,N)->reverse(L,N,1,[]).
reverse([H|T],N,Index,Res)->
	if 
		Index<N->								
			[H|reverse(T,N,Index+1,[Res|H])];	%要用中括號括起來,不然前面一節就沒了
		true->
			[H|reverse_all(T)]					
	end.
	
	
reverse_all(L)->reverse_all(L,[]).	%這一段是全部翻轉的代碼
reverse_all([],Res)->Res;
reverse_all([H|T],Res)->
	reverse_all(T,[H|Res]).

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\31> erl
Eshell V10.7  (abort with ^G)
1> c(q31).
{ok,q31}
2> L=[1,2,3,4,5,6].
[1,2,3,4,5,6]
3> q31:reverse(L,3).
[1,2,3,6,5,4]
4>

32、使用“匿名函數”檢查列表的每個元素是否符合傳入的最大最小值(都是閉區間)

1

我還以爲是匿名函數作爲參數傳進去呢,原來就說用匿名函數判斷一哈而已
話說怎麼把匿名函數作爲參數傳進去呢?只知道lists:map()這個函數闊以接受匿名函數,但是那是庫函數啊

erl文件

-module(q32).
-export([valid_max_min/3]).

valid_max_min([],Min,Max)->true;
valid_max_min([H|T],Min,Max)->
	F=fun(X,Min,Max)->(X>=Min) andalso (X=<Max)end,
	
	case F(H,Min,Max) of
		false->
			false;
		true->
			valid_max_min(T,Min,Max)
	end.

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\32> erl
Eshell V10.7  (abort with ^G)
1> c(q32).
q32.erl:4: Warning: variable 'Max' is unused
q32.erl:4: Warning: variable 'Min' is unused
q32.erl:6: Warning: variable 'Max' shadowed in 'fun'
q32.erl:6: Warning: variable 'Min' shadowed in 'fun'
{ok,q32}
2> L=[1,2,3,4,5,6].
[1,2,3,4,5,6]
3> q32:valid_max_min(L,1,6).
true
4>
q32:valid_max_min(L,2,6).
false
5>
q32:valid_max_min(L,1,5).
false
6>
q32:valid_max_min(L,0,7).
true
7>

爲什麼case of 換成 if 就說 illegal guard expression
難道是 if 後面不能判斷函數???

2

這個是不用匿名函數的

-module(q32).
-export([valid_max_min/3]).
valid_max_min([],Min,Max)->true;
valid_max_min([H|T],Min,Max)->
	if
		H<Min->
			false;
		H>Max->
			false;
		true->
			valid_max_min(T,Min,Max)
	end.

3.原來闊以匿名函數傳參進去(`・ω・´)

erl文件

%匿名函數爲:F=fun(X,Min,Max)->(X>=Min) andalso (X=<Max)end,

-module(qqq32).
-export([valid_max_min/4]).

valid_max_min([],Min,Max,F)->true;
valid_max_min([H|T],Min,Max,F)->
	case F(H,Min,Max) of
		false->
			false;
		true->
			valid_max_min(T,Min,Max,F)
	end.

輸入erlong shell測試

PS D:\lpf\lpf練習題\已完成\32> erl
Eshell V10.7  (abort with ^G)
1> c(qqq32).
qqq32.erl:4: Warning: variable 'F' is unused
qqq32.erl:4: Warning: variable 'Max' is unused
qqq32.erl:4: Warning: variable 'Min' is unused
{ok,qqq32}
2> L=[1,2,3,4,5,6].
[1,2,3,4,5,6]
3> F=fun(X,Min,Max)->(X>=Min) andalso (X=<Max)end.
#Fun<erl_eval.19.126501267>
4> qqq32:valid_max_min(L,1,6,F).
true
5>

qqq32:valid_max_min(L,2,6,F).
false
6>

qqq32:valid_max_min(L,1,5,F).
false
7>

qqq32:valid_max_min(L,0,7,F).
true
8>

33、獲得列表或元組的最大最小值

用庫函數

erl文件

-module(q33).
-export([max_min/1]).
max_min(L)->[lists:max(L),lists:min(L)].

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\33> erl
Eshell V10.7  (abort with ^G)
1> c(q33).
{ok,q33}
2> q33:max_min([1,2,3,4,5,33,44,55]).
[55,1]
3>

34、成生指定數量元組,每個元素爲隨機integer元素, 元素不能有相同的

erl文件

-module(q34).
-export([lpfrand/1]).

lpfrand(N)->lpfrand(N,[]).

lpfrand(0,L)->L;
lpfrand(N,L)->
	X=rand:uniform(100),
	A=lists:member(X,L),
	if
		(A==false)
			->lpfrand(N-1,lists:append(L,[X]));	%如果X不在列表裏,就把這個元素加進去
		true
			->lpfrand(N,L)
	end.

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\34> erl
Eshell V10.7  (abort with ^G)
1> c(q34).
{ok,q34}
2> q34:lpfrand(10).
[48,3,98,72,60,33,73,52,44,17]
3>

不重複的隨機數有個不好理解的算法:這裏是相關博客

35、對一個int進行位移操作,取出0到16位的數據,16到32位的數據,輸出這兩個數

erl文件

-module(q35).
-export([bin/1]).

bin(Number)->{(Number band 16#ffff0000) bsr 16,Number band 16#0000ffff}.

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\35> erl
Eshell V8.3  (abort with ^G)
1> c(q35).
{ok,q35}
2> q35:bin(123456789).
{1883,52501}
3>

36、輸入A(元子列表),B(數值列表)兩個相同長度的參數進行隨機匹配(要求字母爲Key,數值爲Value),支持指定的Key和Value在一組

erl文件

-module(q36).
-export([match/2]).

match(L1,L2)->match(L1,L2,1).

match(L1,L2,Index)when Index=<length(L1)->
		Len=length(L1),
		Pos1=rand:uniform(Len),			%產生隨機數
		X1=lists:nth(Pos1,L1),			%從L1中選
		Pos2=rand:uniform(Len),
		X2=lists:nth(Pos2,L2),
		[{X1,X2}|match(L1,L2,Index+1)];
match(L1,L2,Index)->[].					%這句話用來遞歸結束,必須要,因爲上面條件不滿足的話就不會返回東西

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\36> erl
Eshell V10.7  (abort with ^G)
1> c(q36).
q36.erl:14: Warning: variable 'Index' is unused
q36.erl:14: Warning: variable 'L1' is unused
q36.erl:14: Warning: variable 'L2' is unused
{ok,q36}
2> L1=[a,b,c].
[a,b,c]
3> L2=[10,20,30].
[10,20,30]
4> q36:match(L1,L2).
[{c,10},{b,20},{c,10}]
5> q36:match(L1,L2).
[{a,10},{c,30},{a,20}]
6> q36:match(L1,L2).
[{c,30},{a,30},{c,10}]
7> q36:match(L1,L2).
[{b,30},{b,10},{c,10}]
8> q36:match(L1,L2).
[{c,10},{b,20},{a,10}]
9>

37、對相同類型的數據進行拼接,如binary(<<1,2>><<3,4>> =<<1,2,3,4>>) tuple({a,b},{c} ={a,b,c}) list([10],[20] =[10,20])

erl文件

%思路就是都轉換成列表來加
-module(q37).
-export([lpfjoin/1]).

lpfjoin(L)->lpfjoin(L,[],[],[]).

lpfjoin([],Binary,[],[])->list_to_binary(Binary);
lpfjoin([],[],Tuple,[])->list_to_tuple(Tuple);
lpfjoin([],[],[],List)->List;
lpfjoin([H|T],Binary,Tuple,List)->
	if
		is_binary(H)->
			Hb=binary_to_list(H),	%轉換成list
			lpfjoin(T,Binary++[Hb],Tuple,List);
		(is_tuple(H))->
			Ht=tuple_to_list(H),	%轉換成list
			lpfjoin(T,Binary,Tuple++Ht,List);	
		true
			->lpfjoin(T,Binary,Tuple,List++H)	%這裏的H以及上面的Hb,Ht都已經是列表了,所以++的時候不用再加中括號
	end.

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\37> erl
Eshell V10.7  (abort with ^G)
1> c(q37).
{ok,q37}
2>
B=[<<1,2>>,<<3,4>>].
[<<1,2>>,<<3,4>>]
3> q37:lpfjoin(B).
<<1,2,3,4>>
4>

T=[{a,b},{c}].
[{a,b},{c}]
5> q37:lpfjoin(T).
{a,b,c}
6>

L=[[10],[20]].
["\n",[20]]
7> q37:lpfjoin(L).
[10,20]
8>

38、將列表中相同key的值進行合併,[{a,1},{b,2},{c,3},{b,4},{b,5},{c,6},{d,7},{d,8}]

erl文件

%思路就是把key和val分別裝入KeyList,ValList,然後再合併
-module(q38).
-export([lpfmix/1]).

lpfmix(L)->lpfmix(L,[],[]).

mix([],[],Res)->Res;
mix([Hk|Tk],[Hv|Tv],Res)->
	mix(Tk,Tv,Res++[{Hk,Hv}]).	%合併到Res中

lpfmix([],KeyList,ValList)->mix(KeyList,ValList,[]);
lpfmix([{K,V}|T],KeyList,ValList)->
	X=lists:member(K,KeyList),
	if
		X==true->
			lpfmix(T,KeyList,ValList);	%如果K在KeyList列表裏面,就不管
		true->
			TP1=proplists:append_values(K,T),	%KeyList裏沒有的話,就把所以鍵值爲K的提取出來,返回是個列表
			TP2=lists:sum(TP1)+V,					%把返回的這個列表求和,並且加上當前K的鍵值V
			lpfmix(T,KeyList++[K],ValList++[TP2])		%然後分別加進去
	end.

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\38> erl
Eshell V10.7  (abort with ^G)
1> c(q38).
{ok,q38}
2> L=[{a,1},{b,2},{c,3},{b,4},{b,5},{c,6},{d,7},{d,8}].
[{a,1},{b,2},{c,3},{b,4},{b,5},{c,6},{d,7},{d,8}]
3> q38:lpfmix(L).
[{a,1},{b,11},{c,9},{d,15}]
4>

39、Erlang程序設計(第2版)中5.3節的count_characters方法有錯,自行修改證

在這裏插入圖片描述

erl文件

按道理來說這樣應該是對的,

-module(q39).
-export([count_characters/1]).

count_characters(Str)->count_characters(Str,#{}).

count_characters([], X) ->X;
count_characters([H|T], #{H=>N}=X) ->
	count_characters(T,X#{H:=N+1});		%如果匹配上了,就說明有,就要把N更新成N+1
count_characters([H|T],X)->
	count_characters(T,X#{H=>1}).		%不然就增加這個映射

但是我的映射不能模式匹配,也就是說會出現下面這種情況,說不合法的匹配 (illegal pattern)

PS D:\lpf\lpf練習題\未完成\39> erl
Eshell V10.7  (abort with ^G)
1> M1=#{a=>10,b=>20}.
#{a => 10,b => 20}
2> #{a=>X}=M1.
* 1: illegal pattern
3>

然後看其他童鞋寫的並沒有用模式匹配這種方法,用的是maps裏的函數

-module(q39).
-export([count_characters/1]).

count_characters(Str)->count_characters(Str,#{}).

count_characters([], M) ->M;
count_characters([H|T], M) ->
	case maps:is_key(H,M)of									%看H是不是M中的key
		false ->
			count_characters(T, maps:put(H,1,M));			%如果不是,就在M中增加 H=>1 一個映射
		true  -> 
			Count = maps:get(H,M),							%獲得當前的映射的val
			count_characters(T, maps:update(H,Count+1,M))	% H=>Count 這個 映射更新成 H=>Count+1
	end.

輸入erlong shell測試

PS D:\lpf\lpf練習題\未完成\39> erl
Eshell V10.7  (abort with ^G)
1> c(q39).
{ok,q39}
2> q39:count_characters("hello").
#{101 => 1,104 => 1,108 => 2,111 => 1}
3>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章