任务一
分析以下函数或表达式的类型(先自己分析再程序验证):
fun all (your, base) = (*fn : int*string list->string list*)
case your of
0 => base
| _ => "are belong to us" :: all(your - 1, base)
fun funny (f, []) = 0 (*fn:(a'*int->int)*a' list->int*)
| funny (f, x::xs) = f(x, funny(f, xs))
(fn x => (fn y => x)) "Hello, World!"
(*fn : ?.X1 -> string*)
任务二
用归纳法证明ins函数和isort函数的正确性
fun ins (x, [ ]) = [x]
| ins (x, y::L) = case compare(x, y) of
GREATER => y::ins(x, L)
| _ => x::y::L
简单归纳法,0个元素成立
k-1个元素成立=>k个元素成立
(*isort : int list -> int list*)
(* REQUIRES true *)
(* ENSURES isort(L) = a sorted perm of L *)
fun isort [ ] = [ ]
| isort (x::L) = ins (x, isort L)
简单归纳法,0个元素成立
k-1个元素成立=>k个元素成立
任务三
分析下面菲波拉契函数的执行性能
fun fib n = if n<=2 then 1 else fib(n-1) + fib(n-2);
准确的来说不是O(2n),详细看下方的链接中的证明
递推时间复杂度的求解
fun fibber (0: int) : int * int = (1, 1)
| fibber (n: int) : int * int =
let val (x: int, y: int) = fibber (n-1)
in (y, x + y)
end
O(n)
任务四
定义函数divisibleByThree: int -> bool,以使当n为3的倍数时,divisibleByThree n为true,否则为false。
注意:程序中不能使用取余函数’mod’。
(* divisibleByThree : int -> bool *)
(* REQUIRES: n>=0 *)
(* ENSURES: divisibleByThree n evaluates to true if n is a multiple of 3 and to false otherwise *)
fun divisibleByThree 0=true
| divisibleByThree 1=false
| divisibleByThree 2=false
| divisibleByThree n=divisibleByThree (n-3);
任务五
函数evenP为偶数判断函数,即当且仅当该数为偶数时返回true。
其代码描述如下:
(* evenP : int -> bool )
( REQUIRES: n >= 0 )
( ENSURES: evenP n evaluates to true iff n is even. *)
fun evenP (0 : int) : bool = true
| evenP 1 = false
| evenP n = evenP (n - 2)
试编写奇数判断函数oddP: int -> bool,当且仅当该数为奇数时返回true。注意:代码不要调用函数evenP或mod。
fun oddP (0:int) :bool=false
| oddP 1 =true
| oddP n = oddP (n-2);
任务六
编写函数 interleave: int list * int list -> int list,该函数能实现两个int list数据的合并,且两个list中的元素在结果中交替出现,直至其中一个int list数据结束,而另一个int list数据中的剩余元素则直接附加至结果数据的尾部。如:
interleave([2],[4]) = [2,4]
interleave([2,3],[4,5]) = [2,4,3,5]
interleave([2,3],[4,5,6,7,8,9]) = [2,4,3,5,6,7,8,9]
interleave([2,3],[ ]) = [2,3]
fun interleave ([],B):int list=B
| interleave (A,[])=A
| interleave (x::A,y::B)=x::y::interleave(A,B);
任务七
编写函数reverse和reverse’,要求:
函数类型均为:int list->int list,功能均为实现输出表参数的逆序输出;
函数reverse不能借助任何帮助函数;函数reverse’可以借助帮助函数,时间复杂度为O(n)。
fun reverse []:int list=[]
| reverse (x::L)=(reverse L)@[x]
fun reverseHelp ([],B):int list=B
| reverseHelp (x::A,B)=reverseHelp(A,x::B);
fun reverse' L=reverseHelp(L,[]);
任务八
给定一个数组A[1…n],前缀和数组PrefixSum[1…n]定义为: PrefixSum[i] = A[0]+A[1]+…+A[i-1];
例如:PrefixSum [ ] = [ ]
PrefixSum [5,4,2] = [5, 9, 11]
PrefixSum [5,6,7,8] = [5,11,18,26]
试编写:
函数PrefixSum: int list -> int list,
要求:WPrefixSum(n) = O(n2)。(n为输入int list的长度)
fun PrefixSumHelp (x,[])=[ ]
| PrefixSumHelp (x,a::L)=(x+a)::PrefixSumHelp(x,L);
fun PrefixSum []=[]
| PrefixSum (x::L)=x::PrefixSumHelp(x,PrefixSum L);
(2) 函数fastPrefixSum: int list -> int list,
要求: WfastPrefixSum(n) =O(n).
(提示:可借助帮助函数PrefixSumHelp)
fun PrefixSum []=[]
| PrefixSum [x]=[x]
| PrefixSum (x::y::L)=x::PrefixSum(x+y::L);
fun PrefixSumHelp ([],a):int list=[a]
| PrefixSumHelp (x::L,a)=a::PrefixSumHelp(L,a+x);
fun fastPrefixSum []=[]
| fastPrefixSum (x::L)=PrefixSumHelp(L,x);