Scala课程习题解答

Scala课程习题解答

1.基础

(1)用体重和身高计算BMI值,它需要满足下面的测试:

(体重(公斤) / 身高2(cm2)

例如:一個52公斤的人,身高是155厘米,則BMI为:52(公斤)/1.552 (cm2 )= 21.6)小于18.5 体重过轻, 18.5~24 正常 大于 24 过重.

val normal = bmiStatus(75, 183)
Assert(“Normal weight”== normal,”Expected Normal Weight, Got”+ normal) 
val normal = bmiStatus(160, 68)
Assert(“Normal weight”== normal,”Expected Normal Weight, Got”+ normal) 
val normal = bmiStatus(160, 68)
Assert(“Normal weight”== normal,”Expected Normal Weight, Got”+ normal)
代码
class BMI {
    def bmiStatus(weight:Double,height:Double):String={

       val  bmi=weight/((height/100)*(height/100));

      bmi match{
        case bmi if(bmi>24)=>"Over Weight"
        case bmi if(bmi<18.5)=>"Below Weight"
        case _ =>"Normal weight"
      }

    }

}
object test{
  def main(args: Array[String]): Unit = {
    val bmi=new BMI
    val normal = bmi.bmiStatus(75, 183)
    println(normal)
    assert("Normal weight"== normal,"Expected Normal Weight, Got"+ normal)
    val normal2 = bmi.bmiStatus(68, 170)
    println(normal2)
    assert("Normal weight"== normal2,"Expected Normal Weight, Got"+ normal2)
    val normal3 = bmi.bmiStatus(58, 160)
    println(normal3)
    assert("Normal weight"== normal3,"Expected Normal Weight, Got"+ normal3)
  }
}

(2)彩票小程序,编写 Scala 小程序Lottery,设计自己的函数实现以下功能:

1 允许用户输入7个 1~35 的数字(用户购买彩票,程序能检测出非法数值,提示重新输入)

2 随机生成7个数字(开奖),系统自动兑奖并返回中奖结果

代码
class Lottery {
  val res = new Array[Int](7)
  var nums = new Array[Int](7)

  def input():Unit = {
    try {
      for (i <- 0 to 6) {
        println("please input a num in [1,35]")
        nums(i) = scala.io.StdIn.readInt();
        while (nums(i) < 1 || nums(i) > 35) {
          println("invalid num,please input a num in [1,35]")
          nums(i) = scala.io.StdIn.readInt();
        }

      }
    }
    catch {
      case Throwable=>{
        println("invalid num,please input a num in [1,35]")
        input()
      }


    }

  }

  def generate() = {
    res.map(_ => scala.util.Random.nextInt(36))


  }

  def calculate(): String = {
    var sum = 0;

    for (i <- 0 until 7) {
      val result = res(i)
      val num = nums(i)
      println(s"result:$result your input $num")
      if (nums(i) == res(i)) {
        sum += 1;
      }
    }
    sum match {
      case 0 => "sorry"
      case 1 => "not bad"
      case 2 => "just so so"
      case 3 => "good"
      case 4 => "great"
      case 5 => "very good"
      case 6 => "excellent"
      case 7 => "unbelievable"
    }
  }


}

object Lottery {
  def main(args: Array[String]): Unit = {
    val lottery = new Lottery();
    lottery.input();
    lottery.generate();
    print(lottery.calculate());
  }
}

2.面向对象

1.编写一个Time类,加入只读属性hours和minutes,和一个检查某一时刻是否早于另一时刻 的方法before(other:Time):Boolean。Time对象应该以new Time(hrs,min)方式构建。其中hrs以 军用时间格式呈现(介于0和23之间)

代码
class Time(val hrs: Int, val mins: Int) {

    if (hrs > 24 || hrs < 0 || mins > 60 || mins < 0) {
      throw new Exception("invalid hours or minutes,construct failed")//暂时没有找到怎么在构造函数中限制参数的范围

    }
  def before(other: Time): Boolean = {
    if (this.hrs < other.hrs) {
      true
    }
    else if (this.hrs == other.hrs) {
      if (this.mins < this.mins) {
        true
      }
      false
    }
    else {
      false
    }

  }

}
object  Time{
  def main(args: Array[String]): Unit = {
    val time=new Time(24,12);
    val time1=new Time(22,12);
    println(time1.before(time))
    val time2=new Time(121,12)

   
  }
}

