约瑟夫斯问题_关于约瑟夫斯问题的反馈

约瑟夫斯问题

我上周的文章是关于解决Kotlin的约瑟夫斯问题的。 为了便于比较,这是我最初编写的版本:

classSoldier(valposition:Int){

    varstate=State.Living
    lateinitvarnext:Soldier

    funsuicide(){
        state=State.Dead
    }

    funisDead()=state==State.Dead
}

enumclassState{
    Living,Dead
}

classCircle(privatevalsize:Int,privatevalstep:Int){

    privatevalfirst=Soldier(0)

    init{
        varperson=first
        while(person.position<size-1){
            person=createNext(person)
        }
        vallast=person
        last.next=first
    }

    privatefuncreateNext(soldier:Soldier):Soldier{
        valnew=Soldier(soldier.position+1)
        soldier.next=new
        returnnew
    }

    funfindSurvivor():Soldier{
        varsoldier:Soldier=first
        varnumberOfDead=0

        while(numberOfDead<size-1){
            varcount:Int=0
            while(count<step){
                soldier=nextLivingSoldier(soldier)
                count++
            }
            soldier.suicide()
            numberOfDead++
        }
        returnnextLivingSoldier(soldier)
    }

    privatefunnextLivingSoldier(soldier:Soldier):Soldier{
        varcurrentSoldier=soldier.next
        while(currentSoldier.isDead()){
            currentSoldier=currentSoldier.next
        }

        returncurrentSoldier
    }
}

帖子以一个开放的问题结尾:代码是正确的方法吗? 特别是:

  • 代码是惯用的Kotlin吗?
  • 缺少for表示与var while使用
  • 我个人喜欢太多的可变性( var

我收到了来自社区的许多不同反馈,包括JetBrains的Ilya Ryzhenkov,CédricBeust,Peter Somerhoff和GaëtanZoritchak。 多谢你们!

我认为最有趣的是与Gaëtan最初的Gist略有修改的版本:

classSoldier(valposition:Int,varstate:State=State.Living){

    funsuicide(){
        state=State.Dead
    }

    funisAlive()=state==State.Living
}

enumclassState{
    Living,Dead
}

classCircle(valsize:Int,valstep:Int){

    valsoldiers=Array(size,{Soldier(it)}).toList()

    funfindSurvivor():Soldier{
        varsoldier=soldiers.first()
        (2..size).forEach{
            (1..step).forEach{
                soldier=soldier.nextLivingSoldier()
            }
            soldier.suicide()
        }
        returnsoldier.nextLivingSoldier()
    }

   tailrecprivatefunSoldier.nextLivingSoldier():Soldier=
       if(next().isAlive())
           next()
       else
           next().nextLivingSoldier()

    privatefunSoldier.next()=soldiers.get(
        if(position==size-1)
            0
        else
            position+1
    )
}

我非常喜欢此代码,因为它感觉更像Kotlin。 改进很多。

  • 代码更短,不会损失任何可读性
  • 这是完全的功能,这里只有一个var涉及:
    • 2个while循环及其关联的var计数器已由Int范围内的简单forEach替换。
    • 链接Soldier实例不是通过next()方法在Soldier类本身中进行处理,而是通过包含的Circle 因此,一个简单的后备数组可以存储它们,并且不需要带有可变变量的自定义代码。
  • 递归的 nextLivingSoldier()函数已使用tailrec进行“注释”,以便编译器运行其优化魔术。
  • Soldier类不知道它的容器Circle size ,因此使用它的功能已经在内部移动Circle类为扩展函数的Soldier类。 这是Kotlin扩展功能的绝佳用法。

这种经验使我坚信,仅阅读一种语言是不够的。 要真正做到这一点,应该采取以下步骤:

  1. 显然,学习该语言的语法-及其API,
  2. 用这种语言编写解决方案或应用的代码,
  3. 要求反馈,
  4. 阅读,分析和理解反馈,
  5. 冲洗并重复。

翻译自: https://blog.frankel.ch/feedback-jospehus-problem/

约瑟夫斯问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值