1.计算级数

代码

// exercise2-1.scala
import scala.io.StdIn

object exercise2_1 {
def main(args: Array[String]): Unit = {
print("请输入q的值(大于0的整数): ")
val q = StdIn.readDouble()

var Sn = 0.0  // 级数和
var n = 1     // 当前项数

// 计算级数:Sn = Σ[i=1 to n] (i+1)/i
// 直到 Sn >= q
while (Sn < q) {
  // 计算第n项:(n+1)/n
  val term = (n.toDouble + 1.0) / n.toDouble
  Sn += term
  n += 1
}

// 输出结果,保留6位小数
println(f"Sn=$Sn%.6f")

}
}

image

2.模拟图形绘制

代码

// exercise2-2.scala - 模拟图形绘制

// 定义Drawable特质
trait Drawable {
def draw(): Unit = { println(this.toString) }
}

// 定义Point类
case class Point(var x: Double, var y: Double) extends Drawable {
def shift(deltaX: Double, deltaY: Double): Unit = {
x += deltaX
y += deltaY
}
}

// 定义Shape抽象类
abstract class Shape(val point: Point) {
def moveTo(newPoint: Point): Unit
def zoom(scale: Double): Unit
}

// 定义Line类
class Line(p1: Point, var p2: Point) extends Shape(p1) with Drawable {
// 移动直线到新位置
override def moveTo(newPoint: Point): Unit = {
val deltaX = newPoint.x - point.x
val deltaY = newPoint.y - point.y
point.shift(deltaX, deltaY)
p2.shift(deltaX, deltaY)
}

// 缩放直线,中点不变
override def zoom(scale: Double): Unit = {
// 计算中点
val midX = (point.x + p2.x) / 2
val midY = (point.y + p2.y) / 2

// 按比例调整两个端点
point.x = midX + (point.x - midX) * scale
point.y = midY + (point.y - midY) * scale
p2.x = midX + (p2.x - midX) * scale
p2.y = midY + (p2.y - midY) * scale

}

// 重载draw方法
override def draw(): Unit = {
println(s"Line:(${point.x},${point.y})--(${p2.x},${p2.y})")
}
}

// 定义Circle类
class Circle(center: Point, var radius: Double) extends Shape(center) with Drawable {
// 移动圆到新位置
override def moveTo(newPoint: Point): Unit = {
point.x = newPoint.x
point.y = newPoint.y
}

// 缩放圆,圆心不变,半径变化
override def zoom(scale: Double): Unit = {
radius *= scale
}

// 重载draw方法
override def draw(): Unit = {
println(s"Circle center:(${point.x},${point.y}),R=$radius")
}
}

// 主程序
object MyDraw {
def main(args: Array[String]): Unit = {
// 测试Point
val p = new Point(10, 30)
p.draw()

// 测试Line
val line1 = new Line(Point(0, 0), Point(20, 20))
line1.draw()

line1.moveTo(Point(5, 5)) // 移动到一个新的点
line1.draw()

line1.zoom(2) // 放大两倍
line1.draw()

// 测试Circle
val cir = new Circle(Point(10, 10), 5)
cir.draw()

cir.moveTo(Point(30, 20))
cir.draw()

cir.zoom(0.5)
cir.draw()

}
}

image

3.统计学生成绩

代码

// exercise2-3.scala - 统计学生成绩

