多段階選抜 (Java/Groovy/Scala)


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

Swiftで書けるならJVM系でも問題なく書けますよね…

## Java

```java:tyama_hena24_enum.java
//usr/bin/env java $0 $@;exit # pseudo-shebang for Java 11+

// http://qiita.com/Nabetani/items/1c83005a854d2c6cbb69
// http://nabetani.sakura.ne.jp/hena/ord24eliseq/
import java.util.Map;
import java.util.HashMap;
import java.util.Scanner;
import java.util.Iterator;
import java.util.function.Function;
import java.util.function.BiFunction;

class Hena24{
	static 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;
	}
	static 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;
	}
	class generate implements Iterator<Integer>{
		int i=0;
		public boolean hasNext(){return true;}
		public Integer next(){
			i+=1;
			return i;
		}
	}
	class drop_prev implements Iterator<Integer>{
		Iterator<Integer> prev;
		Function<Integer,Boolean> check;
		int a=0;
		int b=0;
		drop_prev(Function<Integer,Boolean> check_, Iterator<Integer> prev_){
			check = check_;
			prev = prev_;
			b = prev.next();
		}
		public boolean hasNext(){return true;}
		public Integer next(){
			for(;;){
				a = b;
				b = prev.next();
				if(!check.apply(b)){
					return a;
				}
			}
		}
	}
	class drop_next implements Iterator<Integer>{
		Iterator<Integer> prev;
		Function<Integer,Boolean> check;
		boolean first = true;
		int a=0;
		int b=0;
		drop_next(Function<Integer,Boolean> check_, Iterator<Integer> prev_){
			check = check_;
			prev = prev_;
		}
		public boolean hasNext(){return true;}
		public Integer next(){
			for(;;){
				a = b;
				b = prev.next();
				if(first||!check.apply(a)){
					first = false;
					return b;
				}
			}
		}
	}
	class drop_n implements Iterator<Integer>{
		Iterator<Integer> prev;
		BiFunction<Integer,Integer,Boolean> check;
		int n=0;
		int i=0;
		drop_n(BiFunction<Integer,Integer,Boolean> check_, int n_, Iterator<Integer> prev_){
			check = check_;
			prev = prev_;
			n = n_;
		}
		public boolean hasNext(){return true;}
		public Integer next(){
			for(;;){
				i++;
				int a = prev.next();
				if(!check.apply(i,n)){
					return a;
				}
			}
		}
	}
	static boolean is_sq(int n){
		int x=isqrt(n);
		return x*x==n;
	}
	static boolean is_cb(int n){
		int x=icbrt(n);
		return x*x*x==n;
	}
	static boolean is_multiple(int i,int n){return i%n==0;}
	static boolean is_le(int i,int n){return i<=n;}

	public void Run(){
		Map<Character,Function<Iterator<Integer>,Iterator<Integer>>> f=new HashMap<Character,Function<Iterator<Integer>,Iterator<Integer>>>(){
			{
				put('S',(e)->new drop_next(Hena24::is_sq,e));
				put('s',(e)->new drop_prev(Hena24::is_sq,e));
				put('C',(e)->new drop_next(Hena24::is_cb,e));
				put('c',(e)->new drop_prev(Hena24::is_cb,e));
				put('h',(e)->new drop_n(Hena24::is_le,100,e));
			}
		};
		for(int i=2;i<=9;i++){
			int j=i;
			f.put(String.valueOf(i).charAt(0),(e)->new drop_n(Hena24::is_multiple,j,e));
		}

		Scanner cin = new Scanner(System.in);
		for(;cin.hasNext();){
			String line = cin.nextLine();
			boolean first=true;

			Iterator<Integer> z=new generate();
			for(char e:line.toCharArray())z=f.get(e).apply(z);
			for(int i=0;i<10;i++){
				int n=z.next();
				if(!first)System.out.print(',');
				first=false;
				System.out.print(n);
			}
			System.out.print('\n');
			System.out.flush();
		}
	}
	public static void main(String[]z){new Hena24().Run();}
}
```

