ABC - 111- A&B&C

#AtCoder ABC 111 A&B&C
[AtCoder - 111](https://atcoder.jp/contests/abc111)

#A問題

 - '9'を'1'に、'1'を'9'に変換する
 - Streamでcharを扱ってみたが、毎回Stringに変換する必要があるためすごくパフォーマンスが悪い
 - charのstreamがないので使いづらいです。。。

コメントアウトしているのはfor文版

```java
	private void solveA() {
		Scanner scanner = null;
		String line = "";

		try {
			scanner = new Scanner(System.in);
			line = scanner.nextLine();

			String res = line.chars()
					.mapToObj(c -> {
						switch ((char) c) {
						case '1':
							return String.valueOf('9');
						case '9':
							return String.valueOf('1');
						default:
							return String.valueOf(c);
						}
					}).collect(Collectors.joining());

			System.out.println(res);

			//			char[] wkArray = line.toCharArray();
			//			StringBuffer buf = new StringBuffer();
			//			for (int i = 0; i < wkArray.length; i++) {
			//				switch (wkArray[i]) {
			//				case '1':
			//					buf.append(9);
			//					break;
			//				case '9':
			//					buf.append(1);
			//					break;
			//				default:
			//					buf.append(wkArray[i]);
			//					break;
			//				}
			//
			//			}
			//
			//			System.out.println(buf.toString());

		} finally {
			if (scanner != null) {
				scanner.close();
			}
		}
	}
```

#B問題

 - N以上の数で、同じ数字で構成される3桁の数値を出力
 - 実装ではNからスタートして、1つずつ数値をchar[]に変換して比較しているけど、3桁以内限定ならもっと楽な方法もあった
    - 考えられる値は　{$111,222,333,444,555,666,777,888,999$}　しかないのだからそれで直接比較してもよかったな

```java
	private void solveB() {
		Scanner scanner = null;
		String line = "";

		try {
			scanner = new Scanner(System.in);
			line = scanner.nextLine();
			int start = Integer.parseInt(line);

			for (int outer = start; outer <= 999; outer++) {
				char[] wkArray = Integer.toString(outer).toCharArray();

				if (wkArray[0] == wkArray[1] && wkArray[1] == wkArray[2]) {
					System.out.println(outer);
					return;
				}
			}

		} finally {
			if (scanner != null) {
				scanner.close();
			}
		}
	}
```

#C問題

 - 偶数番目と奇数番目を分けて考える
 - 主な解説はインラインで書いた

```java
	private void solveC() {

		int num = 0;

		try (Scanner scanner = new Scanner(System.in)) {
			num = scanner.nextInt();

			int[] wk = IntStream.range(0, num).map(i -> scanner.nextInt()).toArray();

			Map<Integer, Integer> wkMapEven = new HashMap<Integer, Integer>();
			Map<Integer, Integer> wkMapOdd = new HashMap<Integer, Integer>();

			/*
			 * 奇数番と偶数番でカウントを分ける
			 */
			for (int i = 0; i < num; i++) {
				int val = wk[i];
				if (i % 2 == 0) {
					wkMapEven.merge(val, 1, (oldV, newV) -> oldV + newV);
				} else {
					wkMapOdd.merge(val, 1, (oldV, newV) -> oldV + newV);
				}
			}

			int cnt = 0;
			/*
			 * 偶数番を出現数順でソート
			 */
			long[][] resEven = new long[wkMapEven.size()][2];
			for (Entry<Integer, Integer> entry : wkMapEven.entrySet()) {
				resEven[cnt][0] = entry.getKey();
				resEven[cnt][1] = entry.getValue();
				cnt++;
			}

			Arrays.sort(resEven, (x, y) -> {
				if (x[1] < y[1]) {
					return -1;
				} else if (x[1] > y[1]) {
					return 1;
				} else {
					if (x[0] < y[0]) {
						return -1;
					} else if (x[0] > y[0]) {
						return 1;
					} else {
						return 0;
					}
				}
			});

			cnt = 0;
			/*
			 * 奇数番を出現数順でソート
			 */
			long[][] resOdd = new long[wkMapOdd.size()][2];
			for (Entry<Integer, Integer> entry : wkMapOdd.entrySet()) {
				resOdd[cnt][0] = entry.getKey();
				resOdd[cnt][1] = entry.getValue();
				cnt++;
			}

			Arrays.sort(resOdd, (x, y) -> {
				if (x[1] < y[1]) {
					return -1;
				} else if (x[1] > y[1]) {
					return 1;
				} else {
					if (x[0] < y[0]) {
						return -1;
					} else if (x[0] > y[0]) {
						return 1;
					} else {
						return 0;
					}
				}
			});

			long sum = 0;
			//偶数番の最頻出
			long maxEven = resEven[resEven.length - 1][0];
			//偶数番の最頻出-1
			long maxEvenVal = resEven[resEven.length - 1][1];
			//奇数番の最頻出
			long maxOdd = resOdd[resOdd.length - 1][0];
			//奇数番の最頻出-1
			long maxOddVal = resOdd[resOdd.length - 1][1];

			//偶数番のトータル
			long even = Arrays.stream(resEven).mapToLong(i -> i[1]).sum();
			//奇数番のトータル
			long odd = Arrays.stream(resOdd).mapToLong(i -> i[1]).sum();

			//偶数番と奇数番の最頻出が同じかどうか
			if (maxEven != maxOdd) {
				//最頻出値が違うので、お互いに最頻出を除いた全てを最頻出値に書き換える
				sum = (even - maxEvenVal) + (odd - maxOddVal);
			} else {
				/*
				 * 最頻出値が同じなので、最頻出or最頻出-1の値に書き換えた場合の回数を比べ
				 * 書き換え回数の少ないほうを採用
				 */

				/*
				 * 0で初期化するのは、偶数番の値が1つしかないパターンがあるため
				 * 値が1つの場合は、最頻出と最頻出-1が同じ値となる（最頻出-1は実質存在しない）
				 */
				long maxEven2Val = 0;
				if (resEven.length != 1) {
					//値が複数あるので、再頻出-1
					maxEven2Val = resEven[resEven.length - 2][1];
				}

				//偶数番と同じ処理
				long maxOdd2Val = 0;
				if (resOdd.length != 1) {
					maxOdd2Val = resOdd[resOdd.length - 2][1];
				}

				/*
				 * 最頻出-1は、値が1つしかない場合は0となる
				 * 例
				 * 1 2 1 4 1 4
				 * 奇数番の最頻出は１で出現回数は３
				 * 最頻出-1は0
				 */

				//偶数番の総計-偶数番の最頻出 + 奇数番の総計-奇数番の最頻出
				long val1 = (even - maxEvenVal) + (odd - maxOdd2Val);
				//偶数番の総計-偶数番の最頻出-1 + 奇数番の総計-奇数番の最頻出
				long val2 = (even - maxEven2Val) + (odd - maxOddVal);
				sum = Math.min(val1, val2);

			}
			System.out.println(sum);
		}
	}
```