多段階選抜 (Pascal/Cobra)


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

## Pascal

[PascalABC.NET](http://pascalabc.net/en/download)実装です。
つまり…実質C#です…
FPCがFiberに対応した際の足がかりとでも思っておきます…

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

program hena24;
uses
	System;
var
	i: longint;
	g: sequence of longint;
	s: string;
	z: IEnumerator<longint>;

function isqrt(n: longint): longint;
var
	x: longint;
	y: longint;
begin
	if(n<=0) then
		isqrt:=0
	else if(n<4) then
		isqrt:=1
	else begin
		x:=0;
		y:=n;
		while((x<>y) and (x+1<>y)) do begin
			x:=y;
			y:=(n div y+y) div 2;
		end;
		isqrt:=x;
	end;
end;

function icbrt(n: longint): longint;
var
	x: longint;
	y: longint;
begin
	if(n<0) then
		icbrt:=0
	else if(n<8) then
		icbrt:=1
	else begin
		x:=0;
		y:=n;
		while((x<>y) and (x+1<>y)) do begin
			x:=y;
			y:=(n div y div y+y*2) div 3;
		end;
		icbrt:=x;
	end;
end;

function is_sq(n: longint): boolean;
var
	x: longint;
begin
	x:=isqrt(n);
	is_sq:=x*x=n;
end;

function is_cb(n: longint): boolean;
var
	x: longint;
begin
	x:=icbrt(n);
	is_cb:=x*x*x=n;
end;

function is_multiple(i:longint; n: longint): boolean;
begin
	is_multiple:=i mod n=0;
end;

function is_le(i:longint; n: longint): boolean;
begin
	is_le:=i<=n;
end;

function generate(): sequence of longint;
var
	i: longint;
begin
	i:=1;
	while true do begin
		yield i;
		i:=i+1;
	end;
end;

function drop_prev(check: function(x:longint):boolean; _prev: sequence of longint): sequence of longint;
var
	a: longint;
	b: longint;
	prev: IEnumerator<longint>;
begin
	prev:=_prev.GetEnumerator();
	prev.MoveNext();
	a:=prev.Current;
	prev.MoveNext();
	b:=prev.Current;
	while true do begin
		if not check(b) then yield a;
		a:=b;
		prev.MoveNext();
		b:=prev.Current;
	end;
end;

function drop_next(check: function(x:longint):boolean; _prev: sequence of longint): sequence of longint;
var
	a: longint;
	b: longint;
	prev: IEnumerator<longint>;
begin
	prev:=_prev.GetEnumerator();
	prev.MoveNext();
	a:=prev.Current;
	prev.MoveNext();
	b:=prev.Current;
	yield a;
	while true do begin
		if not check(a) then yield b;
		a:=b;
		prev.MoveNext();
		b:=prev.Current;
	end;
end;

function drop_n(check: function(x:longint;y:longint):boolean; n: longint; _prev: sequence of longint): sequence of longint;
var
	a: longint;
	i: longint;
	prev: IEnumerator<longint>;
begin
	prev:=_prev.GetEnumerator();
	i:=0;
	while true do begin
		i:=i+1;
		prev.MoveNext();
		a:=prev.Current;
		if not check(i,n) then yield a;
	end;
end;

begin
	var f:=new Dictionary<char,Func<sequence of longint,sequence of longint>>();
	f['S']:=x->drop_next(is_sq,x);
	f['s']:=x->drop_prev(is_sq,x);
	f['C']:=x->drop_next(is_cb,x);
	f['c']:=x->drop_prev(is_cb,x);
	f['h']:=x->drop_n(is_le,100,x);
	for i:=2 to 9 do begin
		var j:=i;
		f[char(48+j)]:=x->drop_n(is_multiple,j,x);
	end;

	while true do begin
		s:=Console.ReadLine();
		if s=nil then break;
		g:=generate();
		for i:=1 to length(s) do g:=f[s[i]](g);
		z:=g.GetEnumerator();
		for i:=0 to 9 do begin
			if i>0 then write(',');
			z.MoveNext();
			write(z.Current);
		end;
		writeln();
		Console.Out.Flush();
	end;
end.
```

## Cobra

処理系 http://cobra-language.com/downloads/

CLR系で水増しとか言わない^^;;

Booの答案をいじったらできた模様。コロン不要だと改行しなきゃという気持ちになっていいですねorz
そういえばコロン不要な言語にCoffeeScriptというのがあった気がしますが、JavaScriptはまだ安定してなかったはずですし、それこそキリが無くなるので汗

にしても、CLR APIの命名とかこだわりを感じるんですが、Linqが使えないという致命傷を抱えているんですよね…

```cobra:tyama_hena24_enum.cobra
#!/usr/bin/env cobra
#http://qiita.com/Nabetani/items/1c83005a854d2c6cbb69
#http://nabetani.sakura.ne.jp/hena/ord24eliseq/
use System
#use System.Linq.Enumerable
use System.Collections.Generic

class Hena24
	def isqrt(n as int) as int
		if n<=0
			return 0
		if n<4
			return 1
		x,y=0,n
		while x<>y and x+1<>y
			x,y=y,(n//y+y)//2
		return x

	def icbrt(n as int) as int
		if n<0
			return -(.icbrt(-n))
		if n==0
			return 0
		if n<8
			return 1
		x,y=0,n
		while x<>y and x+1<>y
			x,y=y,(n//y // y+y*2) // 3
		return x

	def generate as IEnumerable<of int>
		i=1
		while true
			yield i
			i+=1

	def drop_prev(check as Func<of int,bool>,prev_ as IEnumerable<of int>) as IEnumerable<of int>
		prev=prev_.getEnumerator
		prev.moveNext
		a=prev.current
		prev.moveNext
		b=prev.current
		while true
			if not check(b)
				yield a
			prev.moveNext
			a,b=b,prev.current

	def drop_next(check as Func<of int,bool>,prev_ as IEnumerable<of int>) as IEnumerable<of int>
		prev=prev_.getEnumerator
		prev.moveNext
		a=prev.current
		prev.moveNext
		b=prev.current
		yield a
		while true
			if not check(a)
				yield b
			prev.moveNext
			a,b=b,prev.current

	def drop_n(check as Func<of int,int,bool>,n as int,prev_ as IEnumerable<of int>) as IEnumerable<of int>
		prev=prev_.getEnumerator
		i=0
		while true
			i+=1
			prev.moveNext
			a=prev.current
			if not check(i,n)
				yield a

	def is_sq(n as int) as bool
		return (x=.isqrt(n))*x==n
	def is_cb(n as int) as bool
		return (x=.icbrt(n))*x*x==n
	def is_multiple(i as int,n as int) as bool
		return i%n==0
	def is_le(i as int,n as int) as bool
		return i<=n

	def main
		f=Dictionary<of char,Func<of IEnumerable<of int>,IEnumerable<of int>>>()
		f[c'S']=do(x as IEnumerable<of int>)=.drop_next(ref .is_sq,x)
		f[c's']=do(x as IEnumerable<of int>)=.drop_prev(ref .is_sq,x)
		f[c'C']=do(x as IEnumerable<of int>)=.drop_next(ref .is_cb,x)
		f[c'c']=do(x as IEnumerable<of int>)=.drop_prev(ref .is_cb,x)
		f[c'h']=do(x as IEnumerable<of int>)=.drop_n(ref .is_le,100,x)

		#error: Unexpected call.
		#for e in 2 : 10
		#	z=e
		#	f[(48+z) to char]=(do(n as int)=do(x as IEnumerable<of int>)=.drop_n(ref .is_multiple,n,x))(z)
		
		f[c'2']=do(x as IEnumerable<of int>)=.drop_n(ref .is_multiple,2,x)
		f[c'3']=do(x as IEnumerable<of int>)=.drop_n(ref .is_multiple,3,x)
		f[c'4']=do(x as IEnumerable<of int>)=.drop_n(ref .is_multiple,4,x)
		f[c'5']=do(x as IEnumerable<of int>)=.drop_n(ref .is_multiple,5,x)
		f[c'6']=do(x as IEnumerable<of int>)=.drop_n(ref .is_multiple,6,x)
		f[c'7']=do(x as IEnumerable<of int>)=.drop_n(ref .is_multiple,7,x)
		f[c'8']=do(x as IEnumerable<of int>)=.drop_n(ref .is_multiple,8,x)
		f[c'9']=do(x as IEnumerable<of int>)=.drop_n(ref .is_multiple,9,x)

		while true
			line=Console.readLine
			if line==nil
				break
			first=true
			#cS => f['S'](f['c'](.generate))
			g=.generate
			for c in line
				g=f[c](g)
			for n in g.take(10)
				if not first
					Console.write(',')
				first=false
				Console.write(n)
			Console.writeLine
			Console.out.flush
```