## Groovy

(Javaとほとんど同じですが、HashMapの宣言及びクロージャの呼び方が異なっています)
(動くことは確認しましたが、HashMapの型があっているかはわかりません…)

```groovy:tyama_hena24_enum.groovy
#!/usr/bin/env groovy

// http://qiita.com/Nabetani/items/1c83005a854d2c6cbb69
// http://nabetani.sakura.ne.jp/hena/ord24eliseq/
import java.util.Map;
import java.util.HashMap;
import java.util.Scanner;
import java.util.Iterator;
import java.util.function.Function;
import java.util.function.BiFunction;

class Hena24{
	static 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;
	}
	static 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;
	}
	class generate implements Iterator<Integer>{
		int i=0;
		public boolean hasNext(){return true;}
		public Integer next(){
			i+=1;
			return i;
		}
	}
	class drop_prev implements Iterator<Integer>{
		Iterator<Integer> prev;
		Function<Integer,Boolean> check;
		int a=0;
		int b=0;
		drop_prev(Function<Integer,Boolean> check_, Iterator<Integer> prev_){
			check = check_;
			prev = prev_;
			b = prev.next();
		}
		public boolean hasNext(){return true;}
		public Integer next(){
			for(;;){
				a = b;
				b = prev.next();
				if(!check.apply(b)){
					return a;
				}
			}
		}
	}
	class drop_next implements Iterator<Integer>{
		Iterator<Integer> prev;
		Function<Integer,Boolean> check;
		boolean first = true;
		int a=0;
		int b=0;
		drop_next(Function<Integer,Boolean> check_, Iterator<Integer> prev_){
			check = check_;
			prev = prev_;
		}
		public boolean hasNext(){return true;}
		public Integer next(){
			for(;;){
				a = b;
				b = prev.next();
				if(first||!check.apply(a)){
					first = false;
					return b;
				}
			}
		}
	}
	class drop_n implements Iterator<Integer>{
		Iterator<Integer> prev;
		BiFunction<Integer,Integer,Boolean> check;
		int n=0;
		int i=0;
		drop_n(BiFunction<Integer,Integer,Boolean> check_, int n_, Iterator<Integer> prev_){
			check = check_;
			prev = prev_;
			n = n_;
		}
		public boolean hasNext(){return true;}
		public Integer next(){
			for(;;){
				i++;
				int a = prev.next();
				if(!check.apply(i,n)){
					return a;
				}
			}
		}
	}
	static boolean is_sq(int n){
		int x=isqrt(n);
		return x*x==n;
	}
	static boolean is_cb(int n){
		int x=icbrt(n);
		return x*x*x==n;
	}
	static boolean is_multiple(int i,int n){return i%n==0;}
	static boolean is_le(int i,int n){return i<=n;}

	public void Run(){
		Map<Character,Function<Iterator<Integer>,Iterator<Integer>>> f=[
			('S' as char):(e)->new drop_next(Hena24::is_sq,e),
			('s' as char):(e)->new drop_prev(Hena24::is_sq,e),
			('C' as char):(e)->new drop_next(Hena24::is_cb,e),
			('c' as char):(e)->new drop_prev(Hena24::is_cb,e),
			('h' as char):(e)->new drop_n(Hena24::is_le,100,e),
		] as HashMap
		for(int i=2;i<=9;i++){
			int j=i;
			f.put(String.valueOf(i).charAt(0),(e)->new drop_n(Hena24::is_multiple,j,e));
		}

		Scanner cin = new Scanner(System.in);
		for(;cin.hasNext();){
			String line = cin.nextLine();
			boolean first=true;

			Iterator<Integer> z=new generate();
			for(char e:line.toCharArray()){z=f.get(e)(z);}
			for(int i=0;i<10;i++){
				int n=z.next();
				if(!first)System.out.print(',');
				first=false;
				System.out.print(n);
			}
			System.out.print('\n');
			System.out.flush();
		}
	}
	public static void main(String[]z){new Hena24().Run();}
}
```

