2017-01-12 第14回目 最終課題
本日のテーマ
- 概要
- 最終課題の各ステップ
概要
目標
- 簡易版の最終成績を算出してください。
- 簡易版の最終成績は、定期試験の点数です。
- その点数を元に、秀、優、良、可、不可、K(未受験)のグレードを判定してください。
- IDと最終成績(点数)とグレードをコンマ区切りで出力してください。
- 1行に1名の学生の成績を出力してください。
- 最終成績を出力してください.
- 最終成績の算出方法は、定期試験が60%、課題が35%、小テストの受験率が5% です。
- 小数点以下は切り捨ててください.
- その点数を元に、秀、優、良、可、不可、K(未受験)のグレードを判定してください。
- IDと最終成績(点数)とグレードをコンマ区切りで出力してください。
- 1行に1名の学生の成績を出力してください。
- 全体の統計情報を算出してください.
- 最終成績全体の平均点,最高点,最低点を算出してください.
- 各グレード(秀、優、良、可、不可、K)に属している人数を算出してください。
- 上記の統計情報を出力してください。
- 最終成績の分布を算出してください.
- 2までの情報(各人の最終成績とグレード)を出力してください.
- 以下の特別ルールを適用して,最終成績を算出してください.
- 定期試験の素点が80点以上であれば、最終成績をその点数にする。
- ただし、前に述べた算出方法で出した点数の方が高得点であれば、その点数を最終成績とします。
- 小数点以下は切り捨ててください.
- ここで得られた点数を元に、秀、優、良、可、不可、K(未受験)、 ※(出席に数不足)のグレードを判定してください。
- ※(出席日数不足)は、点数が60点未満かつ、小テスト受験回数が7日以下の学生に対してつけられます。
- IDと最終成績(点数)とグレードをコンマ区切りで出力してください。1行に1名の学生の成績を出力してください。
- 出力形式は3と同じです.グレードの算出方法が異なりますので,統計情報も異なってきます.
- オプション解析を行ってください.
- 成績ファイルを
-record
オプションで受け取ってください。 - 出席ファイルを
-attendance
オプションで受け取ってください。 - 小テストファイルを
-miniexam
オプションで受け取ってください。 - 出力先を
-output
オプションで受け取ってください。 - それぞれ、指定されなければ、その点数は0として扱い、上記2, 3, 4の処理を行うようにしてください。
- 成績ファイルを
- その他の統計情報を算出してください.
- 成績(定期試験、最終成績)の順位を算出してください。
- 単位取得率を算出してください。
- 秀、優、良、可、不可、K、※の割合を算出してください。
- 秀、優、良、可の単位取得者における割合を算出してください。
この課題に必要な内容
- クラス定義の基本形
- 参照の一致性と値の一致性
- 文字列から
Integer
型への変換 - コマンドライン引数
- 文字列から
Double
型への変換 - 配列と
List
- 独自の型を作成する.
- 例外機構
- ファイルを扱う型
- 典型的なファイルからのデータの読み込み方法
- 典型的なファイルへのデータの書き込み方法
Map
- 文字列を特定の文字で区切る(
split
)
課題の進め方
この課題は大きく6つに分けられます.
それぞれの課題で,GradeChecker1.java
〜GradeChecker6.java
を作成します.
以下のことを念頭に課題を進めてください.
- 1. 簡易版の最終成績を算出してください。 から順に取り組んでください.
- 1. 簡易版の最終成績を算出してください。 でできた内容を踏まえて2. 最終成績を出力してください.に取り組んでください.
- 3. 全体の統計情報を算出してください. 以降も同様に前の番号の内容をすべて盛り込んで,当該番号に取り組んでください.
- プログラムを作成するとき,一つ前のプログラムをコピーして始めるのも良いでしょう.
- ただし,その場合,
main
メソッドの内容を修正するのを忘れないようにしてください. main
メソッドで,異なる型をnew
するバグはなかなか気付きません.
- ただし,その場合,
- 3. 全体の統計情報を算出してください. までが必須です. それ以降はチャレンジ問題です.
- ただし,必須問題しか行っていない場合,試験で失敗すると単位取得が厳しくなります.
- 4. 以下の特別ルールを適用して,最終成績を算出してください.までを完成させていれば 単位取得も現実的になってきます.
なお,春学期の最終課題と似ていますが,細かな部分の仕様は異なります. 春学期に作成したプログラムをそのまま提出した場合は低い点数になりますので, しっかりと問題文を読み,プログラムを作成してください.
課題の提出方法
この課題は大きく6つに分けられます.
それぞれの課題で,GradeChecker1.java
〜GradeChecker6.java
を作成します.
また,指定はしていませんが,独自の型を作成する必要もあるでしょう.
それら全てのソースファイルをzip圧縮し,zipファイルを提出してください.
- 各ステップに必要なファイルを1つのディレクトリにまとめてください.
- ディレクトリ名は自分の学生証番号としてください.
- 自分の学生証番号のディレクトリを zip で圧縮してください.
- 自分の学生証番号が
111111
の場合,展開すると次のようになっているようにしてください.-
$ ls 111111.zip $ unzip 111111.zip $ ls 111111.zip 111111 $ tree 111111 111111 ... // 必要なファイル ├── GradeChecker1.java ├── GradeChecker2.java ... // 必要なファイル └── GradeChecker6.java
-
- 提出期限は,2017年2月3日(金) 24:00です.
- 提出先はMoodleの【〆切 2017/2/3 24:00】最終課題です.
- 次のチェックリストを提出前に確認してください.
- 空のディレクトリを作成し,その中に必要なソースファイルをすべて入れた.
- その状態でコンパイルに成功した.
- すべてのソースファイルにコメントとして,自分の学生証番号,名前が書かれている.
課題のデータ
課題のデータは次からダウンロードしてください. なお,評価には,以下のデータとは異なるデータを使います. データの形式は同じですが,記載されているデータは異なります. そのため,しっかりとデータを読み,適切な分析を行うようにしてください. なお,多少(小数点以下第4位程度)の計算誤差は許容されます.
1. 簡易版の最終成績を算出してください.
1-A. 問題説明
プログラムの実行時に,引数に試験成績のcsvファイルが渡されます. csvファイルは,IDと点数が記載されています. その点数を読み,秀,優,良,可,不可,K(未受験)のグレードを判定してください. IDは番号順に並んでいますが,番号が飛んでいる場合があります. その場合は,飛んだ番号は未受験であるため,0点,Kと出力してください.
点数が60点未満が不可,60以上70点未満が可,70点以上80点未満が良,80点以上90点未満が優, 90点以上が秀です. K(未受験)はexam.csvに掲載されていません. IDが飛んだ時,その学生のグレードをKにしてください.
ファイル名は,GradeChecker1.java
としてください.
なお,入力ファイルの行数が増減した場合でも適切に処理が行えるようにしてください.
1-B. 実行例
出力例は以下の通りです.IDの昇順になるように「ID, 最終成績,グレード」をコンマ区切りで出力してください.
なお,以下からもわかるように,exam.csv
には,ID 5が抜けています.
これは,5番目の学生は未受験であることを表しています.
そのため,出力では5番目の学生の成績は0点で,グレードがKになっています.
$ cat exam.csv
1,22.2
2,69.6
3,42.6
4,59
6,61
...以下略
$ java GradeChecker1 exam.csv
1,22.200,不可
2,69.600,可
3,42.600,不可
4,59.000,不可
5,0.000,K
6,61.000,可
...以下略
1-C. 参考資料
- 参照の一致性と値の一致性
- 文字列から
Integer
型への変換 - 文字列から
Double
型への変換 - 文字列を特定の文字で区切る(
split
) - IDの抜けについて
- IDが連続して抜けていた場合の処理も考えてみましょう。 次の2通りの考え方があります。
Map
のキーにID,バリューに点数を入れることを考えます.- ファイルを全部読み,IDと点数を
Map
に格納します. - その際,最大値を覚えておきます.
- その後、1から最大値まで順に
Map
から点数を取得すると良いでしょう. - 点数が
Map
に入っていなければ,そのIDは抜けている事になります.
- ファイルを全部読み,IDと点数を
- 現在の行番号を数える変数を用意します.
- ファイルを1行ずつ読み,行番号とIDを比較します(値の一致性を参照).
- 一致しなければ,行番号とIDが一致するまでグレードがKの学生が続くことを意味します.
- IDが連続して抜けていた場合の処理も考えてみましょう。 次の2通りの考え方があります。
2. 最終成績を出力してください.
2-A. 問題説明
プログラムの実行時に,引数に試験成績(exam.csv
),課題成績(assignments.csv
),小テストの成績(miniexam.csv
)の3つのcsvファイルが渡されます.
それらの点数を読み,秀,優,良,可,不可,K(未受験)のグレードを判定してください. 最終成績の算出方法は,定期試験が60%,課題が35%,小テストの受験率が5%です. 小数点以下は切り捨ててください.
ファイル名は,GradeChecker2.java
としてください.
なお,入力ファイルの行数が増減した場合でも適切に処理が行えるようにしてください.
それぞれのcsvファイルの内容は次の通りです.
2-A-1. 試験成績ファイル(exam.csv)
試験成績のcsvファイルでは,IDは番号順に並んでいますが,番号が飛んでいる場合があります. 番号が抜けている学生試験を受けていないことを表すため,0点,Kと出力してください.
$ cat exam.csv
1,22.2
2,69.6
3,42.6
4,59
6,61
... 以下略
2-A-2. 課題成績ファイル(assignments.csv)
左の各行は,「ID,課題1,課題2,課題3,課題4,課題5,課題6」の順に各課題の成績が記載されています. 点数が記載されていない部分は未提出です. 課題1〜6までの点数を合計した点数がその人の課題点であり,最高点は60点です. IDは昇順に並んでおり,途中に抜けている番号はありません.
$ cat assignments.csv
1,,8,8,,,
2,10,10,10,10,10,10
3,,,,,,
4,10,10,10,0,8,10
5,,,,,,
6,10,8,8,8,8,8
... 以下略
2-A-3. 小テストの成績ファイル(miniexam.csv)
各行は,IDから始まり,14回分の小テストの点数が記載されています. 点数の記載がない部分は小テストを未受験であり,0は受験したものの点数が取れなかったことを表しています. また,IDは昇順に並んでいますが,途中飛んでいる場合もあります.
この小テストでは,受験率を算出してください. すなわち,書かれている点数は重要ではなく,点数が書かれているか否かが重要です. 受験回数を14で割り,受験率を算出してください.その受験率を小テストの点数とします.
$ cat miniexam.csv
1,,,,,,4,5,,,4,0,,1,2
2,8,6,10,6,6,8,10,5,9,5,0,9,6,7
3,5,5,3,0,0,1,,,2,2,0,3,1,2
4,4,6,5,4,3,10,9,8,4,4,0,9,5,6
5,5,0,,,,,,,,,,,,
6,2,2,1,0,0,0,4,2,0,0,0,1,1,1
7,,0,,,7,,,,,,,,,1
8,5,6,2,5,5,7,4,3,1,4,0,3,3,4
... 以下略
2-A-4. 成績の算出
プログラムには,コマンドライン引数で exam.csv
,assignments.csv
,miniexam.csv
の順にファイルが指定されます.
IDが$n$の学生の最終成績$s$を次の式で算出してください.$e$が定期試験の点数,$a$が課題の合計点,$t$が小テストの受験率(0.0〜1.0)とします.
\[ s = \frac{60}{100}e+\frac{35}{60}a + 5t \]
最終成績$s$は小数点以下を切り捨ててください.切り捨ては,下のように,Math.floor
を利用してください.
また,グレード算出の時にKか不可かを判定するため, 定期試験を受験したか否かのフラグを保持しておくと良いでしょう.
Double givenValue = 18.96;
Double floorValue = Math.floor(givenValue); // floorValueには18.0が代入される.
2-B. 実行例
出力例を下に示します. IDの昇順になるように出力してください. 各行は,ID,最終成績,試験の点数,課題の合計点,小テストの受験回数,グレードをコンマ区切りで出力してください. 以下のID 5の学生のように,試験を受けていない場合は,Kと判断してください.
$ java GradeChecker2 exam.csv assignments.csv miniexam.csv
1,24,22.200,16,6,不可
2,81,69.600,60,14,優
3,29,42.600,0,12,不可
4,68,59.000,48,14,可
5, 0,,0,2,K
6,70,61.000,50,14,良
... 以下略
2-C. 参考資料
- 1人の学生の成績を管理するのに型を作成すると良いでしょう.
Student
という型を用意し,ID,試験の成績,課題の合計点,小テストの受験率,試験を受けたか否かのフラグを変数として持つと良いでしょう.- 独自の型を作成する.
3. 全体の統計情報を算出してください.
3-A. 問題説明
2. 最終成績を出力して下さい.までに出力した内容の統計情報を出力しましょう. 統計情報とは,最終成績の平均,最高,最低点を指します. ただし,K,不可の学生を含めた場合と含めない両方の場合での点数を算出しましょう.
次に,各グレードに何人が属しているかを数えて出力してください.
ファイル名は,GradeChecker3.java
としてください.
なお,入力ファイルの行数が増減した場合でも適切に処理が行えるようにしてください.
3-B. 実行例
最初に統計情報を出力してください. 統計情報は,最終成績の平均,最大,最小です. カッコ内の情報は,単位取得者(最終成績が60点以上)のみを対象に求めた平均,最大,最小です. それらを出力し終えたら,今度は,各グレードに属する人数を出力してください.
以上の統計情報を出力し終えたら,IDの昇順になるように出力してください. 各行は,ID,最終成績,試験の点数,課題の合計点,小テストの受験回数,グレードをコンマ区切りで出力してください.
$ java GradeChecker3 exam.csv assignments.csv miniexam.csv
Avg: 50.904 (74.145)
Max: 91.000 (91.000)
Min: 0.000 (60.000)
秀: 2
優: 19
良: 23
可: 25
不可: 61
K: 26
1,24,22.200,16,6,不可
2,81,69.600,60,14,優
3,29,42.600,0,12,不可
4,68,59.000,48,14,可
5, 0,,0,2,K
6,70,61.000,50,14,良
7,48,78.800,0,3,不可
4. 以下の特別ルールを適用して,最終成績を算出してください.
4-A. 問題説明
この講義の成績算出には,特別ルールが適用されます. それは,定期試験の素点が80点以上であれば,最終成績をその点数とする,というものです. ただし,2. 最終成績を出力して下さい.で算出した成績の方が上であれば,その成績を最終成績とします.
また,グレードに※を追加してください. ※ は出席日数不足を表しています. 条件は,定期試験を受験し,最終成績が60点未満かつ,小テストの受験回数が7回以下の場合に,グレードを※とします. 定期試験を受験していない学生のグレードはKとしてください.
この特別ルールを適用したプログラムを作成してください.
ファイル名は,GradeChecker4.java
とします.
なお,入力ファイルの行数が増減した場合でも適切に処理が行えるようにしてください.
4-B. 実行例
3. 全体の統計情報を算出してください。までは,IDが21の学生の最終成績は84でした. ここでの特別ルールを適用すると,テストの点数が 87.400 ですので,この点数を切り捨て, 87点が最終成績となっています. また,グレードが一つ追加されたため,統計情報にも変更が加わっています.
$ java GradeChecker4 exam.csv assignments.csv miniexam.csv
Avg: 52.308 (75.973)
Max: 98.000 (98.000)
Min: 0.000 (60.000)
秀: 4
優: 28
良: 18
可: 23
不可: 35
K: 26
※: 22
1,24,22.200,16,6,※
2,81,69.600,60,14,優
3,29,42.600,0,12,不可
4,68,59.000,48,14,可
5, 0,,0,2,K
6,70,61.000,50,14,良
7,48,78.800,0,3,※
...途中省略
21,87,87.400,48,12,優
... 以下省略
5. オプション解析を行ってください.
5-A. 問題説明
今までは,コマンドライン引数でexam.csv
,assignments.csv
,miniexam.csv
の順でファイルが渡されていました.
これを自由な順序で指定するようにプログラムを変更します.
しかし,本当に自由な順序で渡されるとどのファイルに何が書かれているのかがわかりませんので,コマンドライン引数でファイルを指定しましょう.
- 成績のファイルを
-record
オプションで受け取ってください. - 課題のファイルを
-assignments
オプションで受け取ってください. - 小テストのファイルを
-miniexam
オプションで受け取ってください. - 出力先を
-output
オプションで受け取ってください.
ファイルが指定されない場合は,その成績は0点として最終成績を算出してください.
最終成績の計算式は変更する必要はありません.
また,-output
オプションが指定された場合は,そのファイルに結果を出力してください.
指定されなかった場合は,標準出力(System.out
)に出力してください.
ファイル名は,GradeChecker5.java
としてください.
なお,入力ファイルの行数が増減した場合でも適切に処理が行えるようにしてください.
5-B. 実行例
コマンド入力の途中で改行するには,左図のように,\
の後ろで改行してください.改行がエスケープされます.
左の実行例では,小テストのファイルを指定せずに成績を算出し,結果をresult.csv
に出力するよう指定しています.
もちろん,-output
オプションが指定されなければ, 今まで通り標準出力に出力されます.
小テストが指定されていないため,出力の小テストの列はすべて0になっています. そのため,最終成績が60点以下であれば,グレードが全て※になっています.
$ java GradeChecker5 -record exam.csv \
-assignments assignments.csv -output result.csv
$ cat result.csv
Avg: 49.647 (74.800)
Max: 98.000 (98.000)
Min: 0.000 (60.000)
秀: 3
優: 24
良: 17
可: 21
不可: 0
K: 26
※: 65
1,22,22.200,16,0,※
2,76,69.600,60,0,良
3,25,42.600,0,0,※
4,63,59.000,48,0,可
5, 0,,0,0,K
6,65,61.000,50,0,可
7,47,78.800,0,0,※
8,60,74.400,28,0,可
... 以下略
6. その他の統計情報を算出してください.
6-A. 問題説明
次の統計情報と, 最終成績の順位を算出してください.
ファイル名は,GradeChecker6.java
としてください.
なお,入力ファイルの行数が増減した場合でも適切に処理が行えるようにしてください.
- 単位取得率
- 各グレードの人数の全体に占める割合
- 秀,優,良,可の人数の単位取得者に占める割合
6-A-1. 単位取得率
単位取得者の人数を数え,全体の学生数で割ってください. これで単位取得率が算出できます.統計情報として百分率(パーセンテージ)で出力してください.
6-A-2. 各グレードの人数の全体に占める割合
秀,優,良,可,不可,K,※の6種類のグレードが算出されています. 各グレードに属する人数が,全体のうちどれくらいの割合であるのかを算出してください. グレードの人数と同じ行に百分率(パーセンテージ)で出力してください.
6-A-3. 秀,優,良,可の人数の単位取得者に占める割合
秀,優,良,可の4種類のグレードについては,各グレードに属する人数が, 単位取得者のうちどれくらいの割合を占めているのかを算出してください. グレードの人数と同じ行に百分率(パーセンテージ)で出力してください.
6-A-4. 最終成績の順位
最終成績でソートし,学生に順位をつけてください. 各学生の成績を出力するときに,順位を行の最後につけて出力してください. 同じ点数であったとしても,同じ順位である必要はありません. 学生の情報を表す型が用意されている時,次のプログラムでソートが行えます.
学生の情報を表す型がStudent
,最終成績が Student
型の変数score
であるとします.
下のプログラムを StudentComparator.java
として保存し,GradeChecker6.java
と同じ場所に保存してください.
下のプログラムが2つの成績を比べる比較器です.compare
が実際に比較するメソッドです.
今は,最終成績のみで比較していますが,その比較の前にグレードで比較すると
良いでしょう. s1 < s2
であれば負の値,s1 > s2
であれば正の値,s1 == s2
であれば0を返すと,
適切にソートしてくれます.
import java.util.Comparator;
public class StudentComparator
implements Comparator<Student>{
public int compare(Student s1, Student s2){
Double v1 = s1.score;
Double v2 = s2.score;
if(v1 < v2) return -1;
else if(v1 > v2) return 1;
return 0;
}
}
その後,すべての学生情報が入ったArrayList<Student>
を Collections
型
のsort
メソッドに渡してください.
そうすると,list
の順序がscore
の昇順に並び替えられています.
// listに学生の情報がすべて格納されている.
ArrayList<Student> list = // ...
// 先に作成した比較器.
Comparator<Student> comp = new StudentComparator();
// 比較器を元にソートを行う.
Collections.sort(list, comp);
ただし,学生の情報を保存する独自の型は適宜読み替えてください.
また,最終成績が代入されている変数もここでは score
ですが,自分自身で定義したものに置き換えてください.
なお,この場合,総合点のみでソートするため,Kと不可,※は順不同で出力されます.
グレードが秀,優,良,可,不可,K,※の順で並ぶようなプログラムにするにはどのようにすれば良いかを
考えてみましょう. StudentComparator
の compare
メソッドをどのように変更すれば
良いかを考えてみてください.
6-B. 実行例
各行に学生の成績が出力されます. 行のフォーマットは, 「ID,最終成績,試験の点数,課題の点数,小テストの受験回数,グレード,順位」です.
すべての学生の成績の出力後に,統計情報が出力されています. 最終成績の平均,最大値,最小値です. カッコ内の値は,単位取得者に限った時の最終成績の平均,最大値,最小値です.
次に単位取得率が出力されています.
最後に各グレードに属する人数とその割合が出力されています. 秀,優,良,可のカッコ内にある2つの数値は,全体におけるその人数の割合と単位取得者におけるその人数の割合です. 不可,K,※は,全体におけるその人数の割合が出力されています.
例えば,例の場合,全体の人数は156名で,単位取得者の人数は73名,秀の人数は4名です. そのため,単位取得率は46.795%($=\frac{73}{156}$)です. また,全体に占める秀の人数の割合は,2.564%($=\frac{4}{156}$), 単位取得者に占める秀の人数の割合は 5.479%($=\frac{4}{73}$)です.
$ java GradeChecker6 -miniexam miniexam.csv -record exam.csv -assignments assignments.csv
Avg: 52.308 (75.973)
Max: 98.000 (98.000)
Min: 0.000 (60.000)
単位取得率: 46.795%
秀: 4 (2.564%, 5.479%)
優: 28 (17.949%, 38.356%)
良: 18 (11.538%, 24.658%)
可: 23 (14.744%, 31.507%)
不可: 35 (22.436%)
K: 26 (16.667%)
※: 22 (14.103%)
1,24,22.200,16,6,※,124
2,81,69.600,60,14,優,27
3,29,42.600,0,12,不可,122
4,68,59.000,48,14,可,55
5, 0,,0,2,K,156
6,70,61.000,50,14,良,50
7,48,78.800,0,3,※,104
8,65,74.400,28,14,可,63
9,75,68.100,50,14,良,41
10,87,84.200,56,13,優,11
... 以下略