最終課題

ステップ0

以下のステップを実行する前に,概要課題のデータからexam.csvminiexam.csv, assignments.csv の3つのデータをダウンロードしておいてください.

ステップ1

1-A. 問題説明

プログラムの実行時に,引数に試験成績のcsvファイル(exam.csv)が渡されます. csvファイルは,IDと点数が記載されています. その点数を読み,秀,優,良,可,不可,K(未受験)のグレードを判定してください. IDは番号順に並んでいますが,番号が飛んでいる場合があります. その場合は,飛んだ番号は未受験であるため,0点,Kと出力してください.

点数が60点未満が不可,60以上70点未満が可,70点以上80点未満が良,80点以上90点未満が優, 90点以上が秀です. K(未受験)はexam.csvに掲載されていません.つまり,IDが飛んだ時,その学生のグレードをKにしてください.

ファイル名は,GradeChecker1.javaとしてください. なお,入力ファイルの行数が増減した場合でも適切に処理が行えるようにしてください.

1-B. 実行例

$ cat exam.csv
1,70.05347594 # <- ID 2が飛んでいる.
3,86.09625668
4,85.02673797
5,56.14973262
... 以下略
$ java GradeChecker1 exam.csv
1,70.053,良
2,0.000,K # <- IDがexam.csvに存在しないのは,未受験であり,Kとする.
3,86.096,優
4,85.027,優
5,56.150,不可
... 以下略

1-C. ヒント

1-C-1. リンク集

1-C-2. Integer型同士の比較

実はInteger型もString型と同じく,参照型であり,==での比較(参照先の一致性検査)性では,内容の一致性は判定できません. 内容の一致性判定には、Objects.equalsを利用します.

Integer num1 = 1;
Integer num2 = new Integer("1");
System.out.println(num1 == num2);
// 「false」が出力される。
System.out.println(Objects.equals(num1, num2));
// 「true」が出力される。

1-C-3. IDの抜けについて

IDが連続して抜けていた場合の処理も考えてみましょう.次の2通りの考え方があります.

1-D. 評価項目

ステップ2

2-A. 問題説明

プログラムの実行時に,引数に試験成績(exam.csv),課題(assignments.csv),小テスト(miniexam.csv)の3つのcsvファイルが渡されます.

それらの点数を読み,秀,優,良,可,不可,K(未受験)のグレードを判定してください. 最終成績の算出方法は,定期試験が70%,課題が25%,小テストの受験率が5%です. 小数点以下は切り上げてください.

ファイル名は GradeChecker2.javaとしてください. なお,入力ファイルの行数が増減した場合でも適切に処理が行えるようにしてください.

それぞれのcsvファイルの内容は次の通りです.

2-A-1. 試験成績

$ cat exam.csv
1,70.05347594
3,86.09625668
4,85.02673797
5,56.14973262
... 以下略

試験成績のcsvファイルでは,IDは番号順に並んでいますが,番号が飛んでいる場合があります. その場合は,飛んだ番号は未受験であるため,0点,Kと出力してください.

2-A-2. 課題

$ cat assignments.csv
1,10,8,8,10,8,10
2,,,,,,
3,8,9,8,,,10
4,8,10,10,8,10,10
5,10,10,,0,10,
... 以下略

各行は「ID,課題1,課題2,課題3,課題4,課題5,課題6」の順に各課題の成績が記載されています. 点数が記載されていない部分は未提出です. 課題1〜6までの点数を合計した点数がその人の課題点であり,最高点は60点です. IDは昇順に並んでおり,途中に抜けている番号はありません.

2-A-3. 小テスト

$ cat miniexam.csv
1,5,2,,1,2,2,,1,5,0,0,5,0,2
2,5,3,1,,1,0,,0,3,,,,0,1
4,7,2,8,6,9,4,,4,,2,6,6,0,
5,3,5,7,,3,5,,1,3,,2,4,0,0
6,6,8,10,8,,,7,10,9,8,5,7,0,
... 以下略

各行は,IDから始まり,14回分の小テストの点数が記載されています. 点数の記載がない部分は小テストを未受験であり,0は受験したものの点数が取れなかったことを表しています. また,IDは昇順に並んでいますが,途中飛んでいる場合もあります.

