erlang 通过尾递归实现双层循环,并抽象出两向量的叉积的一般运算式

15 篇文章 0 订阅
5 篇文章 0 订阅
当我使用erlang 编程的时候,总是为没有循环而苦恼。连乘法口诀表都很难实现,想想都郁闷。
    然而当你必须要解决循环的时候,你发现了另外一条路。
    C语言:
    for(int i=1;i<10;i++)
        {
            for(int j=1;j<10;j++)
            {
                if(i>=j) printf("%d",i*j); 
            }
            printf("\n");
        }
    第一层循环和第二层的关系:
    i 为第二层的输入,j从  1 迭代到 9 
    然后 i 和 从1~9 相乘, 就是 i 和列表的相乘 ;而元素的收集代码如下:
    collect_sequence(Start_V,End_V,Result) -> if
        Start_V>End_V ->
         Result;
         true -> collect_sequence(Start_V,End_V-1,[End_V|Result])
    这是一个尾递归调用
    将相乘抽象为一个函数MapFun,那么
    filter_map(X,Start_V,End_V,MapFun) ->
         Lst = collect_sequence(Start_V,End_V,[]),
         lists:map(fun(Value) -> MapFun(X,Value) end,Lst).
     如下调用
         second:filter_map(2,1,9,fun(X,Y)->X*Y end) 就会打印 2和 1~9 相乘的列表
    如果在这个上面加一个过滤器的话就类似C语言实现的 if(i>=j)
     实现代码如下:
    filter_map(X,Start_V,End_V,MapFun,FilterFun) ->
         Lst = collect_sequence(Start_V,End_V,[]),
         Lst1 = lists:filter(fun(Value) -> FilterFun(X,Value) end,Lst),
         lists:map(fun(Value) -> MapFun(X,Value) end,Lst1).
     测试用例:
        second:filter_map(2,1,9,fun(X,Y)->X*Y end,fun(X,Y)->X>=Y end).
    然后我们实现第一层循环
arithmetic(A1_Start,A2_End,B1_Start,B2_Start,MapFun,FilterFun) ->
 if
  A1_Start>A2_End ->
   [];
  true ->
   io:format("~w~n",[filter_map(A1_Start,B1_Start,B2_Start,MapFun,FilterFun)]),
   arithmetic(A1_Start+1,A2_End,B1_Start,B2_Start,MapFun,FilterFun)
 end.
测试用例如下:
    second:arithmetic(1,9,1,9,fun(X,Y)-> X*Y end,fun(X,Y)-> X>=Y end).
元素从A1_Start 到A2_End终止,区间为[A1_Start,A1_End]
打印为:
[1]
[2,4]
[3,6,9]
[4,8,12,16]
[5,10,15,20,25]
[6,12,18,24,30,36]
[7,14,21,28,35,42,49]
[8,16,24,32,40,48,56,64]
[9,18,27,36,45,54,63,72,81]
[]
最后一个是函数的返回值,其他为九九乘法表输出
我们仅仅是想通过递归实现九九乘法表,最后我们得到了一个通用的函数:
arithmetic(A1_Start,A2_End,B1_Start,B2_Start,MapFun,FilterFun)
这个函数能够处理两组数(两个集合或者说是两个向量)的叉积,得到一个矩阵。而不仅仅是九九乘法表.

arithmetic_list(Lst1,Lst2,MapFun,FilterFun) 是以列表的方式作为输入最后输出一个运算后的矩阵的通用函数
因为没有了循环而被迫使用递归,而正因为实现的艰难发现了更加深刻的外层和内层循环的关系,而得到了一个通用函数。这和列表的通用函数lists:map,lists:filter,lists:reduce 有些类似。上帝关闭了一扇门,会为我们打开一扇窗。
代码如下:
	-module(second).
	-export ([filter_map/5]).
	-export ([collect_sequence/3]).
	-export ([arithmetic/6]).
	-export ([arithmetic_list/4]).


	%% collect_sequence(Start_V,End_V,Result)
	%% 收集 Start_V~End_V 到结果Result中 区间[Start_V,End_V]
	%% Start_V - 左边界
	%% End_V - 右边界
	collect_sequence(Start_V,End_V,Result) -> if
		Start_V>End_V ->
			Result;
		true -> collect_sequence(Start_V,End_V-1,[End_V|Result])	
	end.
	% filter_map(X,Start_V,End_V,MapFun,FilterFun)
	filter_map(X,Start_V,End_V,MapFun,FilterFun) -> 
		Lst = collect_sequence(Start_V,End_V,[]),
		Lst1 = lists:filter(fun(Value) -> FilterFun(X,Value) end,Lst),
		lists:map(fun(Value)	-> MapFun(X,Value) end,Lst1).
	%arithmetic(A1,A2,B1,B2,MapFun,FilterFun)
	%根据算法F来计算两组数,比如计算[1~9] 和 [1~9] 的乘法口诀表
	%A1_Start 第一组开始值
	%A2_End 第一组终止值
	%B1_Start 第二组开始值
	%B2_Start 第二组终止值
	%F为算法 比如 fun(X,Y) -> X*Y end.
	%% 例子:arithmetic(1,9,1,9,fun(X,Y) -> X*Y end,fun(X,Y) ->X>=Y end).

	arithmetic(A1_Start,A2_End,B1_Start,B2_Start,MapFun,FilterFun) -> 
		if
			A1_Start>A2_End ->
				[];
			true ->
				io:format("~w~n",[filter_map(A1_Start,B1_Start,B2_Start,MapFun,FilterFun)]),
				arithmetic(A1_Start+1,A2_End,B1_Start,B2_Start,MapFun,FilterFun)
		end.
		

	filter_map_list(X,Lst2,MapFun,FilterFun) ->
		TempList = lists:filter(fun(Value) -> FilterFun(X,Value) end,Lst2),
		lists:map(fun(Value) -> MapFun(X,Value) end,TempList).

	%arithmetic_list - 通过 FilterFun,并且通过MapFun来将两个集合(向量)进行运算,
	%得到一个矩阵
	%参数:Lst1 - 第一个集合,Lst2 - 第二个集合,MapFun - 两个集合预算的函数,FilterFun 过滤函数
	%例子:
	%arithmetic_list([1,2,3,4,5,6,7,8,9],[1,2,3,4,5,6,7,8,9],fun(X,Y) ->X*Y end,fun(X,Y)->X>=Y end).

	arithmetic_list([],Lst2,MapFun,FilterFun) -> [];
	arithmetic_list(Lst1,Lst2,MapFun,FilterFun) ->
		[H|T] = Lst1,
		TempLst = filter_map_list(H,Lst2,MapFun,FilterFun),
		io:format("~w~n",[TempLst]),
		arithmetic_list(T,Lst2,MapFun,FilterFun).


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值