自分の解説記事内で使用するテンプレートの紹介[ABC258～ABC289]

※2022/07/27 SimpleScannerの一部を書き換えました
※2022/08/07 LibraryクラスのBufferedReader関連の入力系メソッドを廃止し、SimpleScannerに変更
※2022/08/31 SimpleScannerの一部変更
※2022/09/04 元に戻しました(2022/08/31以前)
※2022/09/07 SimpleScannerを大幅に書き換えました(追記参照)
※2022/10/17 Libraryクラスを大幅に書き換え、SimpleScanner、SimplePrinterクラスを追記しました

## はじめに
これまでと違って別クラスにまとめるようにしました。また、入力を受け取るクラスができたので新しく記事に書いた方が良いかなぁと思って書きました。

コード自体に何のメソッドか書く形にしているので、見にくい等ありましたらコメントください。別に見出しを作って解説を書きます。

## 自作ライブラリ(Library)
細かい説明はコード中にコメントしてあります。
```Library.java
class Library{
	SimpleScanner in;
	SimplePrinter out;
	private long[] Factorials,InFactorials;
	public long mod = 0;
	public Library(InputStream in,OutputStream out){
		this.in = new SimpleScanner(in);
		this.out = new SimplePrinter(out);
	}
	public Library(InputStream in,OutputStream out,int fac,long mod){
		this(in,out);
		Factorials=new long[fac+1];
		Factorials[1]=1;
		for(int i=2;i<=fac;i++)Factorials[i]=Factorials[i-1]*i%mod;
		InFactorials=new long[fac+1];
		InFactorials[fac]=modPow(Factorials[fac],mod-2,mod);
		for(int i=fac;i>1;i--)InFactorials[i-1]=InFactorials[i]*i%mod;
		this.mod = mod;
	}
	public Library(int fac,long mod){
		Factorials=new long[fac+1];
		Factorials[1]=1;
		for(int i=2;i<=fac;i++)Factorials[i]=Factorials[i-1]*i%mod;
		InFactorials=new long[fac+1];
		InFactorials[fac]=modPow(Factorials[fac],mod-2,mod);
		for(int i=fac;i>1;i--)InFactorials[i-1]=InFactorials[i]*i%mod;
		this.mod = mod;
	}

	/**
	 * コンストラクタで渡された値までの
	 * num!、aCbをmodで割ったあまりを返します。
	 */
	public long getFact(int num){
		return Factorials[num];
	}
	public long getCombi(int a,int b){
		return (Factorials[a]*InFactorials[a-b]%mod)*InFactorials[b]%mod;
	}

	/**
	 * factではa!を、
	 * modFactでは引数のmodかコンストラクタで渡されたmodで
	 * 割ったあまりを返します。
	 */
	public static long fact(long a){
		long ans=1;
		for(long i=2;i<=a;i++)ans*=i;
		return ans;
	}
	public static long modFact(long a,long mod){
		long ans=1;
		for(long i=2;i<=a;i++){
			ans*=i%mod;
			ans%=mod;
		}
		return ans;
	}
	public long modFact(long a){
		if(mod==0){
			System.err.println("\u001b[00;31m"+"#mod is not defined#");
			System.exit(1);
		}
		long ans=1;
		for(long i=2;i<=a;i++){
			ans*=i%mod;
			ans%=mod;
		}
		return ans;
	}

	/**
	 * CombiではaCb、
	 * modCombiでは引数のmodかコンストラクタで渡されたmodで
	 * 割ったあまりを返します。
	 */
	public static long combi(long a,long b){
		long ans=1;
		if(b==0||b==a)return 1;
		if(b<0||b>a)return 0;
		b=Math.min(a-b,b);
		for(long i=1;i<=b;i++){
			ans*=a--;
			ans/=i;
		}
		return ans;
	}
	public static long modCombi(long a,long b,long mod){
		long ans=1;
		if(b==0||b==a)return 1;
		if(b<0||b>a)return 0;
		b=Math.min(a-b,b);
		for(long i=1;i<=b;i++){
			ans*=a--;
			ans%=mod;
			ans*=modPow(i,mod-2,mod);
			ans%=mod;
		}
		return ans;
	}
	public long modCombi(long a,long b){
		if(mod==0){
			System.err.println("\u001b[00;31m"+"#mod is not defined#");
			System.exit(1);
		}
		long ans=1;
		if(b==0||b==a)return 1;
		if(b<0||b>a)return 0;
		b=Math.min(a-b,b);
		for(long i=1;i<=b;i++){
			ans*=a--;
			ans%=mod;
			ans*=modPow(i,mod-2,mod);
			ans%=mod;
		}
		return ans;
	}

	/**
	 * int、long型配列をソートします。
	 * 二次元配列の場合は[i][0]と[i][1]の大きさで
	 * 昇順に並べ替えます。
	 */
	public static void sort(int[] list){
		for(int i=0;i<list.length;i++){
			int j=i;
			while(j>0&&list[(j-1)/2]<list[j]){
				int temp=list[(j-1)/2];
				list[(j-1)/2]=list[j];
				list[j]=temp;
				j=(j-1)/2;
			}
		}
		for(int i=list.length;i>0;i--){
			int temp=list[i-1];
			list[i-1]=list[0];
			list[0]=temp;
			int j=0;
			while((2*j+1<i-1&&list[j]<list[2*j+1])||(2*j+2<i-1&&list[j]<list[2*j+2])){
				if(2*j+2==i-1||list[2*j+1]>list[2*j+2]){
					temp=list[2*j+1];
					list[2*j+1]=list[j];
					list[j]=temp;
					j<<=1;
					j++;
				}
				else{
					temp=list[2*j+2];
					list[2*j+2]=list[j];
					list[j]=temp;
					j<<=1;
					j+=2;
				}
			}
		}
	}
	public static void sort(int[][] list){
		for(int i=0;i<list.length;i++){
			int j=i;
			while(j>0&&(list[(j-1)/2][0]<list[j][0]||(list[(j-1)/2][0]==list[j][0]&&list[(j-1)/2][1]<list[j][1]))){
				int[] temp=list[(j-1)/2];
				list[(j-1)/2]=list[j];
				list[j]=temp;
				j=(j-1)/2;
			}
		}
		for(int i=list.length;i>0;i--){
			int[] temp=list[i-1];
			list[i-1]=list[0];
			list[0]=temp;
			int j=0;
			while((2*j+1<i-1&&(list[j][0]<list[2*j+1][0]||(list[j][0]==list[2*j+1][0]&&list[j][1]<list[2*j+1][1])))||
				(2*j+2<i-1&&(list[j][0]<list[2*j+2][0]||(list[j][0]==list[2*j+2][0]&&list[j][1]<list[2*j+2][1])))){
				if(2*j+2==i-1||(list[2*j+1][0]>list[2*j+2][0]||(list[2*j+1][0]==list[2*j+2][0]&&list[2*j+1][1]>list[2*j+2][1]))){
					temp=list[2*j+1];
					list[2*j+1]=list[j];
					list[j]=temp;
					j<<=1;
					j++;
				}
				else{
					temp=list[2*j+2];
					list[2*j+2]=list[j];
					list[j]=temp;
					j<<=1;
					j+=2;
				}
			}
		}
	}
	public static void sort(long[] list){
		for(int i=0;i<list.length;i++){
			int j=i;
			while(j>0&&list[(j-1)/2]<list[j]){
				long temp=list[(j-1)/2];
				list[(j-1)/2]=list[j];
				list[j]=temp;
				j=(j-1)/2;
			}
		}
		for(int i=list.length;i>0;i--){
			long temp=list[i-1];
			list[i-1]=list[0];
			list[0]=temp;
			int j=0;
			while((2*j+1<i-1&&list[j]<list[2*j+1])||(2*j+2<i-1&&list[j]<list[2*j+2])){
				if(2*j+2==i-1||list[2*j+1]>list[2*j+2]){
					temp=list[2*j+1];
					list[2*j+1]=list[j];
					list[j]=temp;
					j<<=1;
					j++;
				}
				else{
					temp=list[2*j+2];
					list[2*j+2]=list[j];
					list[j]=temp;
					j<<=1;
					j+=2;
				}
			}
		}
	}
	public static void sort(long[][] list){
		for(int i=0;i<list.length;i++){
			int j=i;
			while(j>0&&(list[(j-1)/2][0]<list[j][0]||(list[(j-1)/2][0]==list[j][0]&&list[(j-1)/2][1]<list[j][1]))){
				long[] temp=list[(j-1)/2];
				list[(j-1)/2]=list[j];
				list[j]=temp;
				j=(j-1)/2;
			}
		}
		for(int i=list.length;i>0;i--){
			long[] temp=list[i-1];
			list[i-1]=list[0];
			list[0]=temp;
			int j=0;
			while((2*j+1<i-1&&(list[j][0]<list[2*j+1][0]||(list[j][0]==list[2*j+1][0]&&list[j][1]<list[2*j+1][1])))||
				(2*j+2<i-1&&(list[j][0]<list[2*j+2][0]||(list[j][0]==list[2*j+2][0]&&list[j][1]<list[2*j+2][1])))){
				if(2*j+2==i-1||(list[2*j+1][0]>list[2*j+2][0]||(list[2*j+1][0]==list[2*j+2][0]&&list[2*j+1][1]>list[2*j+2][1]))){
					temp=list[2*j+1];
					list[2*j+1]=list[j];
					list[j]=temp;
					j<<=1;
					j++;
				}
				else{
					temp=list[2*j+2];
					list[2*j+2]=list[j];
					list[j]=temp;
					j<<=1;
					j+=2;
				}
			}
		}
	}

	/**
	 * int型配列をソートします。
	 * 最大値が小さい場合は有効です。
	 */
	public static void countSort(int[] nums,int limit){
		int[] list=new int[limit+1];
		for(int i=0;i<nums.length;i++)list[nums[i]]++;
		int temp=0;
		for(int i=0;i<list.length;i++)for(int j=0;j<list[i];j++)nums[temp++]=i;
	}

	/**
	 * gcdは最大公約数を、
	 * lcmは最小公倍数を返します。
	 * lcmはオーバーフローの可能性があるのでご注意を。
	 * 戻り値はlong型です。
	 */
	public static long gcd(long a,long b){
		if(a==0||b==0)
			return Math.max(a,b);
		long temp;
		while((temp=a%b)!=0){
			a=b;
			b=temp;
		}
		return b;
	}
	public static long lcm(long a,long b){
		if(a==0||b==0)
			return 0;
		long mult=a*b,temp;
		while((temp=a%b)!=0){
			a=b;
			b=temp;
		}
		return mult/b;
	}

	/**
	 * BigIntegerクラスのものを使用します。
	 * 素数である確率が高いならtrue、
	 * 確実に合成数ならfalseを返します。
	 * 誤判定の確率は1/2^20以下です。
	 */
	public static boolean isPrime(long num){
		return BigInteger.valueOf(num).isProbablePrime(20);
	}

	/**
	 * 引数まで(引数含む)の素数を返します。
	 * 2^30以上の素数列挙はできないのでご注意を。
	 */
	public static int[] primes(int num){
		BitSet nums=new BitSet(num+1);
		nums.set(2,num+1);
		for(int i=2;i<=Math.sqrt(num);i++)if(nums.get(i))for(int j=i*i;j<=num;j+=i)nums.clear(j);
		int[] answer=new int[nums.cardinality()];
		int i=2,index=0;
		while(true){
			i=nums.nextSetBit(i);
			answer[index++]=i++;
			if(index==answer.length)break;
		}
		return answer;
	}

	/**
	 * powではそのままの結果を、
	 * modPowでは引数のmodかコンストラクタで渡されたmodで
	 * 割ったあまりを返します。
	 */
	public static long pow(long a,long b){
		long ans=1;
		while(b>0){
			if((b&1)==1)ans*=a;
			a*=a;
			b>>=1;
		}
		return ans;
	}
	public static long modPow(long a,long b,long mod){
		long ans=1;
		a%=mod;
		while(b>0){
			if((b&1)==1)ans*=a;
			ans%=mod;
			a*=a;
			a%=mod;
			b>>=1;
		}
		return ans;
	}
	public long modPow(long a,long b){
		if(mod==0){
			System.err.println("\u001b[00;31m"+"#mod is not defined#");
			System.exit(1);
		}
		long ans=1;
		a%=mod;
		while(b>0){
			if((b&1)==1)ans*=a;
			ans%=mod;
			a*=a;
			a%=mod;
			b>>=1;
		}
		return ans;
	}

	/**
	 * Stringをint、longに変換します。
	 * 数値以外の文字であっても無理矢理数値変換してしまうので
	 * 使用の際はご注意を。
	 */
	public static int parseInt(String str){
		char[] nums=str.toCharArray();
		int ans=0;
		boolean plus=true;
		if(nums[0]=='-'){
			plus=!plus;
			nums[0]='0';
		}
		for(int i=0;i<nums.length;i++)ans=ans*10+nums[i]-'0';
		return plus?ans:-ans;
	}
	public static long parseLong(String str){
		char[] nums=str.toCharArray();
		long ans=0;
		boolean plus=true;
		if(nums[0]=='-'){
			plus=!plus;
			nums[0]='0';
		}
		for(int i=0;i<nums.length;i++)ans=ans*10+nums[i]-'0';
		return plus?ans:-ans;
	}

	/**
	 * downSearchではnum以下で最大の要素を、
	 * upSearchではnum以上で最小の要素を探します。
	 * 同様にunderSearchではnum未満で最大の要素を、
	 * overSearchではnumより大きい最小の要素を探します。
	 * なお、underとdownは条件を満たす最大のindexを、
	 * upとoverは条件を満たす最小のindexを返します。
	 * 戻り値は引数の配列(List)のindexです。
	 */
	//downSearch
	public static int downSearch(int[] nums,int num){
		int a=0,b=nums.length-1,ans=-1,c;
		while(a-b<1){
			c=(a+b)/2;
			if(nums[c]>num)b=c-1;
			else a=(ans=c)+1;
		}
		return ans;
	}
	public static int downSearch(long[] nums,long num){
		int a=0,b=nums.length-1,ans=-1,c=-1;
		while(a-b<1){
			c=(a+b)/2;
			if(nums[c]>num)b=c-1;
			else a=(ans=c)+1;
		}
		return ans;
	}
	public static int downSearch(Integer[] nums,Integer num){
		int a=0,b=nums.length-1,ans=-1,c=-1;
		while(a-b<1){
			c=(a+b)/2;
			if(nums[c].compareTo(num)>0)b=c-1;
			else a=(ans=c)+1;
		}
		return ans;
	}
	public static int downSearch(Long[] nums,Long num){
		int a=0,b=nums.length-1,ans=-1,c=-1;
		while(a-b<1){
			c=(a+b)/2;
			if(nums[c].compareTo(num)>0)b=c-1;
			else a=(ans=c)+1;
		}
		return ans;
	}
	public static int downSearch(List<Integer> nums,Integer num){
		int a=0,b=nums.size()-1,ans=-1,c=-1;
		while(a-b<1){
			c=(a+b)/2;
			if(nums.get(c).compareTo(num)>0)b=c-1;
			else a=(ans=c)+1;
		}
		return ans;
	}
	public static int downSearch(List<Long> nums,Long num){
		int a=0,b=nums.size()-1,ans=-1,c=-1;
		while(a-b<1){
			c=(a+b)/2;
			if(nums.get(c).compareTo(num)>0)b=c-1;
			else a=(ans=c)+1;
		}
		return ans;
	}

	//upSearch
	public static int upSearch(int[] nums,int num){
		int a=0,b=nums.length-1,ans=nums.length,c;
		while(a-b<1){
			c=(a+b)/2;
			if(nums[c]>=num)b=(ans=c)-1;
			else a=c+1;
		}
		return ans;
	}
	public static int upSearch(long[] nums,long num){
		int a=0,b=nums.length-1,ans=nums.length,c=-1;
		while(a-b<1){
			c=(a+b)/2;
			if(nums[c]>=num)b=(ans=c)-1;
			else a=c+1;
		}
		return ans;
	}
	public static int upSearch(Integer[] nums,Integer num){
		int a=0,b=nums.length-1,ans=nums.length,c=-1;
		while(a-b<1){
			c=(a+b)/2;
			if(nums[c].compareTo(num)>=0)b=(ans=c)-1;
			else a=c+1;
		}
		return ans;
	}
	public static int upSearch(Long[] nums,Long num){
		int a=0,b=nums.length-1,ans=nums.length,c=-1;
		while(a-b<1){
			c=(a+b)/2;
			if(nums[c].compareTo(num)>=0)b=(ans=c)-1;
			else a=c+1;
		}
		return ans;
	}
	public static int upSearch(List<Integer> nums,int num){
		int a=0,b=nums.size()-1,ans=nums.size(),c=-1;
		while(a-b<1){
			c=(a+b)/2;
			if(nums.get(c).compareTo(num)>=0)b=(ans=c)-1;
			else a=c+1;
		}
		return ans;
	}
	public static int upSearch(List<Long> nums,Long num){
		int a=0,b=nums.size()-1,ans=nums.size(),c=-1;
		while(a-b<1){
			c=(a+b)/2;
			if(nums.get(c).compareTo(num)>=0)b=(ans=c)-1;
			else a=c+1;
		}
		return ans;
	}

	//underSearch
	public static int underSearch(int[] nums,int num){
		int a=0,b=nums.length-1,ans=-1,c;
		while(a-b<1){
			c=(a+b)/2;
			if(nums[c]>=num)b=c-1;
			else a=(ans=c)+1;
		}
		return ans;
	}
	public static int underSearch(long[] nums,long num){
		int a=0,b=nums.length-1,ans=-1,c;
		while(a-b<1){
			c=(a+b)/2;
			if(nums[c]>=num)b=c-1;
			else a=(ans=c)+1;
		}
		return ans;
	}
	public static int underSearch(Integer[] nums,Integer num){
		int a=0,b=nums.length-1,ans=-1,c;
		while(a-b<1){
			c=(a+b)/2;
			if(nums[c].compareTo(num)>=0)b=c-1;
			else a=(ans=c)+1;
		}
		return ans;
	}
	public static int underSearch(Long[] nums,Long num){
		int a=0,b=nums.length-1,ans=-1,c;
		while(a-b<1){
			c=(a+b)/2;
			if(nums[c].compareTo(num)>=0)b=c-1;
			else a=(ans=c)+1;
		}
		return ans;
	}
	public static int underSearch(List<Integer> nums,Integer num){
		int a=0,b=nums.size()-1,ans=-1,c;
		while(a-b<1){
			c=(a+b)/2;
			if(nums.get(c).compareTo(num)>=0)b=c-1;
			else a=(ans=c)+1;
		}
		return ans;
	}
	public static int underSearch(List<Long> nums,Long num){
		int a=0,b=nums.size()-1,ans=-1,c;
		while(a-b<1){
			c=(a+b)/2;
			if(nums.get(c).compareTo(num)>=0)b=c-1;
			else a=(ans=c)+1;
		}
		return ans;
	}

	//overSearch
	public static int overSearch(int[] nums,int num){
		int a=0,b=nums.length-1,ans=nums.length,c;
		while(a-b<1){
			c=(a+b)/2;
			if(nums[c]>num)b=(ans=c)-1;
			else a=c+1;
		}
		return ans;
	}
	public static int overSearch(long[] nums,long num){
		int a=0,b=nums.length-1,ans=nums.length,c;
		while(a-b<1){
			c=(a+b)/2;
			if(nums[c]>num)b=(ans=c)-1;
			else a=c+1;
		}
		return ans;
	}
	public static int overSearch(Integer[] nums,Integer num){
		int a=0,b=nums.length-1,ans=nums.length,c;
		while(a-b<1){
			c=(a+b)/2;
			if(nums[c].compareTo(num)>0)b=(ans=c)-1;
			else a=c+1;
		}
		return ans;
	}
	public static int overSearch(Long[] nums,Long num){
		int a=0,b=nums.length-1,ans=nums.length,c;
		while(a-b<1){
			c=(a+b)/2;
			if(nums[c].compareTo(num)>0)b=(ans=c)-1;
			else a=c+1;
		}
		return ans;
	}
	public static int overSearch(List<Integer> nums,Integer num){
		int a=0,b=nums.size()-1,ans=nums.size(),c;
		while(a-b<1){
			c=(a+b)/2;
			if(nums.get(c).compareTo(num)>0)b=(ans=c)-1;
			else a=c+1;
		}
		return ans;
	}
	public static int overSearch(List<Long> nums,Long num){
		int a=0,b=nums.size()-1,ans=nums.size(),c;
		while(a-b<1){
			c=(a+b)/2;
			if(nums.get(c).compareTo(num)>0)b=(ans=c)-1;
			else a=c+1;
		}
		return ans;
	}

	/**
	 * 最長増加部分列の長さを返します。
	 * 引数にboolean型変数を渡すと
	 * 同じ値も増加と判定するか指定できます。
	 * デフォルトでは増加と判定しません。
	 */
	public static int lis(int[] nums){
		return lis(nums,false);
	}
	public static int lis(int[][] nums,int p){
		return lis(nums,p,false);
	}
	public static int lis(int[] nums,boolean include){
		int[] list = new int[nums.length];
		Arrays.fill(list,Integer.MAX_VALUE);
		for(int i=0;i<nums.length;i++){
			int index = include ? overSearch(list,nums[i]) : upSearch(list,nums[i]);
			list[index] = Math.min(list[index],nums[i]);
		}
		int answer = underSearch(list,Integer.MAX_VALUE);
		return answer+1;
	}
	public static int lis(int[][] nums,int p,boolean include){
		int[] list = new int[nums.length];
		Arrays.fill(list,Integer.MAX_VALUE);
		for(int i=0;i<nums.length;i++){
			int index = include ? overSearch(list,nums[i][p]) : upSearch(list,nums[i][p]);
			list[index] = Math.min(list[index],nums[i][p]);
		}
		int answer = underSearch(list,Integer.MAX_VALUE);
		return answer+1;
	}

	public void exit(int num){
		in.close();
		out.close();
		System.exit(num);
	}
}
```

