Java Silverに合格した話

ご無沙汰です。
ここ2か月位ブログの更新をしてなかった。
更新していなかった期間はポケモンやってたり、後述の勉強をしていたため、
更新できる余裕がなかった。 長々と話す必要もないので、本題、

JavaSilverに受験、そして合格へ・・・

タイトルにもある通り、本日2/23にJavaSilverを受けてきて合格という結果を頂きました。
ボーダーが65%に対し、84%という結果で僕は嬉しいです。
正直言うともっと取れてて欲しかった。
今回はJavaSilverの合格のため、実際どんなことをしていたかをつらつら書き残していこうと思います。
ちなみにJavaのバージョンは8。

使った参考書

株式会社インプレスが出してる「徹底攻略 JavaSE8Silver 問題集」(いわゆる黒本)のみ。
自分は読み物が滅茶苦茶嫌いで、なるべく字の少ないものか、問題集のみを買うように
しています。今回のJavaSilverはコードを読んで、適切なものを選ぶ問題形式なので、
参考書読んで覚えるよりも、実践的なことをした方が覚える気がしたので、問題集のみにしました。
この本についてですが、解説がわかりやすい。
問題のポイントを的確に説明していて、かつ詳しい。
あとからJavaSilver界隈ではこの本が人気と知ったが、納得するレベル。

勉強時間

勉強を始めたのが試験の3週間位前。1週間ごとにまとめると以下の通り。
- テスト3週間前:平日に2時間程度、休日はポケモンやってて0時間
- テスト2週間前:平日に1時間程度、休日は3~5時間程度
- テスト1週間前:平日に1時間程度、休日は5~6時間程度
上記の黒本は11章構成で、10~11章は模擬試験となっている。
大体平日に1章~2章ずつ進めて休日に10~11章の模擬試験を解く、ということを繰り返してる。

テストを受けた感想

勉強しすぎたかなと思います。
というのも、テストの内容が黒本とほぼ同じで、特に10~11章の模擬試験の問題がそのまま出たり、変数や代入する値だけ変えて内容が全く一緒の問題ばかりでした。
正直合格するだけなら、模擬試験が満点取れるくらいに勉強しておけば、問題なさそうです。全ての問題を解き終えるまでに1時間も掛からず、見直しも回答してるかどうかしか見ていないくらい合格したという確信を持てていた。

勉強したメリット・デメリット

メリット
- Javaの記法について、「こんな書き方があったのか」と知る機会になった
- 今までコンパイラに頼っていてちゃんと考えていなかったと反省できた
- Javaを書く時に覚えたことを気を付けるようになった
デメリット
- 時間を割きすぎたことにより、他のことができていなかった
- 問題の内容が特殊すぎて、実践ではあまり使うことができない
- これを覚えたからと言って、すぐにプログラムに組めるかというとそうでもない

これから受ける人へ

黒本は買った方がいいと思います。先ほども言いましたが、問題がそのまま出たりするので解いておけば、わからなくてもなんとなくでも答えが選べるようになります。
もちろん解説がわかりやすいので、解説を読むだけで十分勉強できると思います。
また、テストを受けると決めたら、真っ先に申し込みの準備はできるようにした方がいいと思います。申し込みや結果を見る方法が非常にわかりにくい。

朝9時スタートで非常に眠いので、今回はこの辺で。

Cloud9でpipが使えない

知り合いとの話の流れでPythonGUIを作ろうと思い、環境構築をする必要がないCloud9を
利用としたが、Pythonのpipが使えなくて詰まった。


何をしようとしたか

tkinterと呼ばれるPythonで簡単なGUIを作るライブラリがあり、それを使おうと思ったが
Cloud9上に存在しなかった。
仕方ないので、pip installを使って入れようとしたが、以下の表示が出た

You are using pip version 9.0.3, however version 19.3.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

要約するとpipのバージョンが低いので上げないとインストールできないとのこと
説明にある通りにアップグレードしようとすると、それ以降のpipコマンドが使用できなくなる


原因

始め、pipのあったフォルダは

$ which pip
/usr/bin/pip

となっていたが、以下の通りにアップグレードした後、whichコマンドで調べると

$ sudo pip install --upgrade pip
…略
Successfully installed pip-19.3.1
$ which pip
/usr/local/bin/pip

となっていた。
この状態になって以降、pipコマンドは何してもエラーを吐くので、初期化しました
もし初期化する場合は、コードのバックアップを取っておいた方がいい


さらなる追求

