import java.util.Random;
/**
* 応用情報技術者試験 午前問題の合格確率をモンテカルロシミュレーションで計算するシミュレーター。
* 解答方式(4択、3択、2択)に応じて合格率を算出します。
*/
public class AppliedInformationTechnologistSimulator {
// 応用情報技術者試験 午前問題の定数
private static final int TOTAL_QUESTIONS = 80; // 総問題数
private static final int PASSING_SCORE = 48; // 合格点(正解数)
private static final int DEFAULT_TRIALS = 100000; // 各シナリオでのデフォルト試行回数
/**
* 解答方式を定義する列挙型。
* 各方式の正答率を保持します。
*/
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;
}
}
/**
* シミュレーション結果を保持するレコード。
* (Java 16 以降で利用可能なレコード型を使用しています。古いJavaバージョンの場合は通常のクラスに変換してください)
*/
public record SimulationResult(int knownCorrectQuestions, double successRate) {}
private final Random random;
/**
* AppliedInformationTechnologistSimulator の新しいインスタンスを生成します。
*/
public AppliedInformationTechnologistSimulator() {
this.random = new Random();
}
/**
* 指定されたシナリオでモンテカルロシミュレーションを実行し、合格確率を計算します。
*
* @param answerMethod シミュレーション対象の解答方式
* @param knownCorrectQuestions 事前に知っている正解数
* @param trials 試行回数
* @return シミュレーション結果を表す {@code SimulationResult} オブジェクト
* @throws IllegalArgumentException 不正な引数が指定された場合
*/
public SimulationResult simulateScenario(AnswerMethod answerMethod, int knownCorrectQuestions, int trials) {
if (knownCorrectQuestions < 0 || knownCorrectQuestions > TOTAL_QUESTIONS) {
throw new IllegalArgumentException(
"事前に知っている正解数 (" + knownCorrectQuestions + ") は、0から総問題数 (" + TOTAL_QUESTIONS + ") の範囲で指定してください。"
);
}
if (trials <= 0) {
throw new IllegalArgumentException("試行回数は1以上を指定してください。");
}
int successfulTrials = 0;
// 知っている問題以外の解答に必要な問題数と正解数
int remainingQuestions = TOTAL_QUESTIONS - knownCorrectQuestions;
int requiredCorrectForPassing = PASSING_SCORE - knownCorrectQuestions;
// 事前知識だけで合否が確定する場合の早期リターン
if (requiredCorrectForPassing <= 0) {
return new SimulationResult(knownCorrectQuestions, 100.00); // 確実に合格
}
if (requiredCorrectForPassing > remainingQuestions) {
return new SimulationResult(knownCorrectQuestions, 0.00); // 合格不可能
}
for (int i = 0; i < trials; i++) {
int guessedCorrect = 0;
for (int j = 0; j < remainingQuestions; j++) {
// 解答方式に応じた確率で正解をシミュレート
if (random.nextInt(answerMethod.getTotalChoices()) == 0) { // 例: 4択なら 0,1,2,3 のうち 0 が正解
guessedCorrect++;
}
}
if (guessedCorrect >= requiredCorrectForPassing) {
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());
}
/**
* メインメソッド。応用情報技術者試験の各種シナリオでシミュレーションを実行します。
*/
public static void main(String[] args) {
AppliedInformationTechnologistSimulator simulator = new AppliedInformationTechnologistSimulator();
System.out.println("★応用情報技術者 午前問題 突破確率計算:ランダム選択方式(モンテカルロシミュレーション)★");
System.out.println("---");
System.out.println("総問題数: " + TOTAL_QUESTIONS + "問, 合格に必要な正解数: " + PASSING_SCORE + "問");
System.out.println("---");
System.out.println();
// 4択問題のシミュレーション
System.out.println("■" + AnswerMethod.FOUR_CHOICES.getName() + " 試行結果");
for (int i = 0; i <= PASSING_SCORE; i++) {
try {
SimulationResult result = simulator.simulateScenario(AnswerMethod.FOUR_CHOICES, i, DEFAULT_TRIALS);
simulator.displayResult(result);
} catch (IllegalArgumentException e) {
System.err.println("エラー: " + e.getMessage());
}
}
System.out.println();
// 3択問題のシミュレーション (1つ選択肢を除外できる場合)
System.out.println("■" + AnswerMethod.THREE_CHOICES.getName() + " 試行結果");
for (int i = 0; i <= PASSING_SCORE; i++) {
try {
SimulationResult result = simulator.simulateScenario(AnswerMethod.THREE_CHOICES, i, DEFAULT_TRIALS);
simulator.displayResult(result);
} catch (IllegalArgumentException e) {
System.err.println("エラー: " + e.getMessage());
}
}
System.out.println();
// 2択問題のシミュレーション (2つ選択肢を除外できる場合)
System.out.println("■" + AnswerMethod.TWO_CHOICES.getName() + " 試行結果");
for (int i = 0; i <= PASSING_SCORE; i++) {
try {
SimulationResult result = simulator.simulateScenario(AnswerMethod.TWO_CHOICES, i, DEFAULT_TRIALS);
simulator.displayResult(result);
} catch (IllegalArgumentException e) {
System.err.println("エラー: " + e.getMessage());
}
}
System.out.println("---");
}
}