## Scala

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

// http://qiita.com/Nabetani/items/1c83005a854d2c6cbb69
// http://nabetani.sakura.ne.jp/hena/ord24eliseq/
import java.util.Map;
import java.util.HashMap
import java.util.Scanner
import java.util.Iterator
import java.util.function.Function
import java.util.function.BiFunction

object Hena24{
	def isqrt(n:Int):Int = {
		if(n<=0)return 0
		if(n<4)return 1
		var x=0
		var y=n
		while(x!=y&&x+1!=y){x=y;y=(n/y+y)/2}
		return x
	}
	def icbrt(n:Int):Int = {
		if(n<0)return -icbrt(-n)
		if(n==0)return 0
		if(n<8)return 1
		var x=0
		var y=n
		while(x!=y&&x+1!=y){x=y;y=(n/y/y+y*2)/3}
		return x
	}
	class generate extends Iterator[Int]{
		var i=0
		def hasNext():Boolean = {return true}
		def next():Int = {
			i+=1
			return i
		}
	}
	class drop_prev(check:Function[Int,Boolean], prev:Iterator[Int]) extends Iterator[Int]{
		var a=0
		var b=prev.next()
		def hasNext():Boolean = {return true}
		def next():Int = {
			while(true){
				a = b
				b = prev.next()
				if(!check.apply(b)){
					return a
				}
			}
			assert(false); return -1
		}
	}
	class drop_next(check:Function[Int,Boolean], prev:Iterator[Int]) extends Iterator[Int]{
		var first = true
		var a=0
		var b=0
		def hasNext():Boolean = {return true}
		def next():Int = {
			while(true){
				a = b
				b = prev.next()
				if(first || !check.apply(a)){
					first = false
					return b
				}
			}
			assert(false); return -1
		}
	}
	class drop_n(check:BiFunction[Int,Int,Boolean], n:Int, prev:Iterator[Int]) extends Iterator[Int]{
		var i=0
		def hasNext():Boolean = {return true}
		def next():Int = {
			while(true){
				i+=1
				val a = prev.next()
				if(!check.apply(i,n)){
					return a
				}
			}
			assert(false); return -1
		}
	}
	def is_sq(n:Int):Boolean = {
		val x=isqrt(n)
		return x*x==n
	}
	def is_cb(n:Int):Boolean = {
		val x=icbrt(n)
		return x*x*x==n
	}
	def is_multiple(i:Int,n:Int):Boolean = {return i%n==0}
	def is_le(i:Int,n:Int):Boolean = {return i<=n}

	def main(z:Array[String]):Unit = {
		var f:Map[Character,Function[Iterator[Int],Iterator[Int]]] = new HashMap[Character,Function[Iterator[Int],Iterator[Int]]](){
			{
				put('S',(e:Iterator[Int])=>new drop_next(is_sq _,e))
				put('s',(e:Iterator[Int])=>new drop_prev(is_sq _,e))
				put('C',(e:Iterator[Int])=>new drop_next(is_cb _,e))
				put('c',(e:Iterator[Int])=>new drop_prev(is_cb _,e))
				put('h',(e:Iterator[Int])=>new drop_n(is_le _,100,e))
			}
		}
		for(i<-2 to 9){
			val j=i
			f.put(String.valueOf(i).charAt(0),(e:Iterator[Int])=>new drop_n(is_multiple _,j,e))
		}

		val cin = new Scanner(System.in)
		while(cin.hasNext()){
			val line = cin.nextLine()
			var first=true

			var z:Iterator[Int] = new generate()
			for(e<-line.toCharArray())z=f.get(e).apply(z)
			for(i<-1 to 10){
				var n=z.next()
				if(!first)System.out.print(',')
				first=false
				System.out.print(n)
			}
			System.out.print('\n')
			System.out.flush()
		}
	}
}
```