この小テストでは,受験率を算出してください. すなわち,書かれている点数は重要ではなく,点数が書かれているか否かが重要です. 受験回数を14で割り,受験率を算出してください. その受験率を小テストの点数とします.

2-A-4. 成績の算出

プログラムには,コマンドライン引数で exam.csvassignments.csvminiexam.csvの順にファイルが指定されます. IDが$n$の学生の最終成績$s$を次の式で算出してください. $e$が定期試験の点数,$a$が課題の合計点,$t$が小テストの受験率(0.0〜1.0)とします.

\[ s=\frac{70}{100}e + \frac{25}{60}a + 5t \]

2-B. 実行例

$ java GradeChecker2 exam.csv assignments.csv miniexam.csv
1,76,70.053,54,12,良
2, 4,,0,9,K
3,75,86.096,35,0,良
4,87,85.027,56,11,優
5,56,56.150,30,11,不可
6,71,68.984,45,11,良
... 以下略

IDの昇順になるように出力してください. 各行は,ID,最終成績,試験の点数,課題の合計点,小テストの受験回数, グレードをコンマ区切りで出力してください.

2-C. ヒント

2-C-1. 値の切り上げ

最終成績$s$は小数点以下を切り上げてください. 切り上げは下のように Math.ceilを利用してください. また,グレード算出の時にKか不可かを判定するため, 定期試験を受験したか否かのフラグを保持しておくと良いでしょう.

Double givenValue = 17.01;
Double ceiledValue = Math.ceil(givenValue);
// ceiledValueには 18.0 が代入される.

2-D. 評価項目

ステップ3

3-A. 問題説明

ステップ2で出力した内容の統計情報を出力しましょう. 統計情報とは,各学生の最終成績の平均,最高,最低点を算出してください. ただし,K,不可の学生を含めた場合と含めない場合での点数の両方を算出しましょう.

次に,各グレードに何人が属しているかを数えて出力してください.

ファイル名は,GradeChecker3.javaとしてください. なお,入力ファイルを変更して,行数が増減した場合でも適切に処理が行えるようにしてください.

3-B. 実行例

$ java GradeChecker3 exam.csv assignments.csv miniexam.csv
1,76,70.053,54,12,良
2, 4,,0,9,K
3,75,86.096,35,0,良
4,87,85.027,56,11,優
5,56,56.150,30,11,不可
6,71,68.984,45,11,良
... 途中省略
149,92,93.583,54,9,秀
150,80,76.471,58,6,優
151, 0,,0,0,K
152,64,60.963,38,14,可
Avg: 63.224 (78.226)
Max: 96.000 (96.000)
Min: 0.000 (60.000)
秀:   11
優:   37
良:   41
可:   17
不可: 26
K:    20

出力例は上記の通りです. IDの昇順になるように出力してください. 各行は,ID,最終成績,試験の点数,課題の合計点,小テストの受験回数, グレードをコンマ区切りで出力してください.

すべての学生の成績を出力し終えたら,統計情報を出力してください. 統計情報は,最終成績の平均,最大,最小です. カッコ内の情報は,単位取得者(最終成績が60点以上)のみを対象に求めた平均,最大,最小です.

それらを出力し終えたら,今度は,各グレードに属する人数を出力してください.

3-D. 評価項目

ステップ4

4-A. 問題説明

この講義の成績算出には,特別ルールが適用されます. それは,定期試験の素点が80点以上であれば,最終成績をその点数とする,というものです. ただし,ステップ2で算出した成績の方が上であれば,その成績を最終成績とします.

また,グレードに※を追加してください. ※は出席日数不足を表しています. 条件は,定期試験を受験し,最終成績が60点未満かつ,小テストの受験回数が7回以下の場合に,グレードを※とします. 定期試験を受験していない学生のグレードはKとしてください.

この特別ルールを適用したプログラムを作成してください. ファイル名は,GradeChecker4.javaとします. なお,入力ファイルを変更して行数が増減した場合でも適切に処理が行えるようにしてください.

4-B. 実行例

