多段階選抜 (Kotlin)

多段階選抜
解答日
シリーズ:yieldの練習/ジェネレータを入れ子に/整数平方根・立方根の実装

問題
 

http://nabetani.sakura.ne.jp/hena/ord24eliseq/
https://qiita.com/Nabetani/items/1c83005a854d2c6cbb69

Ruby
2014/8/2(当日)
https://qiita.com/cielavenir/items/9f15e29b73ecf98968a5

C#/Python
2014/8/4
https://qiita.com/cielavenir/items/a1156e6a4f71ddbe5dcb

 
ここから上はdrop_prev_square/drop_prev_cubicをまとめる前の答案

Go/C#/Ruby/Python
2014/8/5
https://qiita.com/cielavenir/items/2a685d3080862f2c2c47

PHP/JavaScript
2014/9/9
https://qiita.com/cielavenir/items/28d613ac3823afbf8407

VB
2014/9/10
https://qiita.com/cielavenir/items/cb7266abd30eadd71c04

D
2015/12/21
https://qiita.com/cielavenir/items/47c9e50ee60bef2847ec

Perl
2017/3/10
https://qiita.com/cielavenir/items/6dfbff749d833c0fd423

Lua
2017/3/13
https://qiita.com/cielavenir/items/c60fe7e8da73487ba062

C++20(TS)
2017/3/15

https://qiita.com/cielavenir/items/e1129ca185008f49cbab (MSVC)
https://qiita.com/cielavenir/items/1cfa90d73d11bb7dc3d4 (clang)

F#
2017/3/17
https://qiita.com/cielavenir/items/a698d6a26824ff53de81

Boo/Nemerle
2017/5/13
https://qiita.com/cielavenir/items/e2a783f0fe4b0fe0ed48

Perl6
2017/5/15
https://qiita.com/cielavenir/items/656ea17fa96c865c4498

Kotlin
2017/5/25
https://qiita.com/cielavenir/items/9c46ce8d9d12e51de285

Crystal
2018/5/8
https://qiita.com/cielavenir/items/1815bfa6a860fd1f90db

MoonScript
2018/6/16
https://qiita.com/cielavenir/items/8b03cce0386f4537b5ad

Julia/Rust
2018/12/20
https://qiita.com/cielavenir/items/3ddf72b06d625da0c4a5

Nim
2018/12/26
https://qiita.com/cielavenir/items/5728944867e609fd52a7

Tcl
2018/12/31
https://qiita.com/cielavenir/items/76cbd9c2022b48c9a2c9

Pascal/Cobra
2019/1/16
https://qiita.com/cielavenir/items/81b81baf8dfc1f877903

Icon
2019/1/17
https://qiita.com/cielavenir/items/889622dcc721f5a4da24

(icbrtの実装に関する)補題
2017/5/11
整数除算であってもn/(x*y)はn/x/yに等しい(ことの証明)
https://qiita.com/cielavenir/items/21a6711afd6be8c18c55

(これまでの中ではあれげな答案が続いていたので)まあまあきれいに書けたほうか。


hena24_enum.kt

// http://qiita.com/Nabetani/items/1c83005a854d2c6cbb69

// http://nabetani.sakura.ne.jp/hena/ord24eliseq/

import kotlin.sequences.*
fun isqrt(n:Int):Int{
if(n<=0)return 0
if(n<4)return 1
var x=0
var y=n
while(x!=y&&x+1!=y){x=y;y=(n/y+y)/2}
return x
}
fun icbrt(n:Int):Int{
if(n<0)return icbrt(-n)
if(n==0)return 0
if(n<8)return 1
var x=0
var y=n
while(x!=y&&x+1!=y){x=y;y=(n/y/y+y*2)/3}
return x
}
fun is_sq(n:Int):Boolean{
val x=isqrt(n)
return x*x==n
}
fun is_cb(n:Int):Boolean{
val x=icbrt(n)
return x*x*x==n
}
fun is_multiple(i:Int,n:Int):Boolean{return i%n==0}
fun is_le(i:Int,n:Int):Boolean{return i<=n}

fun generate():Sequence<Int>{
return sequence{
var i=1
while(true){
yield(i)
i+=1
}
}
}
fun drop_prev(check:(Int)->Boolean,_prev:Sequence<Int>):Sequence<Int>{
return sequence{
val prev=_prev.iterator()
var a=prev.next()
var b=prev.next()
while(true){
if(!check(b))yield(a)
a=b
b=prev.next()
}
}
}
fun drop_next(check:(Int)->Boolean,_prev:Sequence<Int>):Sequence<Int>{
return sequence{
val prev=_prev.iterator()
var a=prev.next()
var b=prev.next()
yield(a)
while(true){
if(!check(a))yield(b)
a=b
b=prev.next()
}
}
}
fun drop_n(check:(Int,Int)->Boolean,n:Int,_prev:Sequence<Int>):Sequence<Int>{
return sequence{
val prev=_prev.iterator()
var i=0
while(true){
i+=1
val a=prev.next()
if(!check(i,n))yield(a)
}
}
}
fun main(args:Array<String>){
val f: HashMap<Char,(Sequence<Int>)->Sequence<Int>> = hashMapOf(
'S' to {e->drop_next(::is_sq,e)},
's' to {e->drop_prev(::is_sq,e)},
'C' to {e->drop_next(::is_cb,e)},
'c' to {e->drop_prev(::is_cb,e)},
'h' to {e->drop_n(::is_le,100,e)}
)
for(i in 2..9){
f[('0'+i).toChar()] = fun(e)=drop_n(::is_multiple,i,e)
//{e->drop_n(::is_multiple,i,e)} //both are OK
}
var line=readLine()
while(line!=null){
var first=true;
//cS => f['S']!!(f['c']!!(generate()))
for(n in line.toCharArray().fold(generate()){
s,e->f[e]!!(s) //nullable? yippee
}.take(10)){
if(!first)print(',')
first=false
print(n)
}
println()
System.out.flush()
line=readLine()
}
}



181024追記

コルーチン周りをKotlin 1.3(以降)のAPIにしました。Kotlin Nativeでコンパイルできることを確認しました。