多段階選抜 (Nim)

多段階選抜
解答日
シリーズ: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


tyama_hena24_enum.nim

#[

/usr/bin/env nim c --nimcache:$HOME/.nimcache --opt:speed --run $0 $@;exit
#]#
proc isqrt(n:int):int =
if n<=0: return 0
if n<4: return 1
var x=0
var y=n
while x!=y and x+1!=y:
x=y
y=(n div y+y) div 2
return x

proc 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 and x+1!=y:
x=y
y=(n div y div y+y*2) div 3
return x

proc generate():iterator:int =
return iterator:int =
var i=1
while true:
yield i
i+=1

proc drop_prev(check:proc(x:int):bool,prev:iterator:int):iterator:int =
return iterator:int =
var a=prev()
var b=prev()
while true:
if not check(b): yield a
a=b
b=prev()

proc drop_next(check:proc(x:int):bool,prev:iterator:int):iterator:int =
return iterator:int =
var a=prev()
var b=prev()
yield a
while true:
if not check(a): yield b
a=b
b=prev()

proc drop_n(check:proc(x:int,y:int):bool,n:int,prev:iterator:int):iterator:int =
return iterator:int =
var i=0
while true:
i+=1
var a=prev()
if not check(i,n): yield a

proc is_sq(n:int):bool =
var x=isqrt(n)
return x*x==n

proc is_cb(n:int):bool =
var x=icbrt(n)
return x*x*x==n

proc is_multiple(i:int,n:int):bool = i mod n==0
proc is_le(i:int,n:int):bool = i<=n

import tables
var f={
'S':proc(e:iterator:int):iterator:int = drop_next(is_sq,e),
's':proc(e:iterator:int):iterator:int = drop_prev(is_sq,e),
'C':proc(e:iterator:int):iterator:int = drop_next(is_cb,e),
'c':proc(e:iterator:int):iterator:int = drop_prev(is_cb,e),
'h':proc(e:iterator:int):iterator:int = drop_n(is_le,100,e),
'2':proc(e:iterator:int):iterator:int = drop_n(is_multiple,2,e),
'3':proc(e:iterator:int):iterator:int = drop_n(is_multiple,3,e),
'4':proc(e:iterator:int):iterator:int = drop_n(is_multiple,4,e),
'5':proc(e:iterator:int):iterator:int = drop_n(is_multiple,5,e),
'6':proc(e:iterator:int):iterator:int = drop_n(is_multiple,6,e),
'7':proc(e:iterator:int):iterator:int = drop_n(is_multiple,7,e),
'8':proc(e:iterator:int):iterator:int = drop_n(is_multiple,8,e),
'9':proc(e:iterator:int):iterator:int = drop_n(is_multiple,9,e),
}.toTable()
## var handling is strict like Rust ##

import strutils
var s=""
while readLine(stdin,s):
var z=generate()
for c in s.strip():
z=f[c](z)
for i in 0..9:
if i>0: write(stdout,',')
write(stdout,z())
writeLine(stdout,"")
flushFile(stdout)