习题来自于这里的公开课 https://class.coursera.org/progfun-2012-001/
1. Exercise 1: Pascal’s Triangle
The following pattern of numbers is called Pascal’s triangle.
1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 ...
The numbers at the edge of the triangle are all1, and each number inside the triangle is the sum of the two numbers above it. Write a function that computes the elements of Pascal’s triangle by means of a recursive process.
Do this exercise by implementing thepascalfunction inMain.scala, which takes a columncand a rowr, counting from0and returns the number at that spot in the triangle. For example,pascal(0,2)=1,pascal(1,2)=2andpascal(1,3)=3.
def pascal(c: Int, r: Int): Int解题思路:每个数是它上面里个数之和。
我的答案:
def pascalTriangle(column: Int, row: Int): Int = { if (column == 0) 1 else if (row == 0) 0 else pascalTriangle(column - 1, row - 1) + pascalTriangle(column, row - 1) } Console: println(pascalTriangle(0, 2)) //1 println(pascalTriangle(1, 2)) //2 println(pascalTriangle(1, 3)) //3 println(pascalTriangle(4, 6)) //15>>>>>>>>>>>>split line>>>>>>>>>>>>>>>>>
2. Exercise 2: Parentheses Balancing
Write a recursive function which verifies the balancing of parentheses in a string, which we represent as aList[Char]not aString. For example, the function should returntruefor the following strings:
The function should returnfalsefor the following strings:
The last example shows that it’s not enough to verify that a string contains the same number of opening and closing parentheses.
Do this exercise by implementing thebalancefunction inMain.scala. Its signature is as follows:
def balance(chars: List[Char]): Boolean
There are three methods onList[Char]that are useful for this exercise:
Hint: you can define an inner function if you need to pass extra parameters to your function.
Testing: You can use thetoListmethod to convert from aStringto aList[Char]: e.g."(just an) example".toList.
解题思路:如果使用java非递归来实现,会有一个stack来记录入栈和出栈, 遇到'('时入栈, 遇到')'时弹出栈顶,最后判断栈是否为空。此时要求使用递归,那么要用一个中间变量保存这样的入栈和出栈信息。
我的答案:
def balance(chars: List[Char]): Boolean = { //inner function def helper(chars: List[Char], likeStack: Int): Boolean = { if (likeStack < 0) { false } else { chars match { case Nil => if (likeStack == 0) true else false case '(' :: rest => helper(rest, likeStack + 1) case ')' :: rest => helper(rest, likeStack - 1) case head :: rest => helper(rest, likeStack) } } } helper(chars, 0) } Console: println(balance("(if (zero? x) max (/ 1 x))".toList)) //true println(balance("I told him (that it’s not (yet) done). (But he wasn’t listening)".toList)) //true println(balance(":-)".toList)) //false println(balance("())(".toList)) //false
>>>>>>>>>>>>split line>>>>>>>>>>>>>>>>>
Write a recursive function that counts how many different ways you can make change for an amount, given a list of coin denominations. For example, there are 3 ways to give change for 4 if you have coins with denomiation 1 and 2: 1+1+1+1, 1+1+2, 2+2.
Do this exercise by implementing thecountChangefunction inMain.scala. This function takes an amount to change, and a list of unique denominations for the coins. Its signature is as follows:
def countChange(money: Int, coins: List[Int]): Int
Once again, you can make use of functionsisEmpty,headandtailon the list of integerscoins.
Hint: Think of the degenerate cases. How many ways can you give change for 0 CHF? How many ways can you give change for >0 CHF, if you have no coins?
这一题对我来说有些难度,询问了同学,同学认为是SICP一书第一章的泛化,答案借助了谷歌:
连接:主题:有1元,5元,10元,20元,50元,问组成100元有多少种情况
量化后的一种答案(比较好理解),countingChanges函数返回List,其size即为结果:
def countingChanges() = { for (a <- (0 to 2); b <- (0 to 5); c <- (0 to 10); d <- (0 to 20); e <- (0 to 100); if ((50 * a + 20 * b + 10 * c + 5 * d + 1 * e) == 100)) yield (a, b, c, d, e) }
Eastsun大神给予了答案:
scala> def count(vs: List[Int],all: Int): Int = vs match { | case Nil => if(all == 0) 1 else 0 | case x::xs => (0 to all/x).map{ n => count(xs,all-x*n) }.sum | } count: (vs: List[Int],all: Int)Int scala> count(50::20::10::5::1::Nil,100) res2: Int = 343上述count函数使用标记的方式来计算总个数,对于每次划分,如果本次能够正好划分,就标记本次为1;否则标记为0。第一个case语句说明了函数返回的条件,这也是一般递归函数定义时必不可少的一步;第二个case有点抽象不好懂,总的来说就是按照第一个元素(50)来划分,再把剩余的部分划分。(0 to all/x)表示能够使用第一个元素划分的次数,对于此时的每一次划分,都要分解剩余部分。最后一个sum计算结果List(...1,0,1...0,0,1...)的总和,即最终能被完全分解的总个数(因为不能分解的已经标注为0了)。
--END