2.定义抽象类Animal,在抽象类中定义抽象方法animal 和 sound,并定义templateMethod 方法,在这个方法中直接调用animal 和sound方法是否合理?

代码
abstract class Animal {
  abstract def animal(): String

  abstract def sound(): String

  abstract def food(): String

  def templateMethod(): Unit = {
    animal();
    sound();
  }

}

class Duck extends Animal {
  override def animal(): String = "duck"

  override def sound(): String = "ga ga"

  override def food(): String = "plants"
}
class Cow extends Animal{
  override def animal(): String = "cow"

  override def sound(): String ="mou mou"

  override def food(): String = "grass"
}

object Animal {
  def main(args: Array[String]): Unit = {
    val duck =new Duck
    println(duck.food())
    assert("plants"== duck.food(),"Expected plants, Got"+ duck.food())
    val cow=new Cow
    println(cow.food())
    assert("grass"==cow.food(),"Expected Normal Weight, Got"+ cow.food())
  }
}

定义两种实现类,实现Animal,修 改Animal 和它的子类,使其还能表示动物都吃什么。所编写的代码需要满足如下测试

 val duck = new Duck
Duck food is “plants” 

 val cow = new Cow
Cow.food is “grass”

3.自己设计一套特质,要求体现叠加在一起的特质,设计具体的抽象方法抽象字段

创建trait BatteryPower 来报告剩余电量。如果电量多余40%,那么报告“green”;如果在 20%~39% 之间 那么报告yellow;如果少于20%,那么报告”red”。实例化该代码满足下列测试:

class Battery extends EnergySource with BatteryPower

val battery = new Battery 

battery.monitor(80) is “green”

battery.monitor(30) is “yellow” 

battery.monitor(10) is “red”
代码
trait Power {
  def cal(power: Double): Double = {
    power
  }
}

trait EnergySoure extends Power {

  override def cal(power: Double): Double = {
    power
  }
}

trait BatteryPower extends Power {
  override def cal(power: Double): Double = {
    power match {
      case power if (super.cal(power) >= 40) => 2.0
      case power if (super.cal(power) < 20) => 0.0
      case _ => 1.0
    }

  }
}

class Battery extends EnergySoure with BatteryPower {

  def monitor(power: Double): String = {
    super.cal(power) match {
      case 0.0 => "red"
      case 1.0 => "yellow"
      case 2.0 => "green"
    }
  }

}

object Battery {
  def main(args: Array[String]): Unit = {
    val battery = new Battery

    val green = battery.monitor(44)
    println(green)
    assert("green" == green, "Expected green, Got" + green)

    val yellow = battery.monitor(24)
    println(yellow)
    assert("yellow" == yellow, "Expected  yellow, Got" + yellow)

    val red = battery.monitor(4)
    println(red)
    assert("red" == red, "Expected  red, Got" + red)
  }
}

曲线救国,其实我也没着真正理解特质叠加的精髓,只能依葫芦画瓢。