$ java GradeChecker4 exam.csv assignments.csv miniexam.csv
1,76,70.053,54,12,良
2, 4,,0,9,K
3,87,86.096,35,0,優
4,87,85.027,56,11,優
5,57,56.150,30,11,不可
6,71,68.984,45,11,良
7,76,75.936,48,6,良
8,84,83.957,38,11,優
9,36,32.086,26,5,※
... 途中省略
149,94,93.583,54,9,秀
150,80,76.471,58,6,優
151, 0,,0,0,K
152,64,60.963,38,15,可
Avg: 65.868 (80.027)
Max: 96.000 (96.000)
Min: 0.000 (60.000)
秀:   14
優:   49
良:   35
可:   13
不可:  8
K:    20
※:    13

ステップ3までは, IDが3の学生の最終成績は75でした. ここで特別ルールを適用すると,テストの点数が 86.096 ですので,この点数を切り上げ,87点が最終成績となっています.

一方,IDが4の学生を見てみると,テストの点数が 85.027 と 80 点を超えています. しかし,ステップ2 で計算した点数の方が高いため,最終成績が87になっています.

また,IDが5の学生と9の学生では,最後の小テストの受験回数の違いが,グレードの違いになっています. さらに,グレードが一つ追加されたため,統計情報にも変更が加わっています.

4-C. ヒント

4-D. 評価項目

ステップ5

5-A. 問題説明

今までは,コマンドライン引数でexam.csvassignments.csvminiexam.csvの順でファイルが渡されていました. これを自由な順序で指定するようにプログラムを変更します. しかし,本当に自由な順序で渡されるとどのファイルに何が書かれているのかがわかりませんので,オプションでファイルを指定しましょう.

ファイルが指定されない場合は,その成績は0点として最終成績を算出してください. 最終成績の計算式は変更する必要はありません. また,-outputオプションが指定された場合は,そのファイルに結果を出力してください. 指定されなかった場合は,標準出力に出力してください.

ファイル名は,GradeChecker5.javaとしてください. なお,入力ファイルが変更され,行数が増減した場合でも適切に処理が行えるようにしてください.

5-B. 実行例

$ java GradeChecker5 -record exam.csv -assignments assignments.csv -output result.csv
$ cat result.csv
1,72,70.053,54,0,良
2, 0,,0,0,K
3,87,86.096,35,0,優
4,86,85.027,56,0,優
5,57,56.150,30,0,※
6,69,68.984,45,0,可
... 途中省略
149,94,93.583,54,0,秀
150,78,76.471,58,0,良
151, 0,,0,0,K
152,61,60.963,38,0,可
Avg: 64.539 (78.800)
Max: 96.000 (96.000)
Min: 0.000 (61.000)
秀:   11
優:   43
良:   38
可:   18
不可: 0
K:    20
※:   22

この実行例では,小テストのファイルを指定せずに成績を算出し,結果をresult.csv に出力するよう指定しています. もちろん,-outputオプションが指定されなければ, これまで通り標準出力に出力されます.

小テストが指定されていないため,出力の小テストの列はすべて0になっています. また,最終成績が60点以下であれば,グレードが※になっています.

5-C. ヒント

オプションの解析

オプションの解析では,オプションの指定方法が間違っているケースは考える必要はありません. オプションの内容を記録するためにArguments型を用意しましょう. Arguments型にはフィールドとして,オプションの内容を保持する変数を宣言してください. そして,Arguments型に次のようなparseを用意してください.

void parse(String[] args){
    for(Integer i = 0; i < args.length; i++){
        if(!args[i].startsWith("--")){
            arguments.add(args[i]);
        }
        else {
            i = parseOption(args, i);
        }
    }
}
Integer parseOption(String[] args, Integer i) {
    if(Objects.equals(args[i], "--dest")){
        i++;
        this.dest = args[i];
    }
    ...
    return i;
}

5-D. 評価項目

ステップ6

6-A.

次の統計情報と,最終成績の順位を算出してください. なお,出力順は最終成績順(-score),もしくはID順(-id)のいずれかをオプションで指定できるようにしてください. 両方のオプション(-score-id)が指定された場合は,ID順で出力してください.

ファイル名は,GradeChecker6.javaとしてください. なお,入力ファイルが変更され,行数が増減した場合でも適切に処理が行えるようにしてください.

6-C. ヒント

6-D. 評価項目