object GradeStatistics {

// 统计函数:计算平均值、最小值和最大值
def calculateStats(scores: List[Double]): (Double, Double, Double) = {
val avg = scores.sum / scores.length
val min = scores.min
val max = scores.max
(avg, min, max)
}

// 解析一行数据
def parseLine(line: String): (String, String, List[Double]) = {
val fields = line.trim.split("\s+")
val id = fields(0)
val gender = fields(1)
val scores = fields.drop(2).map(_.toDouble).toList
(id, gender, scores)
}

// 格式化输出
def formatOutput(courseName: String, avg: Double, min: Double, max: Double): String = {
f"$courseName: $avg%7.2f $min%6.2f $max%6.2f"
}

// 主统计函数
def analyzeGrades(data: List[String]): Unit = {
// 解析表头获取课程名称
val header = data.head.split("\s+").toList
val courseNames = header.drop(2) // 去掉Id和gender

// 解析所有数据行
val allStudents = data.tail.map(parseLine)

// 按性别分组
val males = allStudents.filter(_._2 == "male")
val females = allStudents.filter(_._2 == "female")

// 辅助函数:提取特定列的成绩
def extractScores(students: List[(String, String, List[Double])], courseIndex: Int): List[Double] = {
  students.map(_._3(courseIndex))
}

println("course   average  min  max")
// 全体学生的统计
for (i <- courseNames.indices) {
  val scores = extractScores(allStudents, i)
  val (avg, min, max) = calculateStats(scores)
  println(formatOutput(courseNames(i), avg, min, max))
}

// 男生统计
println("\ncourse   average  min  max (males)")
for (i <- courseNames.indices) {
  val scores = extractScores(males, i)
  val (avg, min, max) = calculateStats(scores)
  println(formatOutput(courseNames(i), avg, min, max))
}

// 女生统计
println("\ncourse   average  min  max (females)")
for (i <- courseNames.indices) {
  val scores = extractScores(females, i)
  val (avg, min, max) = calculateStats(scores)
  println(formatOutput(courseNames(i), avg, min, max))
}

}

// 更函数式编程的版本
def analyzeGradesFunctional(data: List[String]): Unit = {
val header = data.head.split("\s+").toList
val courseNames = header.drop(2)

val allStudents = data.tail.map(parseLine)

// 使用模式匹配和函数组合
def printStats(title: String, students: List[(String, String, List[Double])]): Unit = {
  println(s"\ncourse   average  min  max $title")
  
  courseNames.zipWithIndex.foreach { case (courseName, index) =>
    val scores = students.map { case (_, _, scoreList) => scoreList(index) }
    val (avg, min, max) = calculateStats(scores)
    println(formatOutput(courseName, avg, min, max))
  }
}

println("course   average  min  max")
printStats("", allStudents)

val males = allStudents.filter { case (_, gender, _) => gender == "male" }
val females = allStudents.filter { case (_, gender, _) => gender == "female" }

printStats("(males)", males)
printStats("(females)", females)

}

// 测试样例1
val sample1 = List(
"Id gender Math English Physics",
"301610 male 80 64 78",
"301611 female 65 87 58",
"301612 female 44 71 77",
"301613 female 66 71 91",
"301614 female 70 71 100",
"301615 male 72 77 72",
"301616 female 73 81 75",
"301617 female 69 77 75",
"301618 male 73 61 65",
"301619 male 74 69 68",
"301620 male 76 62 76",
"301621 male 73 69 91",
"301622 male 55 69 61",
"301623 male 50 58 75",
"301624 female 63 83 93",
"301625 male 72 54 100",
"301626 male 76 66 73",
"301627 male 82 87 79",
"301628 female 62 80 54",
"301629 male 89 77 72"
)

// 测试样例2
val sample2 = List(
"Id gender Math English Physics Science",
"301610 male 72 39 74 93",
"301611 male 75 85 93 26",
"301612 female 85 79 91 57",
"301613 female 63 89 61 62",
"301614 male 72 63 58 64",
"301615 male 99 82 70 31",
"301616 female 100 81 63 72",
"301617 male 74 100 81 59",
"301618 female 68 72 63 100",
"301619 male 63 39 59 87",
"301620 female 84 88 48 48",
"301621 male 71 88 92 46",
"301622 male 82 49 66 78",
"301623 male 63 80 83 88",
"301624 female 86 80 56 69",
"301625 male 76 69 86 49",
"301626 male 91 59 93 51",
"301627 female 92 76 79 100",
"301628 male 79 89 78 57",
"301629 male 85 74 78 80"
)

def main(args: Array[String]): Unit = {
println("=== 样例1统计结果 ===")
analyzeGradesFunctional(sample1)

println("\n\n=== 样例2统计结果 ===")
analyzeGradesFunctional(sample2)

// 也可以测试从文件读取
if (args.length > 0) {
  val filename = args(0)
  val source = scala.io.Source.fromFile(filename)
  val lines = try source.getLines().toList finally source.close()
  
  println(s"\n\n=== 文件 $filename 统计结果 ===")
  analyzeGradesFunctional(lines)
}

}
}
// 更简洁的函数式版本(可选)
object GradeStatisticsAlt {

// 使用case class来表示学生
case class Student(id: String, gender: String, scores: List[Double])

def parseToStudent(line: String): Student = {
val fields = line.trim.split("\s+")
Student(fields(0), fields(1), fields.drop(2).map(_.toDouble).toList)
}

def analyze(data: List[String]): Unit = {
val courseNames = data.head.split("\s+").drop(2).toList
val students = data.tail.map(parseToStudent)

// 统计函数
def statsFor(genderFilter: Student => Boolean): List[(String, Double, Double, Double)] = {
  val filtered = students.filter(genderFilter)
  
  courseNames.zipWithIndex.map { case (course, idx) =>
    val scores = filtered.map(_.scores(idx))
    val avg = scores.sum / scores.length
    val min = scores.min
    val max = scores.max
    (course, avg, min, max)
  }
}

def printStats(title: String, stats: List[(String, Double, Double, Double)]): Unit = {
  println(s"\ncourse   average  min  max $title")
  stats.foreach { case (course, avg, min, max) =>
    println(f"$course: $avg%7.2f $min%6.2f $max%6.2f")
  }
}

println("course   average  min  max")
printStats("", statsFor(_ => true))
printStats("(males)", statsFor(_.gender == "male"))
printStats("(females)", statsFor(_.gender == "female"))

}

def test(): Unit = {
println("=== 使用case class版本 ===")

val sample1 = List(
  "Id gender Math English Physics",
  "301610 male 80 64 78",
  "301611 female 65 87 58"
  // 可以添加更多数据
)

analyze(sample1.take(10)) // 只测试前10行

}
}

image

image