アップグレードする際に、フォルダが変わってしまい、pipが使えなくなるのは困るので
(そもそもpipを使おうと、アップグレードしたのに使えなくなるのは如何なものか)
他に原因はないのかと思い、Pythonとpipのバージョンを調べてみた。
すると、以下のような表示が出た。

$ python -V
python 3.6.8
$ pip -V
pip 9.0.3 from /usr/lib/python2.7/dist-packages (python 2.7)

聡明な皆様なら、もうお判りでしょう。
pipのバージョンを参照しているフォルダを見ると、
/usr/lib/python2.7/dist-packages (python 2.7)
というようになっている。

つまり、今使用しているPythoはPython3なのに対し、
pipはPython2を使用しようしている。
調べてみると、デフォルトの設定がPython2になっているらしい。


そして、解決へ・・・

以下のコマンドを打つ

$ sudo update-alternatives --config python

すると

There are 2 programs which provide 'python'.

  Selection    Command
-----------------------------------------------
*+ 1           /usr/bin/python2.7
   2           /usr/bin/python3.6

Enter to keep the current selection[+], or type selection number:

という表示が出る。
端的に説明すると、Pythonのバージョンを選ぶ画面。
今回はPython3を使用したいので、2と入力する。
これでPython3として使用できるようになる。
ただ、これだけだと実行できないことがあるので、以下のコマンドを入力する
(自分はこれ打った後、使用できるようになった)

$ hash -r

これらを行った後、pipのバージョンアップを行い、試しにnumpyをインストールしてみたが、エラーがなく普通に成功した。


終わりに

Cloud9を使って何かしらライブラリをインストールしようとして失敗した人が大勢いると思う。
今回の方法が解決の糸口になればいいなと。 その後僕は、以下のコマンドを打つまで、tkinterをインストールしようと1時間以上
費やしたことはまた別の話。

$ pip search tk

応用情報技術者試験に合格した話


私の点数…低すぎ…
というわけでギリギリですが、合格しました。
今回は試験についてとやってきたことを真面目に書いておこうかなと思います。
こういうの書く人って両方80点とか高得点取ってる人が多いので恥ずかしい


今回の試験について

令和になって最初の試験ですが、全体を通して難しいという印象でした。
というのも例年よりも新しいIT用語や最先端技術の問題が多く、過去問ばかりやっていると出てこない用語が見受けられた気がします。
特に午後ではプログラミングで「ニューラルネットワーク」が出たことが一番印象的でした。
問題を解く際に「時代は変わったのか~」とか思いながら解いたことを思い出します。
今後は最新技術を取り入れないと、高得点を狙うのは厳しくなるのではないかと思います。(お前が言うな)

もちろんですが、全ての問題が難しいというわけでもなく、午前は半分以上が過去問と、
今までより既出問題が多いという結果だったそうです。1
なので過去問をしっかり解いていれば、午前は合格している人の方が多いかなと思います。
午後については、先程話したプログラミングがニューラルネットワークと聞いて少々戸惑いますが、
問題文をしっかり読めば、解けるようになっていたり、
データベースも基本を押さえていれば、
そこまで難しくないと思いました。

試験終了後、「たぶん不合格かなー」って思いながら試験会場を出たので、落ち込んでいました。それぐらい今回の試験は難しいと思っており、今回合格できたのも点数配分がたまたま自分の良い方向に向かっていっただけかなと思っていますので、しっかり身に着けられるように、今後も勉学に取り組もうと思いました。


今までやってきたこと(午前・午後共通)

今回の試験に向けてやってきたことで、午前・午後共通することは大きく2つ。 - 参考書を読む - 過去問をとにかくやり続ける

1つ目の「参考書を読む」というのは、おそらく試験を受ける人は全員やっていることだと思います。最初はわからなくても1周はした方がいいです。どんなに理解して読んでなくても1周したということが自信に繋がるとも思いますし、一発で理解できる人間は応用情報なんて合格できると思うので。僕は全ての内容を理解できている・できていないに関わらず、ノートに書いてました。
1周したらもう読まなくていいのか、というわけではないです。分からない用語が出てきたら、都度参考書を使って調べるといいと思います。ネットで検索するというのも1つの手だと思いますが、なるべく参考書で調べると良いと思います。
理由はその用語に関連するワードを一緒に見ることになるから。調べたい用語の書いてあるページ周辺はその用語に関連した内容があるので、調べたついでにそのページ周辺の内容も見ておくと頭に入りやすいです。 人は1つことをバラバラに覚えるより関連性のあるものと一緒に覚えた方が忘れないので、個人的には良い方法だと思い、試験前日までやってました。
ネットの場合、用語を調べて終わりってことが多いのでオススメしませんが、参考書に載っていない最新技術などは調べた方がいいと思います。勉強の休憩中にITニュースを見るだけでも、だいぶ違うと思います。