4.通过把 scala.math.Ordered[Point] 混入 java.awt.Point 的方式,定义 OrderedPoint 类, 按照词典的编辑方式排序,也就是说,如果x <x`或者x=x’或者y<y’则(x,y)<(x’,y’)

代码

import java.awt.Point

import scala.math.Ordered;

class OrderedPoint(x:Int,y:Int) extends Point(x:Int,y:Int) with Ordered[Point] {
  override def compare(that: Point): Int = {
    //直接重写了Ordered的compare方法
    if (this.x < that.x || this.x == that.x || this.y < that.y) {
      0
    }
    1
  }
}
object  OrderedPoint{
  def main(args: Array[String]): Unit = {
    val orderedPoint1=new OrderedPoint(1,2)
    val orderedPoint2=new OrderedPoint(2,23)
    print(orderedPoint1.compare(orderedPoint2))
  }
}

5.尝试设计一套特质,灵活的改动整数队列。队列有两种操作:put把整数放入队列,get从尾 部取出它们。队列是先进先出的,get应该依照入队列的顺序取数据。

提示:可以用mutable.ArrayBuffer 模拟队列
在报告中体现出类的线性化特性,要求扩展类实现如下三个功能

  1. Doubling 把放到队列中的数字翻倍
  2. Incrementing 把放到队列的数据增加1
  3. 过滤掉队列中的负数
代码
package zun

import scala.collection.mutable.ArrayBuffer

abstract class Queue {
  println("queue cons")
  var arrayBuffer = new ArrayBuffer[Int]()

   def put(num: Int): Unit

  def get(): Int = {
    arrayBuffer.remove(0)
  }
  def show()={
    arrayBuffer.foreach(println)
  }

}

trait Doubling extends Queue {
  println("double cons")

  abstract override def put(num: Int): Unit = {
    println("double put")
    super.put(2 * num)
  }

}

trait Incrementing extends Queue {
  println("incre cons")

abstract override def put(num: Int): Unit = {
    println("incre put")
    super.put(num + 1)
  }




}
trait NegativeFiltering extends Queue {
  println("nega cons")

  abstract override def put(num: Int): Unit = {
    println("nega put")
    if (num > 0) {
      super.put(num)
    }
    else {
      println("please append positive")
    }
  }

}
class NewQueue extends Queue   {
  override def put(num: Int): Unit = {
    arrayBuffer += num
  }

}

object Queue {
  def main(args: Array[String]): Unit = {
    //体现线性化顺序
    val queue = new NewQueue() with Doubling with Incrementing  with NegativeFiltering
    queue.put(1)
    queue.put(2)
    queue.put(-1)
    queue.put(22)
    queue.show()
  }
}

有个疑问 ,在实例化时with和类中with有什么不同?

3.函数

1.下面程序改成高阶程序

在这里插入图片描述

代码
object MyModule {

  private def formatAbs(func: (Int) => Int, x: Int) ={
    val msg = "the absolute value of %d is %d"
    msg.format(x, func(x))
  }


  def main(args: Array[String]): Unit = {
    println(formatAbs(x=> if (x >= 0) x else -x, -23))
  }

}

2.用correspond方法让我们判断某个字符串数组里面所有元素的长度是否和某个给定的整数数组一致。

代码

一一对应

object TestCorrespond {
  def main(args: Array[String]): Unit = {
    val a=Array("aa","bb","cc","dd")
    val b=Array(2,2,2,2)
    val c=Array(1,2,3)
    val d=Array(1,2,3,4)
    println(a.corresponds(b)(_.length==_))
    println(a.corresponds(c)(_.length==_))
    println(a.corresponds(d)(_.length==_))
  }
}

3.假设某国的货币有若干面值,现给一张大面值的货币要兑换成零钱,问有多少种兑换方式。 用尾递归实现。

代码
 def countChange(money: Int, coins: List[Int]): Int = {
    if (money == 0) 1
    else if (coins.size == 0 || money < 0) 0
    else countChange(money, coins.tail) + countChange(money - coins.head, coins)//不使用当前的零钱+使用当前的零钱
  }
  def main(args: Array[String]): Unit = {
    val coins = List(1, 5, 10, 20, 50, 100);
    coins.foreach(println)
    val money = 53;
    println(countChange(money, coins))
    println(ans)
  }

4.写一个递归函数,来获取第n个斐波那契数,前两个斐波那契数0 和 1,第n个数总是等于前 两个数的和——序列开始为0,1,1,2,3,5.请定义尾递归函数 def fib(n: Int): Int

代码
object FIb {

  def  fib(n:Int):Int={  
    
    def cal(n:Int,before:Int,after:Int):Int={
      if(n==1) before

      else cal(n-1,after,before+after)
    }
    cal(n,0,1)
  }

  def main(args: Array[String]): Unit = {
    println(fib(6))
  }

}

5.定义一个操作符+%,将一个给定的百分比添加到某个值。举例来说120 +% 10 = 132,由于操 作符是方法而不是函数,你需要提供一个implicit。

代码
package zun

class AddPercent(x: Double) {
  def +%(n: Double)= x + x * n * 0.01

}

object Operator {

  implicit def test(x: Double) = new AddPercent(x)//这个函数名可以是任意的

  def main(args: Array[String]): Unit = {

    println(120.+%(10))
  }
}

4.集合操作

1.一千万个随机数,随机数范围在1到1亿之间,现在要求写出一种算法,将1到1亿之间没有出现的随机数求出来。

代码
  def main(args: Array[String]): Unit = {
    val bat = BitSet() ++ (1 to 10000000).par.toList
    val bit = BitSet() ++ (1 to 100000000).par.map(x => Random.nextInt(10000000) + 1).toList
    val res = bat -- bit
    println(res)
    println(bat)
    println(bit)
    println(res.size)
  }

2. 编 写 一 个 函 数 , 接 收 一 个 字 符 串 集 合 , 以 及 一 个 从 字 符 串 到 整 数 的 映 射 ,返回整数集合,其值为能和集合中某个字符串相应的映射值。举例来说,给定Array(“Tom”,“Fred”,“Harry”) 和 Map(“Tom”->3,“Dick”->4,“Harry”->5),返回Array(3,5)

代码
object Mapper {
  def mapper(names:Array[String],map:Map[String,Int]):Array[Int]={
      names.flatMap(map.get(_))//相当于将结果扁平化了
  }
  def main(args: Array[String]): Unit = {
    val names=Array("Tom","Fred","Harry")
    val map=Map("Tom"->3,"Dick"->4,"Harry"->5)
    println(mapper(names,map).mkString(","))

  }
}

3.对给定的整型列表lst,(lst :\ ListInt)(:: )得到的是什么? (ListInt /: lst)(:+)又得到什么?如何修改这两个操 作,对原来列表反向操作?

代码
object ListOperation {
  def main(args: Array[String]): Unit = {
    val lst=List(1,23,45,3)
    val lst1=(lst :\ List[Int]())(_:: _)//:\foldRight
    val lst1_re=(lst :\ List[Int]())((x,y)=>(y:+x))
    val lst2=(List[Int]() /: lst)(_:+_)// /:foldLeft
    val lst2_re=(List[Int]() /: lst)((x,y)=>y+:x)
    println(lst1)
    println(lst2)
    println(lst2_re)
    println(lst1_re)
  }

}

4.根据 flatMap 实现一个variance(方差)函数,如果一个序列的平均值m,variance是对序列中的每一个元素x进行 math.pow(x-m,2) def variances(xs: Seq[Double]): Option[Double]

代码

用的是map,用flatMap不知道怎么写

object Varience {
  def variances(xs: Seq[Double]): Option[Double] = {
    val len = xs.size
    val m = xs.sum / xs.size
    Some(xs.map(x=>math.pow(x-m,2)).sum/len)
  }

  def main(args: Array[String]): Unit = {
    val xs = Seq(1.0, 1, 1, 1)
   println( variances(xs))

  }
}

5.统计字符串中字母出现的频率映射,例如字符串 “scalajavajavascript”返回Map[Char,Int]。用aggregate 方法

代码
import scala.collection.immutable.HashMap


object FrequenceMap {
  def main(args: Array[String]): Unit = {
    val str = "scalajavajavascript"
    val res = str.par.aggregate(HashMap[Char, Int]())(
      (hashMap, char) => {
        //相当于map阶段,处理成key,value形式
        hashMap + (char -> (hashMap.getOrElse(char, 0) + 1))
      }
      (map1, map2) => {
        (map1.keySet ++ map2.keySet).foldLeft(HashMap[Char, Int]()) {
          (hashMap, key) => {
            hashMap + (key -> (map1.getOrElse(key, 0) + map2.getOrElse(key, 0)))
          }
        }
      }
    )
    println(res)

  }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值