## 入力受け取り(SimpleScanner)
自分でもいまいちわかってないところがあるんで解説はできませんが、一応載せておきます。

※2022/08/07追記
複数の要素を受け取るメソッドを追加しました。
```SimpleScanner.java
class SimpleScanner{
	private final int buff_size=1<<16;
	private final InputStream is=System.in;
	private byte[] buff=new byte[buff_size];
	private int length=0,point=0;

	public SimpleScanner(){}

	//読み取り位置の調整や再読込用のメソッド群
	private void reload()throws IOException{
		point=0;
		length=is.read(buff,0,buff_size);
	}
	private void load(int n)throws IOException{
		if(n<=length-point)return;
		for(int i=point,j=0;i<length;i++,j++)buff[j]=buff[i];
		length-=point;
		point=0;
		int temp=is.read(buff,length,buff_size-length);
		if(temp==-1)return;
		length+=temp;
	}
	private void skip()throws IOException{
		while(true){
			while(point<length&&buff[point]<33)point++;
			if(point<length)return;
			reload();
		}
	}

	//受け取り用メソッド
	public long nextLong()throws IOException{
		skip();
		load(20);
		long ans=0;
		boolean negate=false;
		if(buff[point++]=='-')negate=true;
		else point--;
		while(47<buff[point]&&buff[point]<58){
			ans=ans*10+buff[point++]-48;
		}
		return negate?-ans:ans;
	}
	public int nextInt()throws IOException{
		skip();
		load(12);
		int ans=0;
		boolean negate=false;
		if(buff[point++]=='-')negate=true;
		else point--;
		while(47<buff[point]&&buff[point]<58){
			ans=ans*10+buff[point++]-48;
		}
		return negate?-ans:ans;
	}
	public String next()throws IOException{
		skip();
		load(1);
		StringBuilder sb=new StringBuilder();
		while(buff[point]>32){
			sb.append((char)buff[point++]);
		}
		return sb.toString();
	}
	public int[] nextInt(int num)throws IOException{
		int[] array = new int[num];
		for(int i=0;i<num;i++){
			array[i] = nextInt();
		}
		return array;
	}
	public long[] nextLong(int num)throws IOException{
		long[] array = new long[num];
		for(int i=0;i<num;i++){
			array[i] = nextLong();
		}
		return array;
	}
	public String[] next(int num)throws IOException{
		String[] array = new String[num];
		for(int i=0;i<num;i++){
			array[i] = next();
		}
		return array;
	}

	//今の情報を返すメソッド(toStringオーバーライドで実装)
	public String toString(){
		StringBuilder answer = new StringBuilder();
		answer.append("\n*----------------------------------------*\n");
		answer.append("These are SimpleScanner's states\n\n");
		answer.append("BufferSize is "+buff.length+"\n");
		answer.append("Now length is "+length+"\n");
		answer.append("Now point is "+point+"\n");
		answer.append("Buffer---------------\n");
		for(int i=0;i<length+2;i++){
			if(i==point)answer.append("@Point is here@");
			answer.append((char)buff[i]);
		}
		answer.append("---------------------");
		answer.append("\n*----------------------------------------*\n");
		return answer.toString();
	}
}
```