2つめの「過去問をとにかくやり続ける」というのは、どうしても勉強というものを億劫と感じやらなくなると、試験ギリギリまで何もしないというケースに陥ります。
こうならないためにも、午前問題だけでもいいので過去問を毎日やり続けることで、習慣づけるということが大事だと思います。
僕は高校の時、塾講師に「勉強は歯磨きと同じ、毎日やらないと気持ち悪い、違和感を感じるくらいにやれ」と教わりました。僕は試験当日まで毎日午前問題80問、2週間に1回午後問題を解くというのを続けてきました。正直少ないと思いますが、習慣図けるには丁度良いと思いますし、実際のところは「時間あるから追加でもう80問」とかやっていました。
とにかく続けることに意味があると思います。


今までやってきたこと(午前)

午前の対策は「過去問を解く、解説読む」を繰り返していました。
よく利用してたサイトが以下の応用情報技術者試験ドットコム様の過去問道場です。

応用情報技術者過去問道場

こちらのサイトで、暇な時にずっとやってました。特に電車の中でスマホ1つでできる点が良いことと、解説が非常に分かりやすい点がいいと思います。
基本的にはこれだけを利用し、分からないことはメモを取って後でまとめて調べるだけでいいと思います。


今までやってきたこと(午後)

応用情報の合格で一番欠かせない午後の対策ですが、僕は「応用情報技術者 午後問題の重点対策 (重点対策シリーズ) 」という本(以下Amazonのページ)を使って勉強しました。

2020 応用情報技術者 午後問題の重点対策 (重点対策シリーズ)

この本は各分野の説明を今までの過去問を用いて幅広く対応できる問題集となっています。解説が丁寧なので、解説を熟読するだけでも非常に効果的だと思います。
ただし、各分野問題が過去問5回分しかないので、物足りないと思ったら、IPAのサイトや応用情報技術者試験ドットコム様に今までの過去問と解答があるので、そちらを使って問題を解くということをするといいと思います。
また午後は大問で分野が分かれており、11問中必須1問選択4問となっておりますので、どこを解くかは決めておいた方がいいと思います。他のサイトを見ると「解く問題は保険も兼ねて5~6問に決める」とありますが、僕は保険の1~2問に賭けるより4問に集中して勉強した方が効率的と思って、必須も合わせた5分野しか勉強していませんでした。
選択した問題は1番最初の画像にある通りで、開発系ばかり選択していましたが、これらが簡単というわけではなく、これが1番自分に合っていただけです。
まず11分野解いてみて、どれが自分に合っているか探すのがいいと思います。


終わりに

今回の試験の結果については、合格したことについては非常に嬉しく、やっと知識も付いてきたのかなと思いますが、やっぱりギリギリ合格ラインっていうのは、ラッキーなだけかな?とも思っています。また試験に合格したからといって、業務に活かすことができなければ、何の意味もないので、これからも応用情報の知識をベースにもっと勉強しようと思います。
また共に勉強をして下さった友人の方々、ご迷惑をお掛けした方々、本当にありがとうございました。


  1. 応用情報技術者試験ドットコム様 統計情報より

りすとせいせいについて

Pythonで0~99の値の入ったリストを作れ、となった時に以下のリスト1~3の記述の内、 どれが正しいか(以下のコードはPython3)

# リスト1
list1 = []
for i in range(N):
    list1.append(i)
    
# リスト2
list2 = []
for j in range(N):
    list2 += [j]

# リスト3
list3 = [i for i in range(N)]

答えはすべて正しい。それぞれ
リスト1はappendメソッドを用いている
リスト2はリストの結合を用いている
リスト3は内包的記述を用いている

と別々の方法を用いて作成している。もちろんこれ以外にも方法はある。
Pythonを学んで一番最初に使うのはリスト1の方法だと思う。
リスト1の方法は可読性があり、使いやすそうではあるが、
個人的にはリスト3の方法をオススメする。
一番の理由は速度が圧倒的に早いから

実際に以下のプログラムを実行して計測すると以下のようになる1

import time as t # 時間計測用のライブラリ

N = 100
# リスト1
Start = t.clock()
list1 = []
for i in range(N):
    list1.append(i)
Finish = t.clock()
print("list1 create time = ",Finish - Start)

# リスト2
Start = t.clock()
list2 = []
for j in range(N):
    list2 += [j]
