だいぶ古い記事ですが、CodeZineの過去の連載で
「脱 超初心者 Javaアルゴリズム問題集」というものをみつけました。
https://codezine.jp/article/corner/58
記事によると、「プログラム経験が3ヶ月もあれば十分解くことができるでしょう。」
という難易度らしいので、今の自分にはちょうどよいと思いました。
4問しか記事が見つけられませんでしたが、基礎を復習する意味で時間も意識して実施しています。
以下、問題文を引用させていただいてます。
正答例は記事で御覧ください。
脱 超初心者 Javaアルゴリズム問題集
https://codezine.jp/article/corner/58
第1回 条件分岐と永久ループ
標準入力された値があればそのまま表示、値がなければエラーメッセージを表示するプログラムを作成してください。なお、「EXIT」が入力されるまで、処理を繰り返し続けるものとします。
所要時間目安 A:30分 B:60分 C:120分(A:(開発歴)2年以上、B:1年程度、C:3ヶ月程度を目安)
コマンドラインに入力を待ち受けるための「>」を表示する。
「EXIT」が入力された時点でプログラムを終了する。それ以外が入力された場合は「未入力です」と表示して、再び入力待ち受け状態にする。
キーワード
if文の使用法を習得する。
while()/for(;;)による永久ループの使用法を習得する。
ポイント
標準入力からの入力を受け取るストリームはSystemクラスのフィールドinよりInputStreamクラスのインスタンスとして取得できる。
永久ループは次のようにすることによって表すことができる。
public static void main(String[] args) {
question1();
}
public static void question1() throws IOException {
System.out.print(">");
InputStreamReader writeConsole = new InputStreamReader(System.in);
BufferedReader buffer = new BufferedReader(writeConsole);
String writeString = buffer.readLine();
while (true) {
if (writeString.equals("")) {
System.out.println("未入力です");
} else {
System.out.println(writeString);
}
System.out.print(">");
writeString = buffer.readLine();
if (writeString.equals("EXIT")) {
System.exit(0);
}
}
}
永久ループの手法、InputStreamReaderを使った入力を知られて勉強になった。
第2回 条件分岐(複合条件)
標準入力された月、日が、今日であるかどうかを判定するプログラムを作成してください。
所要時間目安 A:30分 B:60分 C:120分(A:(開発歴)2年以上、B:1年程度、C:3ヶ月程度を目安)
コマンドラインに「今日は何月何日でしょう?」のメッセージを表示する。
それぞれ、「何月?==> 」「何日? ==> 」を表示して入力を受け取る。
入力された月日が今日であれば「正解!!」、間違っていれば「間違っています」と表示する。
キーワード
if文における複合条件の使用方法を習得する。
ポイント
日付の取得は、Calendarクラスを用いて行う。通常のクラスのようにコンストラクタをnewせずgetInstance()メソッドを呼び出してインスタンスを取得する。
標準入力は、Int型で受け取る。
if文は1度しか使用しない。
public static void main(String[] args) {
question2();
}
public static void question2() throws IOException {
System.out.println("今日は何月何日でしょう?");
int rightNowMonth = Calendar.getInstance().get(Calendar.MONTH) + 1;
int rightNowDate = Calendar.getInstance().get(Calendar.DATE);
BufferedReader buffer1 = new BufferedReader(new InputStreamReader(System.in));
System.out.print("何月?==>");
int writeMonth = Integer.parseInt(buffer1.readLine());
System.out.print("何日?==>");
BufferedReader buffer2 = new BufferedReader(new InputStreamReader(System.in));
int writeDate = Integer.parseInt(buffer2.readLine());
if (rightNowMonth == writeMonth && rightNowDate == writeDate) {
System.out.println("正解!!");
} else {
System.out.println("間違っています");
}
}
日付の扱いについての理解が深まった。
第3回 ループ
標準入力から、n個の年齢を受け取り、その平均年齢を算出するプログラムを作成してください。年齢はコマンドライン引数から取得するものとします。
所要時間目安 A:20分 B:40分 C:90分(A:(開発歴)2年以上、B:1年程度、C:3ヶ月程度を目安)
年齢は、コマンドライン引数から取得する。
コマンドライン引数が指定されていない場合は「引数に年齢を指定してください」のメッセージを表示する。
キーワード
for文を使い、n個のループ処理を理解する。
入力チェックを理解する。
ポイント
コマンドライン引数はmain()メソッドにStringの配列型として引き渡される。
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("引数に年齢を指定してください");
} else {
int sumAge = 0;
for (String age : args) {
sumAge += Integer.parseInt(age);
}
int averageAge = sumAge / args.length;
System.out.println("平均年齢は " + averageAge + " 歳です");
}
}
コマンドライン引数を扱うことが少なかったので、良い経験になった。
第4回 多重ループと二次元配列
掛け算九九表を出力するプログラムを作成してください。
所要時間目安 A:30分 B:50分 C:100分(開発歴)2年以上、B:1年程度、C:3ヶ月程度を目安)
二次元配列を作成して、九九データの代入を行い、その後の表示は分けて作成する。
ヘッダー、フッタ及び、列ヘッダー(段の表示)は、省いても構いません。
キーワード
for文を使った多重ループ処理を理解する。
二次元配列への代入、参照を理解する。
ポイント
数字を桁をそろえて出力するにはDecimalFormatクラスを使用する。0詰め2桁で出力するにはnewするときにコンストラクタに"00"を渡す。
public static void main(String[] args) {
System.out.println("+--------- かけ算九九表 --------+");
System.out.println("| 1 2 3 4 5 6 7 8 9 |");
System.out.println("| +----------------------------|");
int h = 1;
for (int[] list : question4()) {
// List<Integer>を利用する場合は以下
// for (List<Integer> list : question4_2()) {
System.out.print("| " + h++ + "|");
for (int value : list) {
if (value < 10) {
System.out.print(" 0" + value);
} else {
System.out.print(" " + value);
}
}
System.out.print(" |\n");
}
System.out.println("+--+----------------------------+");
}
//配列を使用
public static int[][] question4() {
int[][] list = new int[9][9];
for (int outer = 0; outer < 9; outer++) {
int[] value = new int[9];
for (int inner = 0; inner < 9; inner++) {
value[inner] = (outer + 1) * (inner + 1);
}
list[outer] = value;
}
return list;
}
//Listを使用
public static List<List<Integer>> question4_2() {
List<List<Integer>> list = new ArrayList<List<Integer>>();
for (int outer = 1; outer <= 9; outer++) {
List<Integer> value = new ArrayList<Integer>();
for (int inner = 1; inner <= 9; inner++) {
value.add(outer * inner);
}
list.add(value);
}
return list;
}
出力結果の見た目までこだわって実装したので楽しかった。
すべての問題を1問あたり1時間以内に解答でき、楽しめました。
4問目の2次元配列の問題は、Listと配列両方の実装方法を解答しています。
それぞれの違いは、要素数が固定か否かくらいしか理解してませんでしたが、改めて調べると、データへのアクセス方法が異なるため、処理速度に違いがあるらしいことがわかりました。
要素へのアクセス | 要素の追加 | |
---|---|---|
配列 | 高速 | 低速 |
List | 低速 | 高速 |