#### 追記
上記のSimpleScannerを使っていると受け取りミス(どうミスるかはわかってないです)が発生するってことがわかったので書き換えました。メソッドと引数が上記と同じなら同じ機能のメソッドです。
```SimpleScanner.java
class SimpleScanner{
	final private int buff_size = 1<<10;
	private InputStream is;
	private byte[] buff;
	private int point,length;
	public SimpleScanner(InputStream is){
		this.is = is;
		buff = new byte[buff_size];
		point = length = 0;
	}
	private void reload(){
		do{
			try{
				length = is.read(buff,point = 0,buff_size);
			}catch(IOException e){
				e.printStackTrace();
				System.exit(1);
			}
		}while(length==-1);
	}
	private byte read(){
		if(point==length)reload();
		return buff[point++];
	}
	public byte nextByte(){
		byte c = read();
		while(c<=' ')c = read();
		return c;
	}
	public int nextInt(){
		int ans = 0;
		byte c = read();
		while(c<=' ')c = read();
		boolean negate = c == '-';
		if(c=='-')c = read();
		while('0'<=c&&c<='9'){
			ans = ans*10+c-'0';
			c = read();
		}
		return negate ? -ans : ans;
	}
	public long nextLong(){
		long ans = 0;
		byte c = read();
		while(c<=' ')c = read();
		boolean negate = c == '-';
		if(c=='-')c = read();
		while('0'<=c&&c<='9'){
			ans = ans*10+c-'0';
			c = read();
		}
		return negate ? -ans : ans;
	}
	public char nextChar(){
		byte c = read();
		while(c<=' ')c = read();
		return (char)c;
	}
	public String next(){
		StringBuilder ans = new StringBuilder();
		byte c = read();
		while(c<=' ')c = read();
		while(c>' '){
			ans.append((char)c);
			c = read();
		}
		return ans.toString();
	}
	public byte[] nextByte(int n){
		byte[] ans = new byte[n];
		for(int i=0;i<n;i++){
			ans[i] = nextByte();
		}
		return ans;
	}
	public int[] nextInt(int n){
		int[] ans = new int[n];
		for(int i=0;i<n;i++){
			ans[i] = nextInt();
		}
		return ans;
	}
	public long[] nextLong(int n){
		long[] ans = new long[n];
		for(int i=0;i<n;i++){
			ans[i] = nextLong();
		}
		return ans;
	}
	public String[] next(int n){
		String[] ans = new String[n];
		for(int i=0;i<n;i++){
			ans[i] = next();
		}
		return ans;
	}
	public byte[][] nextByte(int n,int m){
		byte[][] ans = new byte[n][];
		for(int i=0;i<n;i++){
			ans[i] = nextByte(m);
		}
		return ans;
	}
	public int[][] nextInt(int n,int m){
		int[][] ans = new int[n][];
		for(int i=0;i<n;i++){
			ans[i] = nextInt(m);
		}
		return ans;
	}
	public long[][] nextLong(int n,int m){
		long[][] ans = new long[n][];
		for(int i=0;i<n;i++){
			ans[i] = nextLong(m);
		}
		return ans;
	}
	public String[][] next(int n,int m){
		String[][] ans = new String[n][];
		for(int i=0;i<n;i++){
			ans[i] = next(m);
		}
		return ans;
	}
	public char[] nextCharArray(){
		return next().toCharArray();
	}
	public char[][] nextCharArray(int n){
		char[][] ans = new char[n][];
		for(int i=0;i<n;i++){
			ans[i] = next().toCharArray();
		}
		return ans;
	}
	public void close(){
		try{
			is.close();
		}catch(IOException e){
			e.printStackTrace();
			System.exit(1);
		}
	}
}
```