Finish = t.clock()
print("list2 create time = ",Finish - Start)

# リスト3
Start = t.clock()
list3 = [i for i in range(N)]
Finish = t.clock()
print("list3 create time = ",Finish - Start)

結果

>>python listCreateTime.py
list1 create time =  1.2999999999999123e-05
list2 create time =  1.1000000000000593e-05
list3 create time =  4.9999999999980616e-06
>>

リスト1とリスト2は実行によって多少誤差が生じ、速さが逆転することもあるが
リスト3は圧倒的に違う。
理由としては
リスト1は追加する度にメソッドの呼び出しがあるため
リスト2は追加する度に演算が発生するため

と考えられる。

今回の場合は0~99といった小さいデータだったため、問題ないが
これが深層学習で取り扱うような大きなデータの場合は、
この差は大きい。
学習にも時間が掛かるのにデータを用意するのにも時間のは良くない。
なのでなるべくはリスト3の方法を扱えるようにした方がいい。

次回はリスト内包的記述について書こう。


  1. 今回は環境設定が面倒だったので、こちらのpaiza.ioを利用した。https://paiza.io/projects

いふねーむいこーるいこーる"めいん"

Pythonのプログラムでよく見ることになる以下のコード

if __name__ == "__main__":

呪文のようにとりあえず書いているけど、実際どういう意味があるのか。
忘れないようにメモ書き程度で残す。
※コードはPython3

全体

一般的には以下のように書いてある

def test():
    print("これはテスト")
    
if __name__ == "__main__":
    test():

このtest1.pyを実行すると

>>python test1.py
これはテスト
>>

これは以下のコードと同じ

def test():
    print("これはテスト")
test():

「同じならif __name__ == "__main__":って必要ないやん」
ってなるけど、普通に意味はある。
それはtest1.pyを外部からインポートする場合、test()実行させないため
どういうことか、1つ1つ細かく見ていく

__name__とは

__name__というのは特殊属性1の1つで
どこのプログラムから呼び出されているのかがわかるもの。
ファイル指定で呼び出した場合は、mainが入る

例えば

def print_test():
    print(__name__)

if __name__ == "__main__":
    print("これはメイン")
    print_test()

というプログラムを以下のようにmain.pyでインポートする

import name_test

name_test.print_test()

この状態でそれぞれ実行すると

>>python main
name_test
>>python name_test
これはメイン
__main__

というようになる。
main.pyではインポート先からprint_test()を呼び出しているので、
インポートしているモジュール名name_testがnameに入る。
そのため、name_test.pyのif __name__ == "__main__":はFalseになる。

一方name_test.pyを直接実行した場合、ファイルを指定して呼び出しているので、
nameにはmainが入る。
そのため、name_test.pyのif __name__ == "__main__":はTrueになる。

if __name__ == "__main__":の必要性

もしこのif文がない、以下のようなコードをインポートする。

def print_test():
    print(__name__)

print_test()
import name_test2

print("main.py")

このmain.pyを実行すると

>>python main
name_test2
main.py
>>

実行してもいないのに、name_testが表示される。
これはインポートする際に、name_test2.pyのprint_test()を実行してしまうため。
つまり「if __name__ == "__main__":」は
関数や関数の外で実行されるものを外部参照際に実行させないようにするために使われる!

応用方法

結局「if __name__ == "__main__":」はどうゆう時に使用するかというと
モジュール作った際、テストする時に使用する」というのが一般的。
テストする時はif文にテスト用のプログラムを書いて、そのファイルを直接実行する。
本番では、インポートするプログラムを実行する。

実際に例を出すと入力した数値を2倍にして返すモジュールを作る。
ただモジュールとして利用する前にテストする場合、以下のように書く。

def baipush(int i):
    i *= 2
    return i

if __name__ == "__main__":
    print("これはテスト")
    print(baipush(3))

このプログラムを実行すると

>>python nibai.py
これはテスト
6
>>

これにより、正しく実装されているのが確認できたので、
あとはインポートするメインのプログラムで実行すればいい。
このテストはif文の中に書いてあるので、前述で話した通り、
メインのプログラムで実行した場合は、実行されない。

まとめ

  • 記述例は以下の通り
def test():
    print("これはテスト")
    
if __name__ == "__main__":
    test():
  • nameはどこのプログラムから呼び出されているか知るための特殊属性
  • 「if __name__ == "__main__":」は外部参照時に関数の実行を避けるために使用される
  • 応用方法は主にモジュールのテストするため

  1. xxxという記法で書かれた変数。有名なものだと_init_