《快学scala》第十一章课后习题:
1.根据优先级规则,3 + 4 -> 5和3 -> 4 + 5是如何被求值的?
2.BigInt类有一个pow方法,但没有用操作符字符。Scala类库的设计者为什么没有选用**(像Fortran那样)或者^(像Pascal那样)作为乘方操作符呢?
3.实现Fraction类,支持+*/操作。支持约分,例如将15/-6变为-5/2。除以最大公约数,像这样:
class Fraction(n:Int,d:Int){
private val num:Int = if(d==0) 1 else n * sign(d)/gcd(n,d);
private val den:Int = if(d==0) 0 else d * sign(d)/gcd(n,d);
override def toString = num + "/" + den
def sign(a:Int) = if(a > 0) 1 else if (a < 0) -1 else 0
def gcd(a:Int,b:Int):Int = if(b==0) abs(a) else gcd(b,a%b)
...
}
4.实现一个Money类,加入美元和美分字段。提供+,-操作符以及比较操作符==和<。举例来说,Money(1,75)+Money(0,50)==Money(2,25)应为true。你应该同时提供*和/操作符吗?为什么?
5.提供操作符用于构造HTML表格。例如:Table() | "Java" | "Scala" || "Gosling" | "Odersky" || "JVM" | "JVM,.NET"应产出:<table><tr><td>Java</td></tr><td>Scala</td></tr><tr><td>Gosling…
6.提供一个ASCIIArt类,其对象包含类似这样的图形:
/\_/\
( ' ' )
( - )
| | |
(__|__)
提供将两个ASCIIArt图形横向或纵向结合的操作符。选用适当优先级的操作符命名。纵向结合的实例
/\_/\ -----
( ' ' ) / Hello \
( - ) < Scala |
| | | \ Coder /
(__|__) -----
7.实现一个BigSequence类,将64个bit的序列打包在一个Long值中。提供apply和update操作来获取和设置某个具体的bit
8.提供一个Matrix类—你可以选择需要的是一个2*2的矩阵,任意大小的正方形矩阵,或m*n的矩阵。支持+和*操作。*操作应同样适用于单值,例如mat*2。单个元素可以通过mat(row,col)得到
9.为RichFile类定义unapply操作,提取文件路径,名称和扩展名。举例来说,文件/home/cay/readme.txt的路径为/home/cay,名称为readme,扩展名为txt
10.为RichFile类定义一个unapplySeq,提取所有路径段。举例来说,对于/home/cay/readme.txt,你应该产出三个路径段的序列:home,cay和readme.txt
package llf
/**
* Created by sendoh on 2015/5/10.
*/
class answer11 {
}
//11.1
//从左至右执行
//2
//Scala中的操作符就是方法,其优先级是根据首字母来判断的,优先级如下:
//最高优先级:除以下字符外的操作符字符
//* / %
//+ -
//:
//= !
//< >
//&
//ˆ
//|
//非操作符
//最低优先级:赋值操作符
//3
import scala.math.abs
class Fraction(n: Int, d: Int){
private val num: Int = if (d == 0) 1 else n * sign(d) / gcd(n, d)
private val den: Int = if (d == 0) 0 else d * sign(d) / gcd(n, d)
override def toString = num + "/" + den
def sign(a: Int) = if (a > 0) 1 else if (a < 0) -1 else 0
def gcd(a: Int, b: Int): Int = if (b == 0) abs(a) else gcd(b, a % b)
def +(other: Fraction): Fraction = {
newFrac((this.num * other.den) + (other.num * this.den), this.den * other.den)
}
def -(other: Fraction): Fraction = {
newFrac((this.num * other.den) - (other.num * this.den), this.den * other.den)
}
def *(other: Fraction): Fraction = {
newFrac(this.num * other.num, this.den * other.den)
}
def /(other: Fraction): Fraction = {
newFrac(this.num * other.den, this.den * other.num)
}
private def newFrac(a: Int, b: Int): Fraction = {
val x: Int = if (b == 0) 1 else a * sign(b) / gcd(a, b)
val y: Int = if (b == 0) 0 else b * sign(b) / gcd(a, b)
new Fraction(x, y)
}
}
object Test extends App{
val p = new Fraction(20, 8)
val q = new Fraction(30, 4)
println(p + " " + q + " " + (p + q) + " " + (p - q) + " " + p * q + " " + p / q)
}
//4
class Money(val dollar: BigInt, val cent: BigInt){
def +(other: Money): Money = {
val (a, b) = (this.cent + other.cent) /% 100
new Money(this.dollar + other.dollar + a,b)
}
def -(other: Money): Money = {
val (c, d) = (this.toCent() - other.toCent()) /% 100
new Money(c, d)
}
private def toCent() = {
this.dollar * 100 + this.cent
}
def ==(other: Money): Boolean = this.dollar == other.dollar && this.cent == other.cent
def <(other: Money): Boolean = this.dollar < other.dollar || (this.dollar == other.dollar && this.cent < other.cent)
override def toString = "dollar = " + dollar + " cent =" + cent
}
object Money{
def apply(dollar: Int, cent: Int): Money ={
new Money(dollar, cent)
}
def main(args: Array[String]): Unit ={
val R1 = Money(1, 1000)
val R2 = Money(2, 1500)
println(R1 + R2)
println(R1 - R2)
println(R1 == R2)
println(R1 < R2)
println(Money(1,75)+Money(0,50)==Money(2,25))
}
}
//5
class Table{
var s: String = ""
def |(str: String): Table ={
val t = Table()
t.s = this.s + "<td>" + str + "</td>"
t
}
def ||(str: String): Table ={
val t = Table()
t.s = this.s + "</tr><tr><td>" + str + "</td>"
t
}
override def toString: String ={
"<table><tr>" + this.s + "</tr></table>"
}
}
object Table{
def apply(): Table = {
new Table()
}
def main(args: Array[String]): Unit ={
println(Table() | "Java" | "Scala" || "Gosling" | "Odersky" || "JVM" | "JVM,.NET")
}
}
//6????????
import collection.mutable.ArrayBuffer
class ASCIIArt(str:String){
val arr:ArrayBuffer[ArrayBuffer[String]] = new ArrayBuffer[ArrayBuffer[String]]()
if (str != null && !str.trim.eq("")){
str.split("[\r\n]+").foreach{
line =>
val s = new ArrayBuffer[String]()
s += line
arr += s
}
}
def this(){
this("")
}
def +(other:ASCIIArt):ASCIIArt={
val art = new ASCIIArt()
val length = if (this.arr.length >= other.arr.length) this.arr.length else other.arr.length
for(i <- 0 until length){
val s = new ArrayBuffer[String]()
val thisArr:ArrayBuffer[String] = if (i < this.arr.length) this.arr(i) else new ArrayBuffer[String]()
val otherArr:ArrayBuffer[String] = if (i < other.arr.length) other.arr(i) else new ArrayBuffer[String]()
thisArr.foreach(s += _)
otherArr.foreach(s += _)
art.arr += s
}
art
}
def *(other:ASCIIArt):ASCIIArt={
val art = new ASCIIArt()
this.arr.foreach(art.arr += _)
other.arr.foreach(art.arr += _)
art
}
override def toString()={
var ss:String = ""
arr.foreach{
ss += _.mkString(" ") + "\n"
}
ss
}
}
object Test6 extends App{
val a = new ASCIIArt(""" /\_/\
|( ' ' )
|( - )
| | | |
|(__|__)
|""".stripMargin)
val b = new ASCIIArt( """ -----
| / Hello \
| < Scala |
| \ Coder /
| -----
|""".stripMargin)
println(a + b * b)
println((a + b) * b)
println(a * b)
}
//7
class BigSequence{
var num = new Array[Int](64)
for (i <- 0 until num.length){
num(i) = -1
}
def pack():Long={
num.filter(_ >= 0).mkString.toLong
}
}
object BigSequence{
def apply(num:Int):BigSequence={
val b = new BigSequence
var i = 0
num.toString.foreach{
n=>
b.num(i) = n.getNumericValue
i+=1
}
b
}
def main(args: Array[String]) {
val b = BigSequence(10100)
println(b.pack())
}
}
//8
class Matrix(val x:Int,val y:Int){
def +(other:Matrix):Matrix={
Matrix(this.x + other.x,this.y + other.y)
}
def +(other:Int):Matrix={
Matrix(this.x + other,this.y + other)
}
def *(other:Matrix):Matrix={
Matrix(this.x * other.x,this.y * other.y)
}
def *(other:Int):Matrix={
Matrix(this.x * other,this.y * other)
}
override def toString()={
var str = ""
for(i <- 1 to x){
for(j <- 1 to y){
str += "*"
}
str += "\n"
}
str
}
}
object Matrix{
def apply(x:Int,y:Int):Matrix= new Matrix(x,y)
def main(args: Array[String]) {
val m = Matrix(2,2)
val n = Matrix(3,4)
println(m)
println(n)
println(m + n)
println()
println(m * n)
println()
println(m + 2)
println()
println(n * 2)
println()
}
}
//9
class RichFile(val path:String){}
object RichFile{
def apply(path:String):RichFile={
new RichFile(path)
}
def unapply(richFile:RichFile) = {
if(richFile.path == null){
None
} else {
val reg = "([/\\w+]+)/(\\w+)\\.(\\w+)".r
val reg(r1,r2,r3) = richFile.path
Some((r1,r2,r3))
}
}
def main(args: Array[String]) {
val richFile = RichFile("/home/cay/readme.txt")
val RichFile(r1,r2,r3) = richFile
println(r1)
println(r2)
println(r3)
}
}
//10
class RichFile10(val path:String){}
object RichFile10{
def apply(path:String):RichFile={
new RichFile(path)
}
def unapplySeq(richFile:RichFile):Option[Seq[String]]={
if(richFile.path == null){
None
} else {
Some(richFile.path.split("/"))
}
}
def main(args: Array[String]) {
val richFile = RichFile("/home/cay/readme.txt")
val RichFile(r @ _*) = richFile
println(r)
}
}
/
《快学scala》第十二章课后习题:
1.编写函数values(fun:(Int)=>Int,low:Int,high:Int),该函数输出一个集合,对应给定区间内给定函数的输入和输出。比如,values(x=>x*x,-5,5)应该产出一个对偶的集合(-5,25),(-4,16),(-3,9),…,(5,25)
2.如何用reduceLeft得到数组中的最大元素?
3.用to和reduceLeft实现阶乘函数,不得使用循环或递归
4.前一个实现需要处理一个特殊情况,即n<1的情况。展示如何用foldLeft来避免这个需要。
5.编写函数largest(fun:(Int)=>Int,inputs:Seq[Int]),输出在给定输入序列中给定函数的最大值。举例来说,largest(x=>10*x-x*x,1 to 10)应该返回25.不得使用循环或递归
6.修改前一个函数,返回最大的输出对应的输入。举例来说,largestAt(fun:(Int)=>Int,inputs:Seq[Int])应该返回5。不得使用循环或递归
7.要得到一个序列的对偶很容易,比如:val pairs = (1 to 10) zip (11 to 20)
8.在12.8节中,你看到了用于两组字符串数组的corresponds方法。做出一个对该方法的调用,让它帮我们判断某个字符串数组里的所有元素的长度是否和某个给定的整数数组相对应
9.不使用柯里化实现corresponds。然后尝试从前一个练习的代码来调用。你遇到了什么问题?
10.实现一个unless控制抽象,工作机制类似if,但条件是反过来的。第一个参数需要是换名调用的参数吗?你需要柯里化吗?
package llf
/**
* Created by sendoh on 2015/5/10.
*/
class answer12 {
}
//12.1
object Test1 extends App{
def values(fun: (Int) => Int, low: Int, high: Int) = {
var arr = List[(Int, Int)]()
low to high foreach{
num =>
arr = (num, fun(num)) :: arr
}
arr
}
println(values(x => x * x, -5, 5).mkString)
}
//2
object Test2 extends App{
val arr2 = Array(1, 3, 4, 2, 8, 5, 9, 11, 7)
println(arr2.reduceLeft((a, b) => if (a > b) a else b))
}
//3
object Test3 extends App {
println(1 to 10 reduceLeft (_ * _))
}
//4
object Test4 extends App{
println((1 to -10).foldLeft(1)(_ * _))
}
//5
object Test5 extends App{
def largest(fun: (Int) => Int, inputs: Seq[Int]) = {
val s = inputs.reduceLeft((a, b) => if (fun(a) > fun(b)) a else b)
fun(s)
}
println(largest(x => 10 * x - x * x, 1 to 10))
}
//6
object Test6 extends App{
def largest(fun: (Int) => Int, inputs: Seq[Int]) = {
inputs.reduceLeft((a, b) => if (fun(a) > fun(b))a else b)
}
println(largest(x => 10 * x - x * x, 1 to 10))
}
//7
object Test7 extends App{
var list = List[Int]()
def adjustToPair(fun: (Int, Int) => Int)(tup: (Int, Int)) = {
list = fun(tup._1, tup._2) :: List
this
}
def map(fun: (Int, Int) => Int): Int = {
list.reduceLeft(fun)
}
val pairs = (1 to 10) zip (11 to 20)
for ((a, b) <- pairs){
adjustToPair(_ * _)((a, b))
}
println(map(_ + _))
}
//8
object Test8 extends App{
val a = Array("sss", "ee", "rrrr")
val b = Array(3, 2, 4)
val c = Array(3, 2, 1)
println(a.corresponds(b)(_.length == _))
println(a.corresponds(c)(_.length == _))
}
//9
//没有柯里化不能用前一个练习的方式调用
//10
object Test10 extends App {
def unless(condition: =>Boolean)(block: =>Unit){
if (!condition){
block
}
}
var x = 10
unless(x == 0){
x -= 1
println(x)
}
}
//
《快学scala》第十三章课后习题:
1.编写一个函数,给定字符串,产出一个包含所有字符的下标的映射。举例来说:indexes("Mississippi")应返回一个映射,让'M'对应集{0},'i'对应集{1,4,7,10},依此类推。使用字符到可变集的映射。另外,你如何保证集是经过排序的?
2.重复前一个练习,这次用字符到列表的不可变映射。
3.编写一个函数,从一个整型链表中去除所有的零值。
4.编写一个函数,接受一个字符串的集合,以及一个从字符串到整数值的映射。返回整型的集合,其值为能和集合中某个字符串相对应的映射的值。举例来说,给定Array("Tom","Fred","Harry")和Map("Tom"->3,"Dick"->4,"Harry"->5),返回Array(3,5)。提示:用flatMap将get返回的Option值组合在一起
5.实现一个函数,作用与mkString相同,使用reduceLeft。
6.给定整型列表lst,(lst :\ List[Int]())(_ :: _ )得到什么?(List[Int]() /: lst)(_ :+ _)又得到什么?如何修改它们中的一个,以对原列表进行反向排序?
7.在13.11节中,表达式(prices zip quantities) map { p => p._1 * p._2}有些不够优雅。我们不能用(prices zip quantities) map { _ * _},因为 _ * _ 是一个带两个参数的函数,而我们需要的是一个带单个类型为元组的参数的函数,Function对象的tupled方法可以将带两个参数的函数改为以元俎为参数的函数。将tupled应用于乘法函数,以使我们可以用它来映射由对偶组成的列表。
8.编写一个函数。将Double数组转换成二维数组。传入列数作为参数。举例来说,Array(1,2,3,4,5,6)和三列,返回Array(Array(1,2,3),Array(4,5,6))。用grouped方法。
9.Harry Hacker写了一个从命令行接受一系列文件名的程序。对每个文件名,他都启动一个新的线程来读取文件内容并更新一个字母出现频率映射,声明为:
val frequencies = new scala.collection.multable.HashMap[Char,Int] with scala.collection.mutable.SynchronizedMap[Char,Int]
10.Harry Hacker把文件读取到字符串中,然后想对字符串的不同部分用并行集合来并发地更新字母出现频率映射。他用了如下代码:
val frequencies = new scala.collection.mutable.HashMap[Char,Int]
for(c <- str.par) frequencies(c) = frequencies.getOrElse(c,0) + 1
/
package llf
import scala.collection.mutable
/**
* Created by sendoh on 2015/5/11.
*/
class answer13 {
}
//13.1
class Test1{
import collection.mutable.{Map,HashMap,SortedSet}
def index(str: String): Map[Char, SortedSet[Int]] = {
var map = new mutable.HashMap[Char, mutable.SortedSet[Int]]()
var i = 0
str.foreach{
c =>
map.get(c) match{
case Some(result) => map(c) = result + i
case None => map += (c -> SortedSet{i})
}
i + 1
}
map
}
println(index("Mississippi"))
}
//2
class Test2{
import collection.immutable.HashMap
import collection.mutable.ListBuffer
def index(str: String): Map[Char, ListBuffer[Int]] = {
var map = new HashMap[Char, ListBuffer[Int]]()
var i = 0
str.foreach{
c =>
map.get(c) match{
case Some(result) => result += i
case None => map += (c -> ListBuffer{i})
}
i + 1
}
map
}
println(index("Mississippi"))
}
//3
class Test3{
def rmZero(nums: List[Int]): List[Int] = {
nums.filter(_ != 0)
}
println(rmZero(List(1, 0, 3, 4, 0, 7)))
}
//4
class Test4{
def strMap(strArr: Array[String], map: Map[String, Int]): Array[Int] = {
strArr.flatMap(map.get(_))
}
val a = Array("aaa", "bbbb", "ccccc")
val m = Map("aaa" -> 3, "bbbb" -> 4, "ccccc" -> 5)
println(strMap(a, m).mkString(","))
}
//5
//mkString 用指定分割符号连接所有元素,返回字符串
class Test5{
import collection.mutable
trait mymkString {
this: mutable.Iterable[String] =>
def mymkString = if (this != Nil) this.reduceLeft(_ + _)
}
var a = new mutable.HashSet[String] with mymkString
a += "1"
a += "2"
a += "3"
println(a.mymkString)
}
//6
class Test6{
val alist = List(1, 2, 3, 4, 5)
println(alist :\ List[Int]())(_::_)
println((List[Int]() /: alist)((a, b) => b :: a))
}
//7
class Test7{
val prices = List(5.0, 20.0, 9.95)
val quantities = List(10, 2, 1)
println((prices zip quantities) map {Function.tupled(_ * _)})
}
//8
class Test8{
def divArr(arr: Array[Double], i: Int) = {
arr.grouped(i).toArray
}
val arr = Array(1.0, 2, 3, 4, 5, 6)
divArr(arr, 3).foreach(a => println(a.mkString(",")))
}
//9
/
//10
/