多段階選抜 (Tcl)


|多段階選抜|解答日|シリーズ:yieldの練習/ジェネレータを入れ子に/整数平方根・立方根の実装|
|:--|:--|:--|
|問題|　|http://nabetani.sakura.ne.jp/hena/ord24eliseq/<br>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)<br>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|
|Swift|2020/5/31|https://qiita.com/cielavenir/items/3b0b84a218e35d538f7f|
|Java/Groovy/Scala|2020/5/31|https://qiita.com/cielavenir/items/7f058203a8fd03b65870|
|V|2020/10/17|https://qiita.com/cielavenir/items/df30a6c101a97a713df5|
|Zig/Zen|2020/10/17|https://qiita.com/cielavenir/items/9cced9e4a94dcd70df0f|
|Pike|2020/11/2|https://qiita.com/cielavenir/items/3a8248f41611302b34fd|
|Vala/Smalltalk|2020/11/29|https://qiita.com/cielavenir/items/085dabe593cd916af5e8|
|Objective-C|2020/11/30|https://qiita.com/cielavenir/items/a1736e38789a3dd5cc5a|
|Ruby(Ractor)|2021/1/2|https://qiita.com/cielavenir/items/f493c6d512b63cc571cc|
|Python(_xxsubinterpreters)|2021/6/29|https://qiita.com/cielavenir/items/f1f581a055db918954f1|
|Falcon/Scheme|2021/9/5|https://qiita.com/cielavenir/items/c13d12cf44f0d17f4a94|
|Clojure/Lisp|2021/9/7|https://qiita.com/cielavenir/items/7458ba076f4e5bc0f196|
|(icbrtの実装に関する)補題|2017/5/11|整数除算であってもn/(x*y)はn/x/yに等しい(ことの証明)<br>https://qiita.com/cielavenir/items/21a6711afd6be8c18c55|

```tcl:tyama_hena24_enum.tcl
#!/usr/bin/env tclsh
#http://qiita.com/Nabetani/items/1c83005a854d2c6cbb69
#http://nabetani.sakura.ne.jp/hena/ord24eliseq/

### tclsh >= 8.6 ###

proc isqrt {n} {
	if {$n<=0} {return 0}
	if {$n<4} {return 1}
	set x 0
	set y $n
	while {$x!=$y&&$x+1!=$y} {
		set x $y
		set y [expr ($n/$y+$y)/2]
	}
	return $x
}

proc icbrt {n} {
	if {$n<0} {return -[icbrt -$n]}
	if {$n==0} {return 0}
	if {$n<8} {return 1}
	set x 0
	set y $n
	while {$x!=$y&&$x+1!=$y} {
		set x $y
		set y [expr ($n/$y/$y+$y*2)/3]
	}
	return $x
}

proc generate {g} {
	proc func {} {
		yield [info coroutine]
		set i 1
		while {true} {
			yield $i
			incr i
		}
	}
	coroutine $g func
}

proc drop_prev {g check prev} {
	proc func {check prev} {
		yield [info coroutine]
		set a [$prev]
		set b [$prev]
		while {true} {
			if {![$check $b]} {yield $a}
			set a $b
			set b [$prev]
		}
	}
	coroutine $g func $check $prev
}

proc drop_next {g check prev} {
	proc func {check prev} {
		yield [info coroutine]
		set a [$prev]
		set b [$prev]
		yield $a
		while {true} {
			if {![$check $a]} {yield $b}
			set a $b
			set b [$prev]
		}
	}
	coroutine $g func $check $prev
}

proc drop_n {g check n prev} {
	proc func {check n prev} {
		yield [info coroutine]
		set i 0
		while {true} {
			incr i
			set a [$prev]
			if {![$check $i $n]} {yield $a}
		}
	}
	coroutine $g func $check $n $prev
}

proc is_sq {n} {
	set x [isqrt $n]
	return [expr $x*$x==$n]
}

proc is_cb {n} {
	set x [icbrt $n]
	return [expr $x*$x*$x==$n]
}

proc is_multiple {i n} {return [expr $i%$n==0]}
proc is_le {i n} {return [expr $i<=$n]}

array set f {
	"S" {{g prev} {drop_next $g is_sq $prev}}
	"s" {{g prev} {drop_prev $g is_sq $prev}}
	"C" {{g prev} {drop_next $g is_cb $prev}}
	"c" {{g prev} {drop_prev $g is_cb $prev}}
	"h" {{g prev} {drop_n $g is_le 100 $prev}}
	"2" {{g prev} {drop_n $g is_multiple 2 $prev}}
	"3" {{g prev} {drop_n $g is_multiple 3 $prev}}
	"4" {{g prev} {drop_n $g is_multiple 4 $prev}}
	"5" {{g prev} {drop_n $g is_multiple 5 $prev}}
	"6" {{g prev} {drop_n $g is_multiple 6 $prev}}
	"7" {{g prev} {drop_n $g is_multiple 7 $prev}}
	"8" {{g prev} {drop_n $g is_multiple 8 $prev}}
	"9" {{g prev} {drop_n $g is_multiple 9 $prev}}
}
#2..9: Tcl does not have capturing.

set s [gets stdin]
while {$s!=""} {
	set lst [list hena24]
	generate [lindex $lst 0]
	for {set i 0} {$i < [string length $s]} {incr i} {
		set x [string index $s $i]
		lappend lst [lindex $lst $i]$x
		apply $f($x) [lindex $lst [expr $i+1]] [lindex $lst $i]
	}
	for {set j 0} {$j < 10} {incr j} {
		if {$j>0} {
			puts -nonewline ","
		}
		puts -nonewline [[lindex $lst $i]]
	}
	puts ""
	flush stdout
	set s [gets stdin]
}
```