【paiza】出題解答用の自分用ユーティリティを作った【Java】

# ■PaizaUtilityのJava版を作りました。

以前公開した **[【paiza】出題解答用の自分用ユーティリティを作った【C#】](http://qiita.com/ryo1224/items/3d20f4abbadd9318decc)** のJava版です。

Javaは xxx4j と言う命名が一般的らしいので、PaizaUtil4Jと名付けました。
*（log4jとか、launch4jとか、twitter4jとかもそうですね。）*


**改訂メモ：**

- 【version1】C#版をベースにJava版を実装。
- 【version2】DebugIOプロキシの#readLineのバグ修正
- 【version3】逐次的文字列リテラル代用の為、ファイル入力に実装変更。


## 【version1, 2】基本機能だけ取り敢えずJavaに移植しました。

機能性や使い方はC#版と同じなので、今回は省略します。

**(*'▽')　説明が必要な人は、以前書いた記事の方を参照してね。**

```java:PaizaUtility.java

public class PaizaUtility
{
	public interface ITestIO
	{
		String readLine();

		void writeLine(String line);
	}

	public static class ConsoleProxy implements ITestIO
	{
		private final Scanner in = new Scanner( System.in );

		@Override
		public String readLine()
		{
			return in.nextLine();
		}

		@Override
		public void writeLine(String line)
		{
			System.out.println( line );
		}
	}

	static ITestIO io;

	// static ctor
	static {
		io = new ConsoleProxy();
	}

	public static Iterable<String> readArgs()
	{
		String s = io.readLine();
		int n = Integer.valueOf( s );

		return readArgs( n );
	}
	public static Iterable<String> readArgs(final int n)
	{
		List<String> args = new ArrayList<String>();

		for ( int i = 0; i < n; i++ )
		{
			String arg = io.readLine();

			args.add( arg );
		}

		return args;
	}

	public interface IFunction<TResult, TParameter>
	{
		TResult invoke( TParameter parameter );
	}
	public static Iterable<String> readArgs( IFunction<Integer, String> parseHeaderRecord ) {
		String header = io.readLine();
		int n = parseHeaderRecord.invoke( header ).intValue();

		return readArgs( n );
	}


	// static class.
	private PaizaUtility() { }
}
```

```java:Do.java（paiza出題の解答ロジックを実装するところ）

public class Do
{
	public static void answer()
	{
//		// IFunction デリゲートをラムダで書くとこんなコードになる。
//		Iterable<String> args = PaizaUtility.readArgs(
//				s -> Integer.parseInt( s )
//		);
		Iterable<String> args = PaizaUtility.readArgs();

		for ( String arg : args )
		{
			PaizaUtility.io.writeLine( arg );
		}
	}
}
```

```java:Program.java（プログラムのメインエントリポイント）

public class Program
{
	public static void main( String[] args )
	{
		Do.answer();
	}
}
```


### ◇バグってました＞＜

Scannerクラスの使い方を間違っていたようで、普通にバグっててpaizaで使えませんでした。
（正確には、使えないケースがあった）

```java:ConsoleProxy（修正前）

		@Override
		public String readLine()
		{
			return in.next();
		}
```

```java:ConsoleProxy（修正後）

		@Override
		public String readLine()
		{
			return in.nextLine();
		}
```

なんてこったい(´・ω・｀)

Javaで標準IOなんてそうそうやらないから、paiza公式の [値取得・出力サンプルコード](https://paiza.jp/guide/samplecode) をそのまま実装したらハメられました。
よく確認しなかった自分が悪いんですけどね、、、。

**参考情報：**
似たような所でハマッてる人がいて参考になりました。

[JavaのScannerとか.nextLine()の挙動をよく分かってなかった話](http://qiita.com/wing-x/items/187e988125a3bd7b2b32)



## 【version3】逐次的文字列リテラル対応（ファイル入力化）

```java:DebugIO（コンストラクタのみ抜粋）

		public DebugIO()
		{
			super();
			this.source = readDataSource();
		}
		private static String[] readDataSource()
		{
			// 取り敢えず相対パスでテキストファイルから読み込む事にする。
			Path path = Paths.get( "dat/datasource.txt" );

			try
			{
				return Files.lines( path ).toArray( String[]::new );
			}
			catch ( IOException ex )
			{
				// 絶対有り得ないケースだから何でも良いんだけど取り敢えず空にしとく。
				ex.printStackTrace();
				return new String[]{};
			}
		}
```

```text:dat/datasource.txt
3
hoge
moge
piyo
```

```text:実行結果
hoge
moge
piyo
```

## 【version4】ヒアドキュメントにした
最近ちょっと Paiza のゲームをやるために、古いユーティリティコードを再利用しました。
Gist の方にありますが、今の Java にはヒアドキュメントがあるので、素直にそれを入力にしました。

# ■コード一式はこちら

地味に Gist に移動しました。
https://gist.github.com/sugaryo/e2aafb97f04c947670ec1d9b767ae04c