Edited at

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

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

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


C#

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

cbrtはDllImportのため環境依存。

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

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

あとはJava。でもStreamはようわからんのよね。

Stream.generateはコルーチンでないのでだめそうです。てかEnumeratorに該当するものがない気がする。


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は何もしないと勝手に外部イテレータになるのが嬉しいですね。


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