一週間で身につくJava言語の基本の解答集 ~基本編の問題②~

https://qiita.com/tachiyuu1011/items/2e7391bd62cd3fad0eb6

上記の内容のつづき～
チャレンジ問題の解答集

## 基本問題(7)：チャレンジ問題
### prob8-1.(難易度★★)（ピタゴラス数）
```java
public class PythagoreanTriplets {
    public static void main(String[] args) {
        // a, b, c の組み合わせを探すための二重ループ
        for (int a = 1; a <= 100; a++) {
            for (int b = a; b <= 100; b++) {
                // ピタゴラスの定理に基づいて c の二乗を計算
                int cSquare = a * a + b * b;
                // c を計算
                int c = (int) Math.sqrt(cSquare);

                // c が整数であり、100以下の場合、三重数として表示
                if (c * c == cSquare && c <= 100) {
                    System.out.println("a=" + a + ", b=" + b + ", c=" + c);
                }
            }
        }
    }
}
```

### prob8-2.(難易度★★)（ピタゴラス数2）
```java
import java.util.ArrayList;
import java.util.List;

public class TripletsGenerator {

    public static void main(String[] args) {
        // 三重数を生成して表示
        generateAndPrintTriplets(100);
    }

    public static void generateAndPrintTriplets(int maxC) {
        // 三重数のリストを生成
        List<Triplet> triplets = generateTriplets(maxC);

        // 生成した三重数を表示
        for (Triplet triplet : triplets) {
            System.out.println(triplet);
        }
    }

    public static List<Triplet> generateTriplets(int maxC) {
        // 三重数を格納するリスト
        List<Triplet> triplets = new ArrayList<>();

        // a, b の値をループして三重数を生成
        for (int a = 1; a <= maxC; a++) {
            for (int b = a; b <= maxC; b++) {
                // ピタゴラスの定理を使用して c を計算
                int cSquared = a * a + b * b;
                int c = (int) Math.sqrt(cSquared);

                // c が整数であり、maxC以下の場合、三重数として追加
                if (c * c == cSquared && c <= maxC) {
                    triplets.add(new Triplet(a, b, c));
                }
            }
        }

        return triplets;
    }
}

class Triplet {
    private int a;
    private int b;
    private int c;

    public Triplet(int a, int b, int c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    @Override
    public String toString() {
        return "a=" + a + ", b=" + b + ", c=" + c;
    }
}
```

### prob8-3.(難易度★★)（階乗を求める計算）

