多段階選抜 (Swift)


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

Swift5で、yieldが使えるようになったようです。が、_read/_modifyアクセサ限定な上に、Pythonの[contextmanager](https://docs.python.org/ja/3/library/contextlib.html#contextlib.contextmanager)レベルのことしかできないようです(複数回yieldすらできない)。

**私としては少々キレかかってしまいました、、お恥ずかしい。**

まずはRuby版を、ループ末尾でyieldするように変換。

```rb
def drop_prev(check,prev)
	return to_enum(:drop_prev,check,prev) if !block_given?
	a=nil
	b=prev.next
	loop{
		a,b=b,prev.next
		yield a if !check[b]
	}
end
def drop_next(check,prev)
	return to_enum(:drop_next,check,prev) if !block_given?
	first=true
	a=nil
	b=nil
	loop{
		a,b=b,prev.next
		(first=false;yield b) if (first || !check[a])
	}
end
def drop_n(check,n,prev)
	return to_enum(:drop_n,check,n,prev) if !block_given?
	i=0
	loop{
		i+=1
		a=prev.next
		yield a if !check[i,n]
	}
end
```

これであれば、yieldなしに書けそうです！

\# にしても、`A!=B`と書くとdereference A assign Bと解釈されるので、`<>`演算子を定義したほうが早いっていうね…

```swift:tyama_hena24_enum.swift
//usr/bin/env swift $0 $@;exit

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

precedencegroup PowerPrecedence {
	associativity: right
	higherThan: MultiplicationPrecedence
}
infix operator <>: ComparisonPrecedence
infix operator ≠: ComparisonPrecedence
infix operator ≤: ComparisonPrecedence
infix operator ≥: ComparisonPrecedence
infix operator **: PowerPrecedence
public func <> <T: Equatable>(lhs: T, rhs: T) -> Bool{return lhs != rhs}
public func ≠ <T: Equatable>(lhs: T, rhs: T) -> Bool{return lhs != rhs}
public func ≤ <T: Comparable>(lhs: T, rhs: T) -> Bool{return lhs <= rhs}
public func ≥ <T: Comparable>(lhs: T, rhs: T) -> Bool{return lhs >= rhs}
public func ** <T: Numeric>(lhs: T, rhs: Int64) -> T{
	var x = lhs
	var k = rhs
	var e = 1 as T
	while k>0{
		if k%2>0 {e*=x}
		x*=x
		k/=2
	}
	return e
}

func isqrt(_ n: Int64) -> Int64{
	if n<=0 {return 0}
	if n<4 {return 1}
	var x: Int64 = 0
	var y: Int64 = n
	while x<>y && x+1<>y {
		x = y
		y = (n/y+y)/2
	}
	return x
}
func icbrt(_ n: Int64) -> Int64{
	if n<0 {return -icbrt(-n)}
	if n==0 {return 0}
	if n<8 {return 1}
	var x: Int64 = 0
	var y: Int64 = n
	while x<>y && x+1<>y {
		x = y
		y = (n/y/y+y*2)/3
	}
	return x
}

class generate: Sequence, IteratorProtocol{
	var i: Int64 = 0
	func next() -> Int64?{
		i += 1
		return i
	}
}
class drop_prev: Sequence, IteratorProtocol{
	var prev: AnyIterator<Int64>
	var check: (Int64) -> Bool
	var a: Int64 = 0
	var b: Int64 = 0
	init(_ check_: @escaping (Int64) -> Bool, _ prev_: AnyIterator<Int64>){
		check = check_
		prev = prev_
		b = prev.next()!
	}
	func next() -> Int64?{
		while true{
			a = b
			b = prev.next()!
			if !check(b){
				return a
			}
		}
	}
}
class drop_next: Sequence, IteratorProtocol{
	var prev: AnyIterator<Int64>
	var check: (Int64) -> Bool
	var first: Bool = true
	var a: Int64 = 0
	var b: Int64 = 0
	init(_ check_: @escaping (Int64) -> Bool, _ prev_: AnyIterator<Int64>){
		check = check_
		prev = prev_
	}
	func next() -> Int64?{
		while true{
			a = b
			b = prev.next()!
			if first || !check(a){
				first = false
				return b
			}
		}
	}
}
class drop_n: Sequence, IteratorProtocol{
	var prev: AnyIterator<Int64>
	var check: (Int64,Int64) -> Bool
	var n: Int64
	var i: Int64 = 0
	init(_ check_: @escaping (Int64,Int64) -> Bool, _ n_: Int64, _ prev_: AnyIterator<Int64>){
		check = check_
		prev = prev_
		n = n_
	}
	func next() -> Int64?{
		while true{
			i += 1
			let a = prev.next()!
			if !check(i,n){
				return a
			}
		}
	}
}
	
func is_sq(_ n: Int64) -> Bool{return isqrt(n)**2==n}
func is_cb(_ n: Int64) -> Bool{return icbrt(n)**3==n}
func is_multiple(_ i: Int64, _ n: Int64) -> Bool{return i%n==0}
func is_le(_ i: Int64, _ n: Int64) -> Bool{return i<=n}
var f: [Character: (AnyIterator<Int64>) -> AnyIterator<Int64>] = [:]
f["S"]={AnyIterator(drop_next(is_sq,$0))}
f["s"]={AnyIterator(drop_prev(is_sq,$0))}
f["C"]={AnyIterator(drop_next(is_cb,$0))}
f["c"]={AnyIterator(drop_prev(is_cb,$0))}
f["h"]={AnyIterator(drop_n(is_le,100,$0))}
for i in 2...9{f[Character(String(i))]={AnyIterator(drop_n(is_multiple,Int64(i),$0))}}

while true{
	let s = readLine()
	if s==nil{break}
	var g: AnyIterator<Int64> = AnyIterator(generate())
	for c in s!{
		g = f[c]!(g)
	}
	var c = 0
	for e in g{
		c += 1
		print(e,terminator:c==10 ? "\n" : ",")
		if c==10{break}
	}
}
```

しかし。。こうできちゃった以上はイテレータの概念がない言語でも(OOであれば)書けるってことなんだよなぁ…

\# 正直IteratorProtocolにちゃんと準拠した書き方を調べるほうが大変だったんですけどね--;;;