## 出力(SimplePrinter)
PrintWriterと一緒ですが、配列の出力に対応させました。
```SimplePrinter.java
class SimplePrinter extends PrintWriter{
	public SimplePrinter(OutputStream os){
		super(os);
	}
	public void println(byte[] nums,String str){
		print(nums[0]);
		for(int i=1;i<nums.length;i++){
			print(str);
			print(nums[i]);
		}
		println();
	}
	public void println(byte[] nums,char c){
		print(nums[0]);
		for(int i=1;i<nums.length;i++){
			print(c);
			print(nums[i]);
		}
		println();
	}
	public void println(byte[][] nums,String str){
		for(int i=0;i<nums.length;i++){
			print(nums[i][0]);
			for(int j=1;j<nums[i].length;j++){
				print(str);
				print(nums[i][j]);
			}
			println();
		}
	}
	public void println(byte[][] nums,char c){
		for(int i=0;i<nums.length;i++){
			print(nums[i][0]);
			for(int j=1;j<nums[i].length;j++){
				print(c);
				print(nums[i][j]);
			}
			println();
		}
	}
	public void println(int[] nums,String str){
		print(nums[0]);
		for(int i=1;i<nums.length;i++){
			print(str);
			print(nums[i]);
		}
		println();
	}
	public void println(int[] nums,char c){
		print(nums[0]);
		for(int i=1;i<nums.length;i++){
			print(c);
			print(nums[i]);
		}
		println();
	}
	public void println(int[][] nums,String str){
		for(int i=0;i<nums.length;i++){
			print(nums[i][0]);
			for(int j=1;j<nums[i].length;j++){
				print(str);
				print(nums[i][j]);
			}
			println();
		}
	}
	public void println(int[][] nums,char c){
		for(int i=0;i<nums.length;i++){
			print(nums[i][0]);
			for(int j=1;j<nums[i].length;j++){
				print(c);
				print(nums[i][j]);
			}
			println();
		}
	}
	public void println(long[] nums,String str){
		print(nums[0]);
		for(int i=1;i<nums.length;i++){
			print(str);
			print(nums[i]);
		}
		println();
	}
	public void println(long[] nums,char c){
		print(nums[0]);
		for(int i=1;i<nums.length;i++){
			print(c);
			print(nums[i]);
		}
		println();
	}
	public void println(long[][] nums,String str){
		for(int i=0;i<nums.length;i++){
			print(nums[i][0]);
			for(int j=1;j<nums[i].length;j++){
				print(str);
				print(nums[i][j]);
			}
			println();
		}
	}
	public void println(long[][] nums,char c){
		for(int i=0;i<nums.length;i++){
			print(nums[i][0]);
			for(int j=1;j<nums[i].length;j++){
				print(c);
				print(nums[i][j]);
			}
			println();
		}
	}
	public void println(Byte[] nums,String str){
		print(nums[0]);
		for(int i=1;i<nums.length;i++){
			print(str);
			print(nums[i]);
		}
		println();
	}
	public void println(Byte[] nums,char c){
		print(nums[0]);
		for(int i=1;i<nums.length;i++){
			print(c);
			print(nums[i]);
		}
		println();
	}
	public void println(Byte[][] nums,String str){
		for(int i=0;i<nums.length;i++){
			print(nums[i][0]);
			for(int j=1;j<nums[i].length;j++){
				print(str);
				print(nums[i][j]);
			}
			println();
		}
	}
	public void println(Byte[][] nums,char c){
		for(int i=0;i<nums.length;i++){
			print(nums[i][0]);
			for(int j=1;j<nums[i].length;j++){
				print(c);
				print(nums[i][j]);
			}
			println();
		}
	}
	public void println(Integer[] nums,String str){
		print(nums[0]);
		for(int i=1;i<nums.length;i++){
			print(str);
			print(nums[i]);
		}
		println();
	}
	public void println(Integer[] nums,char c){
		print(nums[0]);
		for(int i=1;i<nums.length;i++){
			print(c);
			print(nums[i]);
		}
		println();
	}
	public void println(Integer[][] nums,String str){
		for(int i=0;i<nums.length;i++){
			print(nums[i][0]);
			for(int j=1;j<nums[i].length;j++){
				print(str);
				print(nums[i][j]);
			}
			println();
		}
	}
	public void println(Integer[][] nums,char c){
		for(int i=0;i<nums.length;i++){
			print(nums[i][0]);
			for(int j=1;j<nums[i].length;j++){
				print(c);
				print(nums[i][j]);
			}
			println();
		}
	}
	public void println(Long[] nums,String str){
		print(nums[0]);
		for(int i=1;i<nums.length;i++){
			print(str);
			print(nums[i]);
		}
		println();
	}
	public void println(Long[] nums,char c){
		print(nums[0]);
		for(int i=1;i<nums.length;i++){
			print(c);
			print(nums[i]);
		}
		println();
	}
	public void println(Long[][] nums,String str){
		for(int i=0;i<nums.length;i++){
			print(nums[i][0]);
			for(int j=1;j<nums[i].length;j++){
				print(str);
				print(nums[i][j]);
			}
			println();
		}
	}
	public void println(Long[][] nums,char c){
		for(int i=0;i<nums.length;i++){
			print(nums[i][0]);
			for(int j=1;j<nums[i].length;j++){
				print(c);
				print(nums[i][j]);
			}
			println();
		}
	}
	public void println(String[] strs,String str){
		println(String.join(str,strs));
	}
	public void println(String[] strs,char c){
		String str = String.valueOf(c);
		println(String.join(str,strs));
	}
	public void println(String[][] strs,String str){
		for(int i=0;i<strs.length;i++){
			println(String.join(str,strs[i]));
		}
	}
	public void println(String[][] strs,char c){
		String str = String.valueOf(c);
		for(int i=0;i<strs.length;i++){
			println(String.join(str,strs[i]));
		}
	}
	public void println(char[] cs,String str){
		print(cs[0]);
		for(int i=1;i<cs.length;i++){
			print(str);
			print(cs[i]);
		}
		println();
	}
	public void println(char[] cs,char c){
		print(cs[0]);
		for(int i=1;i<cs.length;i++){
			print(c);
			print(cs[i]);
		}
		println();
	}
	public void println(char[][] cs){
		for(int i=0;i<cs.length;i++){
			println(cs[i]);
		}
	}
	public void println(char[][] cs,String str){
		print(cs[0]);
		for(int i=1;i<cs.length;i++){
			print(str);
			print(cs[i]);
		}
		println();
	}
	public void println(char[][] cs,char c){
		print(cs[0]);
		for(int i=1;i<cs.length;i++){
			print(c);
			print(cs[i]);
		}
		println();
	}
}
```