Edited at

多段階選抜 (D)

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

2015/03/24にリリースされたD 2.067でGeneratorが追加されたことを知った(遅すぎ)。(Javaとは違って)ありがたいことにyieldが実装されている。

yieldといえば、多段階選抜である。

それにしても、reduceが効かなかったのは少し残念。

ところで、f['2']とかの宣言があれなのは、ラムダ式キャプチャの都合。Pythonもこういう性質を持つらしい。


tyama_hena24_enum.d

#!/usr/bin/env rdmd

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

import std.stdio,std.string,std.math;
import std.algorithm,std.concurrency;

int isqrt(int n){
if(n<=0)return 0;
if(n<4)return 1;
int x=0,y=n;
for(;x!=y&&x+1!=y;)x=y,y=(n/y+y)/2;
return x;
}
int icbrt(int n){
if(n<0)return icbrt(-n);
if(n==0)return 0;
if(n<8)return 1;
int x=0,y=n;
for(;x!=y&&x+1!=y;)x=y,y=(n/y/y+y*2)/3;
return x;
}

auto generate(){
return new Generator!int({
int i=1;
for(;;){
yield(i);
i+=1;
}
});
}
auto drop_prev(bool delegate(int) check,Generator!int prev){
return new Generator!int({
int a=prev.front;
prev.popFront();
int b=prev.front;
for(;;){
if(!check(b))yield(a);
a=b;
prev.popFront();
b=prev.front;
}
});
}
auto drop_next(bool delegate(int) check,Generator!int prev){
return new Generator!int({
int a=prev.front;
prev.popFront();
int b=prev.front;
yield(a);
for(;;){
if(!check(a))yield(b);
a=b;
prev.popFront();
b=prev.front;
}
});
}
auto drop_n(bool delegate(int,int) check,int n,Generator!int prev){
return new Generator!int({
int i=0;
for(;;){
i++;
int a=prev.front;
if(!check(i,n))yield(a);
prev.popFront();
}
});
}

void main(){
bool is_sq(int n){
//int x=cast(int)sqrt(cast(real)n);
int x=isqrt(n);
return x*x==n;
}
bool is_cb(int n){
//int x=cast(int)cbrt(cast(real)n);
int x=icbrt(n);
return x*x*x==n;
}
bool is_multiple(int i,int n){return i%n==0;}
bool is_le(int i,int n){return i<=n;}

Generator!int delegate(Generator!int)[char] f=[
'S':e => drop_next(&is_sq,e),
's':e => drop_prev(&is_sq,e),
'C':e => drop_next(&is_cb,e),
'c':e => drop_prev(&is_cb,e),
'h':e => drop_n(&is_le,100,e),
];
for(int i=2;i<10;i++){
f[cast(char)('0'+i)] = delegate(int i){return (Generator!int e)=>drop_n(&is_multiple,i,e);}(i);
}
string line;
for(;(line=stdin.readln()) !is null;){
line=chomp(line);
bool first=true;
//cS => f['S'](f['c'](generate()))
//auto z=reduce!((s,e)=>f[e](s))(generate(),line);

auto z=generate();
foreach(char e;line)z=f[e](z);

for(int i=0;i<10;i++){
int n=z.front;
z.popFront();
if(!first)write(',');
first=false;
write(n);
}
writeln();
stdout.flush();
}
}