多段階選抜 (C#/Python)(旧)


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

C#/Pythonいずれも無限リスト対応。

## C# ##

発表会中に、「IEnumerableを使えばできるかも」と言ってしまったので、言い出しっぺの法則。

cbrtはDllImportのため環境依存。
イテレータの作り方は増井氏の最短経路の計算( http://qiita.com/cielavenir/items/ac96da5e3040c2edb78c )でやったけど、やはり面倒。

ところで、C#でできるってことはVB2012以降でも可能ってことだけど、労力が半端無いので止め。上に挙げた最短経路の計算のソースをうまく使えば作れるかも。とのみ。

<del>あとはJava。でもStreamはようわからんのよね。</del>
Stream.generateはコルーチンでないのでだめそうです。てかEnumeratorに該当するものがない気がする。

```csharp:hena24.cs
using System;
using System.Linq;
using System.Collections.Generic;
using System.Runtime.InteropServices;

class Hena24{
	[DllImport("c")]
	private extern static double cbrt(double d);

	static private IEnumerable<int> generate(){
		int i=1;
		for(;;){
			yield return i;
			i+=1;
		}
	}
	static private IEnumerable<int> drop_prev_square(IEnumerable<int> _prev){
		IEnumerator<int> prev=_prev.GetEnumerator();
		prev.MoveNext();
		int a=prev.Current;
		prev.MoveNext();
		int b=prev.Current;
		for(;;){
			int x=(int)Math.Sqrt(b);
			if(x*x!=b)yield return a;
			a=b;
			prev.MoveNext();
			b=prev.Current;
		}
	}
	static private IEnumerable<int> drop_next_square(IEnumerable<int> _prev){
		IEnumerator<int> prev=_prev.GetEnumerator();
		prev.MoveNext();
		int a=prev.Current;
		prev.MoveNext();
		int b=prev.Current;
		yield return a;
		for(;;){
			int x=(int)Math.Sqrt(a);
			if(x*x!=a)yield return b;
			a=b;
			prev.MoveNext();
			b=prev.Current;
		}
	}
	static private IEnumerable<int> drop_prev_cubic(IEnumerable<int> _prev){
		IEnumerator<int> prev=_prev.GetEnumerator();
		prev.MoveNext();
		int a=prev.Current;
		prev.MoveNext();
		int b=prev.Current;
		for(;;){
			int x=(int)cbrt(b);
			if(x*x*x!=b)yield return a;
			a=b;
			prev.MoveNext();
			b=prev.Current;
		}
	}
	static private IEnumerable<int> drop_next_cubic(IEnumerable<int> _prev){
		IEnumerator<int> prev=_prev.GetEnumerator();
		prev.MoveNext();
		int a=prev.Current;
		prev.MoveNext();
		int b=prev.Current;
		yield return a;
		for(;;){
			int x=(int)cbrt(a);
			if(x*x*x!=a)yield return b;
			a=b;
			prev.MoveNext();
			b=prev.Current;
		}
	}
	static private IEnumerable<int> drop_num(int n,IEnumerable<int> _prev){
		IEnumerator<int> prev=_prev.GetEnumerator();
		int i=0;
		for(;;){
			i++;
			prev.MoveNext();
			int a=prev.Current;
			if(i%n!=0)yield return a;
		}
	}
	static private IEnumerable<int> drop_cnt(int n,IEnumerable<int> _prev){
		IEnumerator<int> prev=_prev.GetEnumerator();
		int i=0;
		for(;;){
			i++;
			prev.MoveNext();
			int a=prev.Current;
			if(i>n)yield return a;
		}
	}
	static void Main(){
		var f=new Dictionary<char,Func<IEnumerable<int>,IEnumerable<int>>>(){
			{'S',drop_next_square},
			{'s',drop_prev_square},
			{'C',drop_next_cubic},
			{'c',drop_prev_cubic},
			{'h',e => drop_cnt(100,e)},
		};
		for(int i=2;i<10;i++){
			int j=i; //寿命が短いスコープを作ることで、ラムダ式のキャプチャでバグらないようにする。
			f[(char)('0'+j)] = e=>drop_num(j,e);
		}
		string line;
		for(;(line=Console.ReadLine())!=null;){
			bool first=true;
			foreach(int n in line.Aggregate(generate(),(s,e)=>f[e](s)).Take(10)){
				if(!first)Console.Write(',');
				first=false;
				Console.Write(n);
			}
			Console.WriteLine();
		}
	}
}
```

## Python

おまけ程度ですが。
基本、Ruby版と同じロジック。
cbrtはscipyを使用。
Pythonは何もしないと勝手に外部イテレータになるのが嬉しいですね。

```py:hena24_enum.py
#!/usr/bin/env python
#http://qiita.com/Nabetani/items/1c83005a854d2c6cbb69
#http://nabetani.sakura.ne.jp/hena/ord24eliseq/
import sys
import math
import itertools
from functools import partial,reduce
from scipy.special import cbrt # thx @ryosy383

'''
def generate():
	i=1
	while True:
		yield i
		i+=1
'''

def drop_prev_square(prev):
	a=next(prev)
	b=next(prev)
	while True:
		if int(math.sqrt(float(b)))**2!=b: yield a
		a,b=b,next(prev)

def drop_next_square(prev):
	a=next(prev)
	b=next(prev)
	yield a
	while True:
		if int(math.sqrt(float(a)))**2!=a: yield b
		a,b=b,next(prev)

def drop_prev_cubic(prev):
	a=next(prev)
	b=next(prev)
	while True:
		if int(cbrt(float(b)))**3!=b: yield a
		a,b=b,next(prev)

def drop_next_cubic(prev):
	a=next(prev)
	b=next(prev)
	yield a
	while True:
		if int(cbrt(float(a)))**3!=a: yield b
		a,b=b,next(prev)

def drop_num(n,prev):
	i=0
	while True:
		i+=1
		a=next(prev)
		if i%n!=0: yield a

def drop_cnt(n,prev):
	i=0
	while True:
		i+=1
		a=next(prev)
		if i>n: yield a

f={
	'S': drop_next_square,
	's': drop_prev_square,
	'C': drop_next_cubic,
	'c': drop_prev_cubic,
	'h': partial(drop_cnt,100),
}
for e in range(2,10): f[str(e)]=partial(drop_num,e)

if __name__=='__main__':
	try:
		while True:
			print(','.join(map(str,
				list(itertools.islice(
					reduce(lambda s,e:f[e](s),raw_input().rstrip(),itertools.count(1)),
				10))
			)))
	except EOFError:
		pass
```