```java
public class FactorialCalculator {

    public static void main(String[] args) {
        int number = 6; // 階乗を求めたい数値
        long factorial = calculateFactorial(number);
        System.out.println(number + "の階乗は " + factorial + " です。");
    }

    public static long calculateFactorial(int n) {
        if (n < 0) {
            throw new IllegalArgumentException("負の整数の階乗は定義されていません。");
        }
        return factorialRecursive(n);
    }

    // 階乗を再帰的に計算するメソッド
    private static long factorialRecursive(int n) {
        if (n == 0 || n == 1) {
            return 1; // 0の階乗および1の階乗は1
        }
        return n * factorialRecursive(n - 1); // 再帰呼び出しで階乗を計算
    }
}
```
### prob8-4.(難易度★★)（桁数を求める計算）
```java
import java.util.Random;

public class DigitCounter {

    public static void main(String[] args) {
        Random random = new Random();
        int number = random.nextInt(1000) + 1; // 1から1000までのランダムな数を生成

        // 生成した数を表示
        System.out.println("生成された数: " + number);

        // 桁数を計算して表示
        int digits = countDigits(number);
        System.out.println("桁数: " + digits);
    }

    // 桁数を計算するメソッド
    public static int countDigits(int number) {
        if (number < 0) {
            throw new IllegalArgumentException("負の数の桁数は計算できません。");
        }

        if (number == 0) {
            return 1; // 0の桁数は1
        }

        int digits = 0;
        while (number > 0) {
            number /= 10;
            digits++;
        }
        return digits;
    }
}
```
### prob8-5.(難易度★★)（いまさら世界のナベアツ計算）
```java
public class NabeatsuCalculator {

    public static void main(String[] args) {
        for (int number = 1; number <= 100; number++) {
            if (isNabeatsuNumber(number)) {
                System.out.println(number);
            }
        }
    }

    // 3で割り切れるか、数値の中に3が含まれるかを判定するメソッド
    public static boolean isNabeatsuNumber(int number) {
        return (number % 3 == 0) || containsDigitThree(number);
    }

    // 数値の中に3が含まれるかを判定するメソッド
    public static boolean containsDigitThree(int number) {
        while (number > 0) {
            int digit = number % 10;
            if (digit == 3) {
                return true;
            }
            number /= 10;
        }
        return false;
    }
}
```
### prob8-6.(難易度★★★)（分数の計算１）
```java
import java.util.Random;

public class FractionCalculator {

	public static void main(String[] args) {
		Random random = new Random();

		// 分数1の生成
		int numerator1 = random.nextInt(9) + 1; // 分子は1から9のランダムな整数
		int denominator1 = random.nextInt(9) + 2; // 分母は2から10のランダムな整数

		// 分数2の生成
		int numerator2 = random.nextInt(9) + 1;
		int denominator2 = random.nextInt(9) + 2;

		// 分数1を表示
		System.out.print("分数1: " + numerator1 + "/" + denominator1 + "、");

		// 分数2を表示
		System.out.print("分数2: " + numerator2 + "/" + denominator2 + "、");

		// 分数を足し合わせて結果を表示
		int[] resultFraction = addFractions(numerator1, denominator1, numerator2, denominator2);
		int gcd = calculateGCD(resultFraction[0], resultFraction[1]);

		// 約分可能な場合は約分して表示
		if (gcd > 1) {
			resultFraction[0] /= gcd;
			resultFraction[1] /= gcd;
			System.out.println("結果: " + resultFraction[0] + "/" + resultFraction[1]);
		} else {
			// 整数になる場合
			if (resultFraction[0] % resultFraction[1] == 0) {
				int wholePart = resultFraction[0] / resultFraction[1];
				System.out.println("結果: " + wholePart);
			} else {
				// 通常のケース
				System.out.println("結果: " + resultFraction[0] + "/" + resultFraction[1]);
			}
		}
	}

	// 分数の足し算を行うメソッド
	public static int[] addFractions(int numerator1, int denominator1, int numerator2, int denominator2) {
		int resultNumerator = numerator1 * denominator2 + numerator2 * denominator1;
		int resultDenominator = denominator1 * denominator2;
		return new int[] { resultNumerator, resultDenominator };
	}

	// 最大公約数を計算するメソッド
	public static int calculateGCD(int a, int b) {
		if (b == 0) {
			return a;
		}
		return calculateGCD(b, a % b);
	}
}
```
### prob8-7.(難易度★★★)（分数の計算２）
```java
import java.util.Random;

public class FractionCalculator2 {

    public static void main(String[] args) {
        Random random = new Random();

        // ランダムな分数1を生成
        int numerator1 = random.nextInt(10) + 1;
        int denominator1 = random.nextInt(10) + 1;

        // ランダムな分数2を生成
        int numerator2 = random.nextInt(10) + 1;
        int denominator2 = random.nextInt(10) + 1;

        // 分数を表示
        System.out.println(formatFraction(numerator1, denominator1) + " + " + formatFraction(numerator2, denominator2) + " = "
                + formatFraction(numerator1 * denominator2 + numerator2 * denominator1, denominator1 * denominator2));
    }

    // 分数を整形して文字列で返すメソッド
    public static String formatFraction(int numerator, int denominator) {
        if (numerator == 0) {
            return "0";
        } else if (numerator < denominator) {
            return numerator + "/" + denominator;
        } else if (numerator % denominator == 0) {
            return String.valueOf(numerator / denominator);
        } else {
            int wholePart = numerator / denominator;
            int remainder = numerator % denominator;
            return wholePart + "." + remainder + "/" + denominator;
        }
    }
}
```
### prob8-8.(難易度★★)（約数）
```java
import java.util.Scanner;

public class DivisorCalculator {

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);

		System.out.print("1から1000までの数値を入力してください: ");
		int number = scanner.nextInt();

		if (number < 1 || number > 1000) {
			System.out.println("有効な範囲外の数値です。1から1000までの数値を入力してください。");
		} else {
			System.out.println(number + "の約数は以下の通りです:");
			printDivisors(number);
		}

		scanner.close();
	}

	// 約数を計算して表示するメソッド
	public static void printDivisors(int number) {
		for (int i = 1; i <= number; i++) {
			if (number % i == 0) {
				System.out.println(i);
			}
		}
	}
}
```
### prob8-9.(難易度★★★)（完全数）
```java
public class PerfectNumbers {

    public static void main(String[] args) {
        System.out.println("1から10,000以下の完全数:");

        for (int number = 1; number <= 10_000; number++) {
            if (isPerfectNumber(number)) {
                System.out.println(number);
            }
        }
    }

    // 完全数かどうかを判定するメソッド
    public static boolean isPerfectNumber(int number) {
        int sumOfDivisors = 0;
        for (int i = 1; i <= number / 2; i++) {
            if (number % i == 0) {
                sumOfDivisors += i;
            }
        }
        return sumOfDivisors == number;
    }
}
```
### prob8-9.(難易度★★)（数値の分類）
```java
import java.util.Random;

public class EvenOddArray {

	public static void main(String[] args) {
		int[] originalArray = new int[10];
		int[] evenArray;
		int[] oddArray;

		// 配列に1から100までの整数をランダムに代入
		generateRandomNumbers(originalArray);

		// 偶数と奇数の個数を数える
		int evenCount = countEvenNumbers(originalArray);
		int oddCount = originalArray.length - evenCount;

		// 偶数と奇数の配列を作成
		evenArray = new int[evenCount];
		oddArray = new int[oddCount];

		// 偶数と奇数に分類して配列に再代入
		segregateEvenOddNumbers(originalArray, evenArray, oddArray);

		// 配列の値を表示
		System.out.println("元の配列:");
		printArray(originalArray);

		System.out.println("\n偶数:");
		printArray(evenArray);

		System.out.println("\n奇数:");
		printArray(oddArray);
	}

	// 配列に1から100までの整数をランダムに代入するメソッド
	public static void generateRandomNumbers(int[] arr) {
		Random rand = new Random();
		for (int i = 0; i < arr.length; i++) {
			arr[i] = rand.nextInt(100) + 1;
		}
	}

	// 偶数の個数を数えるメソッド
	public static int countEvenNumbers(int[] arr) {
		int count = 0;
		for (int num : arr) {
			if (num % 2 == 0) {
				count++;
			}
		}
		return count;
	}

	// 偶数と奇数に分類して配列に再代入するメソッド
	public static void segregateEvenOddNumbers(int[] original, int[] even, int[] odd) {
		int evenIndex = 0;
		int oddIndex = 0;
		for (int num : original) {
			if (num % 2 == 0) {
				even[evenIndex++] = num;
			} else {
				odd[oddIndex++] = num;
			}
		}
	}

	// 配列の値を表示するメソッド
	public static void printArray(int[] arr) {
		for (int num : arr) {
			System.out.print(num + " ");
		}
		System.out.println();
	}
}
```
### prob8-10.(難易度★★)（フィボナッチ数列）
```java
public class FibonacciSequence {

	public static void main(String[] args) {
		int n = 40; // フィボナッチ数列の要素数
		int[] fibonacciArray = generateFibonacci(n);

		// フィボナッチ数列を表示
		System.out.println("フィボナッチ数列（40まで）:");
		for (int i = 0; i <= n; i++) {
			System.out.print(fibonacciArray[i] + " ");
		}
	}

	public static int[] generateFibonacci(int n) {
		int[] fibonacciArray = new int[n + 1];

		// 最初の2つの要素を初期化
		fibonacciArray[0] = 1;
		fibonacciArray[1] = 1;

		// フィボナッチ数列を生成
		for (int i = 2; i <= n; i++) {
			fibonacciArray[i] = fibonacciArray[i - 1] + fibonacciArray[i - 2];
		}

		return fibonacciArray;
	}
}
```
### prob8-10.(難易度★★)（トリボナッチ数列）
```java
public class TribonacciSequence {

    public static void main(String[] args) {
        int n = 30; // トリボナッチ数列の要素数
        int[] tribonacciArray = generateTribonacci(n);

        // トリボナッチ数列を表示
        System.out.println("トリボナッチ数列（30まで）:");
        for (int i = 0; i <= n; i++) {
            System.out.print(tribonacciArray[i] + " ");
        }
    }

    public static int[] generateTribonacci(int n) {
        int[] tribonacciArray = new int[n + 1];

        // 最初の3つの要素を初期化
        tribonacciArray[0] = 1;
        tribonacciArray[1] = 1;
        tribonacciArray[2] = 2;

        // トリボナッチ数列を生成
        for (int i = 3; i <= n; i++) {
            tribonacciArray[i] = tribonacciArray[i - 1] + tribonacciArray[i - 2] + tribonacciArray[i - 3];
        }

        return tribonacciArray;
    }
}
```
### prob8-11.(難易度★★)（集合）
```java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class CommonAndUniqueValues {

    public static void main(String[] args) {
        int[] array1 = {4, 9, 4, 3, 6, 8, 7, 1, 3, 10};
        int[] array2 = {7, 3, 10, 7, 5, 9, 4, 9, 9, 1};

        // 共通の数を見つけて表示
        int[] commonValues = findCommonValues(array1, array2);
        System.out.println("共通の数：" + Arrays.toString(commonValues));

        // どちらかに入っている数を見つけて表示
        int[] uniqueValues = findUniqueValues(array1, array2);
        System.out.println("どちらかに入っている数：" + Arrays.toString(uniqueValues));
    }

    // 共通の値を検索して配列に格納するメソッド
    public static int[] findCommonValues(int[] arr1, int[] arr2) {
        List<Integer> commonList = new ArrayList<>();
        for (int num1 : arr1) {
            for (int num2 : arr2) {
                if (num1 == num2 && !commonList.contains(num1)) {
                    commonList.add(num1);
                    break; // 同じ数値を重複して追加しないためにbreakを使用
                }
            }
        }
        return listToArray(commonList);
    }

    // どちらかに入っている値を検索して配列に格納するメソッド
    public static int[] findUniqueValues(int[] arr1, int[] arr2) {
        List<Integer> uniqueList = new ArrayList<>();
        // arr1の要素をチェック
        for (int num : arr1) {
            if (!contains(arr2, num) && !uniqueList.contains(num)) {
                uniqueList.add(num);
            }
        }
        // arr2の要素をチェック
        for (int num : arr2) {
            if (!contains(arr1, num) && !uniqueList.contains(num)) {
                uniqueList.add(num);
            }
        }
        return listToArray(uniqueList);
    }

    // List<Integer>をint[]に変換するユーティリティメソッド
    public static int[] listToArray(List<Integer> list) {
        int[] array = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            array[i] = list.get(i);
        }
        return array;
    }

    // 配列に指定の値が含まれているかをチェックするユーティリティメソッド
    public static boolean contains(int[] arr, int value) {
        for (int num : arr) {
            if (num == value) {
                return true;
            }
        }
        return false;
    }
}
```
### prob8-12.(難易度★★★)（エラトステネスのふるい）
```java
public class SieveOfEratosthenes {
    public static void main(String[] args) {
        int n = 100; // 素数を探す範囲（100以下）
        boolean[] isPrime = new boolean[n + 1]; // 素数の判定結果を格納する配列

        // 初期化: 最初は全ての数を素数と仮定
        for (int i = 2; i <= n; i++) {
            isPrime[i] = true;
        }

        // エラトステネスのふるいのアルゴリズムを実行
        for (int p = 2; p * p <= n; p++) {
            // 素数でない場合はスキップ
            if (!isPrime[p]) {
                continue;
            }

            // pの倍数を全て素数でないとマーク
            for (int i = p * p; i <= n; i += p) {
                isPrime[i] = false;
            }
        }

        // 結果を表示
        System.out.println("100以下の素数:");
        for (int i = 2; i <= n; i++) {
            if (isPrime[i]) {
                System.out.print(i + " ");
            }
        }
    }
}
```
### prob8-12.(難易度★★★)（素因数分解）
```java
import java.util.Random;

public class PrimeFactorization {
    public static void main(String[] args) {
        Random random = new Random();

        for (int i = 0; i < 10; i++) { // 10個の乱数を生成して素因数分解
            int number = random.nextInt(99) + 2; // 2から100の乱数を生成
            System.out.println("元の数: " + number);
            System.out.print("素因数分解: ");

            primeFactorization(number);

            System.out.println(); // 改行
        }
    }

    public static void primeFactorization(int n) {
        int divisor = 2;

        while (n > 1) {
            if (n % divisor == 0) {
                System.out.print(divisor);
                n /= divisor;
                if (n > 1) {
                    System.out.print(" × ");
                }
            } else {
                divisor++;
            }
        }
    }
}
```
### prob8-13.(難易度★★★)（並べ替え）
```java
import java.util.Random;

public class SortArrayDescending {
    public static void main(String[] args) {
        int[] array = new int[10];
        Random random = new Random();

        // 配列に1から100までの乱数を代入
        for (int i = 0; i < array.length; i++) {
            array[i] = random.nextInt(100) + 1;
        }

        // 配列を大きい順に並べ替え
        for (int i = 0; i < array.length - 1; i++) {
            int maxIndex = i;

            // 最大値を探す
            for (int j = i + 1; j < array.length; j++) {
                if (array[j] > array[maxIndex]) {
                    maxIndex = j;
                }
            }

            // 最大値と現在の位置の値を交換
            int temp = array[i];
            array[i] = array[maxIndex];
            array[maxIndex] = temp;
        }

        // 並べ替えた配列を表示
        System.out.println("降順に並べ替えた配列:");
        for (int num : array) {
            System.out.print(num + " ");
        }
    }
}
```
### prob8-14.(難易度★★★)（友愛数）
```java
public class AmicableNumbers {
    public static void main(String[] args) {
        int limit = 10000;

        for (int num1 = 2; num1 <= limit; num1++) {
            int num2 = getSumOfDivisors(num1);

            if (areAmicable(num1, num2)) {
                System.out.println(num1 + " と " + num2 + " は友愛数です。");
            }
        }
    }

    // 約数の和を計算するメソッド
    public static int getSumOfDivisors(int n) {
        int sum = 1;

        for (int i = 2; i * i <= n; i++) {
            if (n % i == 0) {
                sum += i;
                if (i != n / i) {
                    sum += n / i;
                }
            }
        }

        return sum;
    }

    // 友愛数かどうかを判定するメソッド
    public static boolean areAmicable(int num1, int num2) {
        return num2 > num1 && num2 <= 10000 && getSumOfDivisors(num2) == num1;
    }
}
```
### prob8-14.(難易度★★★)（ロッカー問題）
```java
public class LockerExperiment {
    public static void main(String[] args) {
        int numLockers = 50;
        int[] lockers = new int[numLockers];

        // ロッカーの初期状態を設定（すべて閉じている）
        for (int i = 0; i < numLockers; i++) {
            lockers[i] = 1;
        }

        // 生徒がロッカーを開け閉めする操作をシミュレーション
        for (int student = 1; student <= numLockers; student++) {
            for (int locker = student; locker <= numLockers; locker += student) {
                // ロッカーを開け閉めする
                lockers[locker - 1] *= -1;
            }
        }

        // 開いているロッカーの数をカウント
        int openLockerCount = 0;
        for (int locker : lockers) {
            if (locker == -1) {
                openLockerCount++;
            }
        }

        System.out.println("最終的に開いているロッカーの数は " + openLockerCount + " 個です。");
    }
}
```