zoukankan      html  css  js  c++  java
  • 《Scala编程》课程作业

    第一题、百元喝酒

    作业要求:每瓶啤酒2元,3个空酒瓶或者5个瓶盖可换1瓶啤酒。100元最多可喝多少瓶啤酒?(不允许借啤酒)

    思路:利用递归算法,一次性买完,然后递归算出瓶盖和空瓶能换的啤酒数

    /**
     * @author DOUBLEXI
     * @date 2021/8/17 15:33
     * @description
     *
     * 作业要求:每瓶啤酒2元,3个空酒瓶或者5个瓶盖可换1瓶啤酒。100元最多可喝多少瓶啤酒?
     * (不允许借啤酒)思路:利用递归算法,一次性买完,然后递归算出瓶盖和空瓶能换的啤酒数
     */
    object HundredBeer {
      /**
       * @param sumBeers  啤酒总数
       * @param bottle    剩余空瓶子数量
       * @param cap       剩余啤酒盖数量
       * @return  返回总啤酒总数
       */
      def beer(sumBeers: Int, bottle: Int, cap: Int): Int = {
        println(s"啤酒总数:$sumBeers,剩余空瓶子:$bottle,剩余啤酒盖:$cap")
        // 递归边界条件
        if (bottle < 3 && cap < 5) return sumBeers
        var b1 = bottle / 3       // 现有空瓶子能够兑换的啤酒数
        var b2 = bottle % 3       // 空瓶子兑换啤酒后,剩余的空瓶子
        var c1 = cap / 5          // 现有啤酒盖能够兑换的啤酒数
        var c2 = cap % 5          // 啤酒盖兑换啤酒后,剩余的空瓶子
        /*
        上面一顿兑换操作后,啤酒总数为:b1 + c1 + sumBeers
        剩余的空瓶子总数为:b1 + c1 + b2
        剩余的啤酒盖总数为:b1 + c1 + c2
        继续递归兑换
         */
        beer(b1 + c1 + sumBeers, b1 + c1 + b2, b1 + c1 + c2)
      }
    
      def main(args: Array[String]): Unit = {
        var sumBeers: Int = 100 / 2         // 初始化啤酒总数
        var bottle, cap : Int = sumBeers    // 初始化空瓶子数=啤酒盖数=啤酒总数
        val beers = beer(sumBeers, bottle, cap)   // 递归求能够喝到的啤酒总数
        println(s"100元最多可以喝$beers 瓶啤酒")
      }
    }

    运行结果如下:

    clipboard

    第二题、人机猜拳

        1.1 作业需求

            1. 选取对战角色

            2. 开始对战,用户出拳,与对手进行比较,提示胜负信息

            3. 猜拳结束算分,平局都加一分,获胜加二分,失败不加分

            4 . 循环对战,当输入“n”时,终止对战,并显示对战结果

            5. 游戏结束后显示得分

    如下图所示:

    1.2 作业分析

    分析业务逻辑,抽象出类、类的属性和方法,如下:

        1. 创建用户类User,定义类的属性(name,score)和类的方法(showFist())

        2. 创建计算机类Computer,定义类的属性(name,score)和类的方法(showFist())

        3. 实现计算机随机出拳

        4. 创建游戏类Game,定义类的属性(甲方玩家、乙方玩家、对战次数)

        5. 编写初始化方法、游戏开始方法

    1、编写用户类User

    /**
     * @author DOUBLEXI
     * @date 2021/8/17 16:45
     * @description
     */
    /**
     * 用户类User
     * @param name  用户名
     * @param score 用户得分
     */
    class User(var name: String, var score: Int) {
      var draw: Int = 0   // 平局数
      var defeat: Int = 0   // 败局数
      var victory: Int = 0  // 胜局数
    
      // 让用户自己出拳,输入1.剪刀 2.石头  3.布
      def showFist(): Int = {
        var fist = scala.io.StdIn.readInt()
        while (fist != 1 && fist != 2 && fist != 3) {
          println("输入不合法,请重新输入!!!")
          fist = scala.io.StdIn.readInt()
        }
        return fist
      }
    
    }

    2、编写电脑类Computer

    /**
     * @author DOUBLEXI
     * @date 2021/8/17 17:09
     * @description
     */
    /**
     * 电脑类
     * @param name  电脑名字
     * @param score 电脑得分
     */
    class Computer(var name: String, var score: Int) {
      var draw: Int = 0     // 电脑平局数
      var defeat: Int = 0   // 电脑败局数
      var victory: Int = 0  // 电脑胜局数
    
      /**
       * 随机出拳,1-3
       * @return 返回一个1-3的数字
       */
      def showFist(): Int = {
        scala.util.Random.nextInt(3) + 1
      }
    
    }

    3、编写游戏类Game

    /**
     * @author DOUBLEXI
     * @date 2021/8/17 17:11
     * @description
     */
    /**
     * 游戏类
     */
    class Game {
      var user: User = _            // 定义玩家
      var computer: Computer = _    // 定义电脑
      var battleNum: Int = _        // 定义对战次数
    
      /**
       * 游戏初始化方法
       */
      def gameInit(): Unit = {
        val motd =
          """
    ------------------欢迎进入游戏世界-----------------
    **************************************
    **************猜拳开始*****************
    **************************************
            """.stripMargin
        println(motd)                                         // 打印游戏欢迎信息
        println("请选择对战角色:(1.刘备  2.关羽  3.张飞)")       // 用户选择电脑的角色
        var roleNum = scala.io.StdIn.readInt()
        while (roleNum != 1 && roleNum != 2 && roleNum != 3) {
          println("没有这个选项,请重新输入!")
          roleNum = scala.io.StdIn.readInt()
        }
        val battleRole = roleNum match {
          case 1 => "刘备"
          case 2 => "关羽"
          case 3 => "张飞"
        }
        println(s"你选择了与${battleRole}对战")
        user = new User("游客", 0)              // 初始化玩家信息
        computer = new Computer(s"$battleRole", 0)  // 初始化电脑信息
        battleNum = 0                                           // 初始化对战信息
      }
    
      /**
       * 游戏主程,游戏开始方法
       * 循环对战,直到输入n终止
       */
      def startGame(): Unit = {
        var isExist = false
        var isStartNext: Char = 'y'
        // 循环对战
        while (!isExist) {
          battleNum += 1;                                     // 对战次数+1
          // 玩家出拳
          println("请出拳!1.剪刀 2.石头  3.布")
          var userFist = user.showFist()
          userFist match {
            case 1 => println("你出拳:剪刀")
            case 2 => println("你出拳:石头")
            case 3 => println("你出拳:布")
          }
          // 电脑出拳
          println(s"${computer.name}出拳!")
          var computerFist = computer.showFist()
          computerFist match {
            case 1 => println(s"${computer.name}出拳:剪刀")
            case 2 => println(s"${computer.name}出拳:石头")
            case 3 => println(s"${computer.name}出拳:布")
          }
          // 调用judge方法,判断胜负
          judge(userFist, computerFist)
          // 根据用户输入判断是否开启下一轮游戏,n退出
          println("是否开始下一轮(y / n)")
          isStartNext = scala.io.StdIn.readChar()
          while (isStartNext != 'n' && isStartNext != 'N' && isStartNext != 'Y' && isStartNext != 'y') {
            println("您的输入不正确,请重新输入!")
            isStartNext = scala.io.StdIn.readChar()
          }
          if (isStartNext =='n'|| isStartNext == 'N') isExist = true
        }
        println("退出游戏!")
        // 打印得分成绩
        echoResult
      }
    
      /**
       * 判断猜拳胜负
       * @param userFist  用户出拳
       * @param computerFist  电脑出拳
       */
      def judge(userFist: Int, computerFist: Int): Unit = {
        val judgeNum = userFist match {
          case 1 => if (computerFist == 1)  0 else if (computerFist == 2) -1 else  1
          case 2 => if (computerFist == 1)  1 else if (computerFist == 2)  0 else  -1
          case 3 => if (computerFist == 1)  -1 else if (computerFist == 2) 1 else  0
        }
    
        if (judgeNum == 0) {
          println("结果:和局! 下次继续努力!")
          user.score += 1
          user.draw += 1
          computer.score += 1
          computer.draw += 1
        } else if (judgeNum == 1) {
          println("结果:恭喜,你赢啦!")
          user.score += 2
          user.victory += 1
          computer.defeat += 1
        } else {
          println("结果:你输了,下次继续努力!")
          user.defeat += 1
          computer.victory += 1
        }
      }
    
      /**
       * 打印得分成绩
       */
      def echoResult(): Unit = {
        println("---------------------------------------------------------")
        println(s"${user.name} VS ${computer.name}")
        println(s"对战次数${battleNum}次")
        println()
        println()
        println("姓名\t等分\t胜局\t和局\t负局")
        println(s"${user.name}\t${user.score}\t\t${user.victory}\t\t${user.draw}\t\t${user.defeat}")
        println(s"${computer.name}\t${computer.score}\t\t${computer.victory}\t\t${computer.draw}\t\t${computer.defeat}")
      }
    }
    
    /**
     * 游戏主程入口
     */
    object Game {
      def main(args: Array[String]): Unit = {
        val game = new Game             // 定义一个游戏对象
        game.gameInit()                 // 游戏初始化
        println("要开始么?y/n")
        var isStart = scala.io.StdIn.readChar()
        while (isStart != 'Y' && isStart != 'y' && isStart != 'n' && isStart != 'N') {
          println("没有这个选项,请重新输入!")
          isStart = scala.io.StdIn.readChar()
        }
        // 开始游戏
        if (isStart == 'Y' || isStart == 'y') game.startGame
      }
    }

    运行结果如下:

    clipboard

    不合法输入:

    clipboard

    打印得分:

    clipboard


    第三题、用户位置时长统计

    现有如下数据需要处理:

        字段:用户ID,位置ID,开始时间,停留时长(分钟)

    4行样例数据:

    UserA,LocationA,8,60

    UserA,LocationA,9,60

    UserB,LocationB,10,60

    UserB,LocationB,11,80

    样例数据中的数据含义是:用户UserA,在LocationA位置,从8点开始,停留了60钟

    处理要求:

        1、对同一个用户,在同一个位置,连续的多条记录进行合并

        2、合并原则:开始时间取最早时间,停留时长累计求和

    答:算法如下:

    1、定义一个样例类,用于存储每个用户的浏览数据

    /**
     * 定义一个样例类:装载用户时长数据
     * @param userName  用户名
     * @param location  用户位置
     * @param startTime 用户开始浏览时间
     * @param duration  用户本次浏览时长
     */
    case class UserInfo(userName:String, location:String, startTime:Int, duration:Int)

    2、在object主程序里,定义一个列表,用于存储各个用户的浏览信息。

    // 定义一个列表,装载各个用户的时长数据
    val userInfoList:List[UserInfo]  = List(
      UserInfo("UserA", "LocationA", 8, 60),
      UserInfo("UserA", "LocationA", 9, 60),
      UserInfo("UserB", "LocationB", 10, 60),
      UserInfo("UserB", "LocationB", 11, 80)
    )

    3、接下来就是要对该用户浏览信息的列表数据做处理。

    这里使用scala的算子来作数据处理。

    因为要对同一个用户、同一个位置的多条记录做合并,所以用到groupby算子,把这两个字段提出来作为一个key,然后把数据做聚合

    // 因为要对同一个用户,同一个位置的数据做合并,所以把这两个字段提出来,一起作为key聚合
    val userMap = userInfoList.groupBy(t=>t.userName + ',' + t.location)
    println(s"userMap: $userMap")

    聚合后userMap数据为:

    userMap: Map(UserB,LocationB -> List(UserInfo(UserB,LocationB,10,60), UserInfo(UserB,LocationB,11,80)), UserA,LocationA -> List(UserInfo(UserA,LocationA,8,60), UserInfo(UserA,LocationA,9,60)))

    对聚合后的数据,按照startTime排序,方便后面取最早的时间

    // 对聚合后的数据,按照startTime排序
    val orderByUserMap = userMap.mapValues(t => t.sortBy(x=>x.startTime))
    println(s"orderByUserMap: $orderByUserMap")

    排完序后的数据为:

    orderByUserMap: Map(UserB,LocationB -> List(UserInfo(UserB,LocationB,10,60), UserInfo(UserB,LocationB,11,80)), UserA,LocationA -> List(UserInfo(UserA,LocationA,8,60), UserInfo(UserA,LocationA,9,60)))

    取得最早的时间,并统计浏览时长之和

    var firstTime = 0
    
    // totalMap: Map(UserB,LocationB -> 140, UserA,LocationA -> 120)
    val totalMap = orderByUserMap.mapValues( t => {
      // 将相同用户、相同位置下,最早的时间的作为firstTime
      firstTime = t.head.startTime
      // 时长字段相加,并作为totalMap的value返回
      var sum = t.map(x=> x.duration).sum
      sum
    })
    println(s"totalMap: $totalMap")

    统计完的结果map如下:

    totalMap: Map(UserB,LocationB -> 140, UserA,LocationA -> 120)

    最后,再重新组合,打印最终结果数据:

    // 重新组合数据,打印最终结果
    /**
     * datas就是totalMap的key,也就是(userName,location)
     * sumTIme就是totalMap的value,也就是上面统计的sum
     */
    totalMap.foreach{
      case (datas, sumTime) => println(s"$datas,$firstTime,$sumTime")
    }

    最终结果如下:

    UserB,LocationB,10,140
    UserA,LocationA,8,120

    合并总的程序如下:

    /**
     * @author DOUBLEXI
     * @date 2021/8/18 15:16
     * @description
     */
    
    /**
     * 定义一个样例类:装载用户时长数据
     * @param userName  用户名
     * @param location  用户位置
     * @param startTime 用户开始浏览时间
     * @param duration  用户本次浏览时长
     */
    case class UserInfo(userName:String, location:String, startTime:Int, duration:Int)
    
    object UserLocationDurationCount {
      def main(args: Array[String]): Unit = {
        // 定义一个列表,装载各个用户的时长数据
        val userInfoList:List[UserInfo]  = List(
          UserInfo("UserA", "LocationA", 8, 60),
          UserInfo("UserA", "LocationA", 9, 60),
          UserInfo("UserB", "LocationB", 10, 60),
          UserInfo("UserB", "LocationB", 11, 80)
        )
    
        // 因为要对同一个用户,同一个位置的数据做合并,所以把这两个字段提出来,一起作为key聚合
        val userMap = userInfoList.groupBy(t=>t.userName + ',' + t.location)
        println(s"userMap: $userMap")
        // 对聚合后的数据,按照startTime排序
        val orderByUserMap = userMap.mapValues(t => t.sortBy(x=>x.startTime))
        println(s"orderByUserMap: $orderByUserMap")
    
        var firstTime = 0
    
        // totalMap: Map(UserB,LocationB -> 140, UserA,LocationA -> 120)
        val totalMap = orderByUserMap.mapValues( t => {
          // 将相同用户、相同位置下,最早的时间的作为firstTime
          firstTime = t.head.startTime
          // 时长字段相加,并作为totalMap的value返回
          var sum = t.map(x=> x.duration).sum
          sum
        })
        println(s"totalMap: $totalMap")
    
        // 重新组合数据,打印最终结果
        /**
         * datas就是totalMap的key,也就是(userName,location)
         * sumTIme就是totalMap的value,也就是上面统计的sum
         */
        totalMap.foreach{
          case (datas, sumTime) => println(s"$datas,$firstTime,$sumTime")
        }
      }
    }

    运行结果如下:

    clipboard

  • 相关阅读:
    Elasticsearch入门讲解
    NLP入门(九)词义消岐(WSD)的简介与实现
    NLP入门(八)使用CRF++实现命名实体识别(NER)
    NLP入门(七)中文预处理之繁简体转换及获取拼音
    NLP入门(六) pyltp的介绍与使用 转自:jclian91
    NLP入门(五)用深度学习实现命名实体识别(NER) 转自:jclian91
    NLP入门(四)命名实体识别(NER):jclian91
    NLP(三)词形还原(Lemmatization) 转自jclian91
    NLP(二)探究TF-IDF的原理(转自:jclian91)
    NLP(一)词袋模型及句子相似度(转自:jclian91)
  • 原文地址:https://www.cnblogs.com/doublexi/p/15609427.html
Copyright © 2011-2022 走看看