import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.HashSet;
import java.util.stream.IntStream;
/**
* ITパスポート試験の合格確率をモンテカルロシミュレーションで計算するシミュレーター。
* 各分野および総合の合格基準を満たす確率を算出します。
* 本シミュレーターはIRT(項目応答理論)採点を再現するものではなく、
* 各採点対象問題の配点が均等であると仮定した「素点計算」に基づきます。
*/
public class IpaPassportSimulator {
// ITパスポート試験の定数(素点計算に基づく)
// 採点対象の総問題数(ダミー8問を除く)
private static final int TOTAL_QUESTIONS_FOR_SCORING = 92;
private static final int DEFAULT_TRIALS = 10000; // 各シナリオでのデフォルト試行回数
// 分野別採点対象問題数と配列インデックス範囲
private static final int STRATEGY_START_INDEX = 0;
private static final int STRATEGY_END_INDEX = 31; // 32問
private static final int MANAGEMENT_START_INDEX = 32;
private static final int MANAGEMENT_END_INDEX = 49; // 18問
private static final int TECHNOLOGY_START_INDEX = 50;
private static final int TECHNOLOGY_END_INDEX = 91; // 42問
// 合格に必要な正解数(素点計算に基づく概算)
// 総合評価点600点以上 / 1000点 -> 92問中 600/1000 * 92 = 55.2問 -> 56問以上
private static final int REQUIRED_TOTAL_CORRECT = 56;
// ストラテジ系300点以上 / 1000点 -> 32問中 300/1000 * 32 = 9.6問 -> 10問以上
private static final int REQUIRED_STRATEGY_CORRECT = 10;
// マネジメント系300点以上 / 1000点 -> 18問中 300/1000 * 18 = 5.4問 -> 6問以上
private static final int REQUIRED_MANAGEMENT_CORRECT = 6;
// テクノロジ系300点以上 / 1000点 -> 42問中 300/1000 * 42 = 12.6問 -> 13問以上
private static final int REQUIRED_TECHNOLOGY_CORRECT = 13;
/**
* 解答方式を定義する列挙型。
* 各方式の正答率を保持します。
*/
public enum AnswerMethod {
FOUR_CHOICES("4択問題", 4),
THREE_CHOICES("3択問題 (1つ除外)", 3),
TWO_CHOICES("2択問題 (2つ除外)", 2);
private final String name;
private final int totalChoices; // 選択肢の数
AnswerMethod(String name, int totalChoices) {
this.name = name;
this.totalChoices = totalChoices;
}
public String getName() {
return name;
}
public int getTotalChoices() {
return totalChoices;
}
// ランダムに正解するかどうかを判定
public boolean isCorrect(Random random) {
return random.nextInt(totalChoices) == 0;
}
}
/**
* シミュレーション結果を保持するレコード。
* (Java 16 以降で利用可能なレコード型を使用しています。古いJavaバージョンの場合は通常のクラスに変換してください)
*/
public record SimulationResult(int knownCorrectQuestions, double successRate) {}
private final Random random;
/**
* IpaPassportSimulator の新しいインスタンスを生成します。
*/
public IpaPassportSimulator() {
this.random = new Random();
}
/**
* 指定されたシナリオでモンテカルロシミュレーションを実行し、合格確率を計算します。
* このメソッドは、ITパスポートの総合および分野別の合格基準を考慮します。
*
* @param answerMethod シミュレーション対象の解答方式
* @param knownCorrectQuestions 事前に知っている正解数(92問全体に対する数)
* @param trials 試行回数
* @return シミュレーション結果を表す {@code SimulationResult} オブジェクト
* @throws IllegalArgumentException 不正な引数が指定された場合
*/
public SimulationResult simulateScenario(AnswerMethod answerMethod, int knownCorrectQuestions, int trials) {
if (knownCorrectQuestions < 0 || knownCorrectQuestions > TOTAL_QUESTIONS_FOR_SCORING) {
throw new IllegalArgumentException(
"事前に知っている正解数 (" + knownCorrectQuestions + ") は、0から採点対象総問題数 (" + TOTAL_QUESTIONS_FOR_SCORING + ") の範囲で指定してください。"
);
}
if (trials <= 0) {
throw new IllegalArgumentException("試行回数は1以上を指定してください。");
}
int successfulTrials = 0;
for (int i = 0; i < trials; i++) {
// 各問題の得点を格納する配列(正解: 1, 不正解: 0)
int[] questionScores = new int[TOTAL_QUESTIONS_FOR_SCORING];
// 1. 「事前に知っている問題」の処理
Set<Integer> knownCorrectIndices = new HashSet<>();
// ランダムに正解する問題のインデックスを選び、得点を1にする
while (knownCorrectIndices.size() < knownCorrectQuestions) {
int randomIndex = random.nextInt(TOTAL_QUESTIONS_FOR_SCORING);
if (knownCorrectIndices.add(randomIndex)) {
questionScores[randomIndex] = 1; // 事前に知っている問題は正解
}
}
// 2. 「残りの問題」の処理(ランダム解答)
for (int j = 0; j < TOTAL_QUESTIONS_FOR_SCORING; j++) {
if (!knownCorrectIndices.contains(j)) { // 事前に知っている問題でなければランダムに解答
if (answerMethod.isCorrect(random)) {
questionScores[j] = 1;
} else {
questionScores[j] = 0;
}
}
}
// 3. 合格条件の判定
// 各分野の正答数を集計
int strategyCorrect = IntStream.rangeClosed(STRATEGY_START_INDEX, STRATEGY_END_INDEX)
.map(idx -> questionScores[idx])
.sum();
int managementCorrect = IntStream.rangeClosed(MANAGEMENT_START_INDEX, MANAGEMENT_END_INDEX)
.map(idx -> questionScores[idx])
.sum();
int technologyCorrect = IntStream.rangeClosed(TECHNOLOGY_START_INDEX, TECHNOLOGY_END_INDEX)
.map(idx -> questionScores[idx])
.sum();
// 総合の正答数を集計
int totalCorrect = IntStream.of(questionScores).sum();
// 全ての合格条件をチェック
boolean passedStrategy = (strategyCorrect >= REQUIRED_STRATEGY_CORRECT);
boolean passedManagement = (managementCorrect >= REQUIRED_MANAGEMENT_CORRECT);
boolean passedTechnology = (technologyCorrect >= REQUIRED_TECHNOLOGY_CORRECT);
boolean passedOverall = (totalCorrect >= REQUIRED_TOTAL_CORRECT);
if (passedStrategy && passedManagement && passedTechnology && passedOverall) {
successfulTrials++;
}
}
double successRate = (double) successfulTrials / trials * 100;
return new SimulationResult(knownCorrectQuestions, successRate);
}
/**
* シミュレーション結果を表示します。
*
* @param result 表示するシミュレーション結果
*/
public void displayResult(SimulationResult result) {
System.out.printf("・事前に%d問知っている場合: 合格率: %.2f%%\n", result.knownCorrectQuestions(), result.successRate());
}
/**
* メインメソッド。ITパスポート試験の各種シナリオでシミュレーションを実行します。
*/
public static void main(String[] args) {
IpaPassportSimulator simulator = new IpaPassportSimulator();
System.out.println("★ITパスポート試験 突破確率計算:ランダム選択方式(モンテカルロシミュレーション)★");
System.out.println("---");
System.out.println("採点対象問題数: " + TOTAL_QUESTIONS_FOR_SCORING + "問");
System.out.println("合格に必要な正解数: 総合" + REQUIRED_TOTAL_CORRECT + "問");
System.out.println(" ストラテジ系: " + REQUIRED_STRATEGY_CORRECT + "問 (" + (STRATEGY_END_INDEX - STRATEGY_START_INDEX + 1) + "問中)");
System.out.println(" マネジメント系: " + REQUIRED_MANAGEMENT_CORRECT + "問 (" + (MANAGEMENT_END_INDEX - MANAGEMENT_START_INDEX + 1) + "問中)");
System.out.println(" テクノロジ系: " + REQUIRED_TECHNOLOGY_CORRECT + "問 (" + (TECHNOLOGY_END_INDEX - TECHNOLOGY_START_INDEX + 1) + "問中)");
System.out.println("---");
System.out.println();
// 各解答方式のシミュレーション
for (AnswerMethod answerMethod : AnswerMethod.values()) {
System.out.println("■" + answerMethod.getName() + " 試行結果");
// knownCorrectQuestions は0問からTOTAL_QUESTIONS_FOR_SCORINGまで繰り返す
for (int i = 0; i <= TOTAL_QUESTIONS_FOR_SCORING; i++) {
try {
SimulationResult result = simulator.simulateScenario(answerMethod, i, DEFAULT_TRIALS);
simulator.displayResult(result);
} catch (IllegalArgumentException e) {
System.err.println("エラー: " + e.getMessage());
}
}
System.out.println(); // 各解答方式の後に空行
}
System.out.println("---");
System.out.println("※本シミュレーターは、ITパスポート試験のIRT(項目応答理論)採点を厳密に再現するものではなく、");
System.out.println(" 各採点対象問題の配点が均等であると仮定した「素点計算」に基づいています。");
System.out.println(" 実際の試験結果と異なる場合があることをご留意ください。");
}
}