Java Silver SE 17 に合格しました

はじめに

Java SE 17 Programmer I (1Z0-825-JPN) 試験に合格し、Oracle Certified Java Programmer, Silver SE 17 認定資格を取得しました。

eCertificate


試験結果

73% と結構ギリギリでした。。。


動機

再就職活動を進めていたところ、Java の求人が多かったため取得を決めました。

ちょっと前までは「資格なんていらねえ! 腕っぷしで証明する!」なんて意気込んでいましたが、
年も行ってるのにスキルなしキャリアなしの人間をトラストするには資格くらいしかないなと最近思うようになりました。

Spring などのフレームワークの知識はないので即戦力にはなりませんが、
ないよりかはマシか、と思っています。

あと友人が(随分昔に)Java Gold を取得していることも刺激になっていますね。

勉強の進め方

参考書(白本)と問題集(黒本)を買いました。
学生時代に Java は競技プログラミング分野、または趣味で使っていたので余裕だろうと思い黒本を解き、分からないところを適宜参考書を参照する、Gemini に聞く、API doc など Web 検索して調べる、という方策で行きました。

横になりながらスマホでできる問題集も解きたいなあと思い、以下の Web サイトを利用していましたが、
問題範囲が異なっていたため 1 回限りでやめました。

正確な問題範囲から出題してもらうために、Gemini Notebook の AI Studio でクイズ、フラッシュカードを作ってもらいました。
ソースに用いるテキストは Gemini に作ってもらいました。

ソースに用いたテキスト:

【Java SE 17 Programmer I (1Z0-825-JPN) 公式出題範囲】

1. Java の概要と簡単なJavaプログラムの作成
- mainメソッドを持つ実行可能なJavaプログラムの作成
- コマンドラインでのJavaプログラムのコンパイルと実行
- パッケージの宣言とimport文の使用

2. Javaの基本データ型と文字列の操作
- 変数の宣言および初期化と変数のスコープ
- ローカル変数型推論 (var) の使用
- 文字列の作成と操作 (String, StringBuilder, テキスト・ブロック)
- 配列 (一次元配列、多次元配列) の宣言、インスタンス化、初期化および使用
- ArrayList の作成と操作

3. 演算子と制御構造
- 演算子の使用 (代入、算術、論理、三項演算子など)
- 条件文 (if, if-else, switch文, switch式)
- ループ文 (for, 拡張for, while, do-while, break, continue)

4. クラスの定義とインスタンスの使用
- Javaクラスの定義とインスタンス化、オブジェクトのライフサイクル
- メソッドとコンストラクタの作成
- メソッドのオーバーロード
- static変数とstaticメソッドの使用
- アクセス修飾子 (public, protected, private, package-private)
- instanceof のパターン・マッチング

5. 継承とインタフェースの使用
- スーパークラスとサブクラスの作成と使用 (継承)
- 抽象クラスの作成と継承
- メソッドのオーバーライド
- 参照型のキャストとポリモーフィックなメソッド呼び出し
- final クラスおよび final メンバーの作成と使用
- インタフェースの作成と実装 (デフォルト・メソッド、プライベート・メソッド含む)

6. 例外処理
- 例外処理の仕組みとチェック例外、非チェック例外、エラーの違い
- try-catch 文による例外処理
- try-with-resources 文による例外処理
- カスタム例外の作成と使用

※注意: Java SE 17 Silver の範囲には「モジュールシステム (module-info.java)」「Lambda式」「Stream API」「java.util.function」は含めないでください。

黒本は最初ボロボロでした。。。自信はあったのですが思ったより知識がなかったり処理を終えてなかったりで、落とす問題が多かったです。
また、sealed, record って何? ってなりました。

黒本は2周弱やりました。白本は開いても知ってるわい! という内容が多く、目が滑るばかりでした。

模擬試験をやった結果です。65%(60問中39問正答)が合格ラインです。

  • 黒本模擬試験① - 7/15
    • 39/60 = 65%
  • 黒本模擬試験② - 7/17
    • 44/60 = 73%
  • 黒本模擬試験① - 7/26
    • 46/60 = 76%
  • 白本模擬試験① - 7/27
    • 26/34 = 76%

試験

試験前

何とか忘れ物なく受付できました。ここが一番怖かった。。。
会場で英検と他の試験、みたいな感じで区分けされており、開場時に「英検の方お待たせしました〜」と案内があり、会場間違えたかと思い焦りましたが、恐る恐る入って「Javaの試験何ですけど、、、」と言ったら案内してもらえました。
入院中なので左手首に名前付きの巻物があるのですが、試験監督から外してくださいと言われたのでブチっとちぎりました。帰った後看護師に伝えても特に怒られることはありませんでした。Java Gold も受験する予定であることを伝えたら、そのままちぎったやつ持っていてください〜とのことでした。
自分は1日に4~6Lほど炭酸水を飲むので1時間おきくらいにトイレに行きたくなります。試験監督に伝えたら「どうしてもという場合は可能」とのことでした。

試験中

白本模擬試験のように、問題で提示されるコードが長く感じました。ちんたら解いていたら見直しの時間がなくなりそうだったので30分経過後あたりから急いで解きました。
全ての問題を解いて見直しをする頃には尿意が限界になったのでピンポンを鳴らし、「すみません"どうしても"トイレ行きたいです。。。」と行ってトイレに行かせてもらいました。
見直しはチェックを付けた問題程度で、全ての問題を見直すことはできませんでした。

試験後

終了ボタンを押すと、即点数が出されます。帰り際に白黒コピーの試験結果を渡してもらいます。

試験終了から 25 分経った後にオンラインでの確認が可能になりました(メールで案内が来ます)。

翌日、認定証が閲覧可能になりました(こちらもメールで案内が来ます)。

合格したのでご褒美に近くの二郎行っちゃうかあ〜と思って行ったのですが、
10分ほど歩いて着いたところでシャッターが閉まっており定休日であることを知りました。
しょんぼりしました(事前に確認せずに場所に向かうことが多いので気をつけたいです。。。)。
入院中はにんにくの摂取が禁止されているので、それを守れたので良かったとしましょう。

終わりに

言語の細かいところ、知らなかったところを勉強できてよかったです。
手続型のオブジェクト指向言語が使える、言語の細かいところまで網羅できる素養があることも証明できていたら嬉しいなと勉強していて思いました。
次は Java Gold 取得目指します。

URL死活監視Discord bot

はじめに

数分置きに Google Sheets ドキュメント記載の URL に HTTP リクエストを飛ばすことで死活監視を行い、Discord の特定のチャンネルに概要、変化のあった URL をポストする Discord bot を作成しました。

github.com

freelancer.com のコンテスト(コンペのようなもの)に提出したものですが、他の方が選ばれたのでここに供養します。

提出物(1枚の画像と説明)はこちらから確認できます。

Entry #13 by arukuka for Lightweight Discord Link Monitor | Freelancer

動機

最近は Unity で簡単なゲームの一部のシミュレーションを作ったのですが、趣味でもっとコード書きたいから何かやりたいなあと思い色々漁った結果、このコンペはまず手を動かすことができるので取り掛かりました。賞金も獲得するぞ〜〜。

また、Discord bot が Google Sheets を読み(書き)するものは作ったことがあるので、 自分にもできそ〜くらいの気持ちです。

よかったことなど

技術要素

  • httpx パッケージを用いて非同期の API を活用できた
    • async あまり分からずだが便利。強い
    • aiohttp の方がパフォーマンスが良い、という話も聞いたがパッケージの選択は適当。開発速度重視
  • セマフォは存在のみ知っていたが、並列数を制限するのに使えることが分かった
  • Google Sheets ドキュメントは公開されている場合 CSV エクスポート API が生えていることが分かった
  • Docker の Python イメージをコンテナで動かす際に、標準出力をすぐにフラッシュさせるには以下の記述が必要ということが分かった
    • ロガーを使って標準エラー出力しろという話はあるが、、、
    environment:
      - PYTHONUNBUFFERED=1
  • (Claude Codeくんに書いてもらっていて、discord.py 特有の知識になるが)Embed ポストはやっぱり bot の特権。かっこいいことが分かった
  • Gemini くんに相談、骨組みを作ってもらったが playwright の存在を教えてもらった
    • 使ってみたい(1 vCPU, 1 GB RAM でヘッドレスブラウザーを並列に動かすのは無理でしょと最初から検証もせず諦めてしまった)

思いの丈

他の方との差別ポイントとして

  • 指定の動作環境で実際に動くことを確認していることを強調した(検証に$0.02かかりました)
  • 希望の上限である 5000 の URL が上記動作環境で(ローカルサーバーに対してだが)余裕を持って完了することを強調した
  • (discord.py 様々だが)200 URL が一度にステータスが変更になってもポストが正常に行われることを強調した
  • オプションとしてクローズドな Google Sheets ドキュメントに対してもアクセスできるようにした
  • 説明文章に上記含めてその他強みを記載した
  • AI で生成されていないスクリーンショットを利用した

ので自信はあったのですが、無念です。

Claude くんもかっこいい画像作ってくれたのに、ごめんね(HTML, CSS で構成してくれて、zipでくれと言ったらくれました。すごお)。

どのコンテストもそんなものなので、そういうものなのでしょうが賞金が ₹1000 INR。大体 1700 円くらいです。安い。。。

経験したことがあったので調査はそこそこにでしたが、実装、検証に計 1 日程度はかかってしまいました。おせえええ。

おわりに

技術的に新しい発見はあまりなかったものの、久しぶりにコードが書けて楽しかったです。

今後はまた Unity で別のシミュレーション作ったり、資格勉強したりしたいなあって思っています。

APRIL18B VAIMIN : April Challenge 2018 Division 2 - Vaibhav and Ministers

問題リンク
https://www.codechef.com/APRIL18B/problems/VAIMIN

概要

組合せをO(1) で求められるように前計算をし、
障害点を考慮しながらゴールまでたどり着く経路の総数を求めます。
for 文DPで書き、 O( (p + q) log MOD + M^2 )

考察

経路について

reputation がcを下回らないように、(p, q) に移動したい、
ということを図にして表すと、「カタラン数」で出てくるような
経路の数え上げ問題になっていることが分かります。

サンプル1 の場合、
f:id:arukuka:20180418233959p:plain

c は無駄の要素なので、与えられる p, q
から cを引いておきます。
その場合のコーナーケースとして、
c だけ good deals している間にVaibhav が提示している
点が通過点にないかチェックする必要があります。

経路は(0, 0) から (p', q) where p' := p - c
までを計算しますが途中M個の障害点を考慮してなければなりません。
包除原理を考える必要がありますが、ある点から次のある点までの
経路数が常に同じであるため、再利用できます。
これで、スタート位置からゴールまでにの経路数の
「奇数個点を通過してゴールについた経路数」 - 「偶数個点を通過してゴールについた経路数」
を計算すれば答えになります(スタートは偶数:0個とする)。
点はあらかじめ何回行動したか(g + b)でソートしてあげます。
同じ座標上に2点存在する場合もありますがそれを経由しようとすると
組合せは0になるため、特に考える必要はありません。

ある点Xから(右側の)ある点Y に移動する総数は

f:id:arukuka:20180418235907p:plain

このように、負のreptationを許す経路数から
「反射」の考えでその余分な分を引くことで求められます。
(自分も完璧に理解できていませんが、詳しくは下記書籍を読んでください。
自分はこれのおかげでなんとかACまで持って来れました。

note7.hyuki.net


以上を踏まえて実装すると

Solution: 18236218 | CodeChef

となります。

AOJ 2511 : 沈みゆく島

Sinking islands | Aizu Online Judge

一番最初のサンプルケースを見ると、
沈む時刻が最後の方から最小全域木を構成していくと良さそう
(座圧して、時刻が同じものはグルーピングしておく)。

一番最初に沈むところまで終えて、
Union-Findが全部同じ親を持つかチェックして
ダメだったら0を出せばいいのかな。

しかしこれでは4番目のサンプルケースが合わない(金額が高くついてしまった)。
何故だ…。ふと普通に最小全域木にしたらコストはどうなるのだろうと思って
やってみたらサンプルと一致する。ホンマか。

図解してみる。

f:id:arukuka:20170617082237p:plain

えでもこれじゃあ時刻25で2の島が沈んだときに
島7-9にリンク張らないとまずいのでは?
と思ったけど、

この場合は,新たに橋を架けることで,まだ沈んでいない島々の間で移動経路が確保できるようにする.
どのように橋を架けても移動経路が確保できなくなった場合は,それ以上の橋の建設は行わない.

これは「全域木が構成できないと分かったらそれ以上リンクを張らない」ということだった。

そこで全域木を構成できない一番早い時刻を記録しておき、
そこまではあらかじめ一緒くたにして最小全域木を構成し、
そこから前に遡りながら島を追加し、最小全域木を構成することにした。

この操作は一般化できるので、

なお,現時点で既に移動経路を確保するように橋を架ける事が出来ない場合は,橋の建設は一切行わない.

これについて気にする必要はなくなる。

AC。

http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=2375641#1

関数calが「全域木を構成できない一番早い時刻」のindexを返し、

      for (int i = 0; i < s; ++i) {
        List<Integer> comer = t.get(i);
        list.addAll(comer);
        added.addAll(comer);
      }

これが「あらかじめ一緒くたにして」いる操作になる
(降順に座圧してます)。
あとは後ろから最小全域木を構成している。

座標圧縮はソートで十分だとは思うけど、
こちらのほうが実装が楽に感じた。


あと少しで諦めて解説を見るところだった…。
しかしサンプルに助けられてしまったなあ。

YQL で html を読み込む方法が変わった(html table is no longer supported.)

algon-320.hatenablog.com

id:algon-320 さんのウィジェットを使わせていただいて、
rating を取得していたのだけれど、ある日AtCoderのratingが
取得できなくなっていた。

返ってきたjsonを見てみると
html table is no longer supported. See https://policies.yahoo.com/us/en/yahoo/terms/product-atos/yql/index.htm for YQL Terms of Use
と出ていた。

その日ずっとドキュメントを見ていたが解決できず…。

今日もう一度調べてみたらStack Overflowが引っ掛かった。

stackoverflow.com

htmlstringというのを使うようになったらしい。

出力も色々変わったようなので新しい仕様に合わせて
rating取得部分を修正。

  function getAtCoderRating() {
    var userpage = 'https://atcoder.jp/user/' + handles['atcoder'];
    var yql = "select * from htmlstring where url='" + userpage + "' and xpath='//*[@id=\\'main-div\\']/div/div/div[2]/dl/dd[2]/span'&format=json&env=store://datatables.org/alltableswithkeys&callback=";
    var url = 'https://query.yahooapis.com/v1/public/yql?q=' + encodeURI(yql);
    $.ajax({
      type: 'GET',
      url: url,
      dataType: 'json',
      timeout: 10000,
      cache: false,
      success: function(json) {
        if(json['query']['results'] != null) {
          ratings['atcoder'] = Number($("span:eq(0)", "<div>" + JSON.stringify(json['query']['results']['result']) + "</div>").text());
          setHtml('atcoder');
        }
        else {
          setHtmlWithoutColor('atcoder');
        }
      },
      error: function() {
        setHtmlWithoutColor('atcoder');
      }
    });
  }

ちょっとjavascript慣れてなくてスマートな感じではないですが…。

これで色付けできるようになりました。


こういうの、ドキュメントのどこを調べると分かるのだろう…。
今回は「後でStack Overflowに出るでしょ」と思ったので放置したけど、
そうはいかない場面に出くわしたときに対処できるようになりたい。

JOI 2012-2013 予選 問題4 : 暑い日々 (Hot days)

JOI 2012-2013 予選 問題4

D: 暑い日々 (Hot days) - 第12回日本情報オリンピック 予選(オンライン) | AtCoder

id:keidaroo さんのblogに触発されてどんなもんじゃろと解いてみました。
JOIの問題は解いたことがないので…。

keidaroo.hatenablog.com

解いてみる

今何日目か前日何を着ていたかが分かれば
その中で最大化しても問題ないことが分かる
(前日より前に何を着ていたかは関係しないため)。
状態dn、遷移nのO(d n^2)DPを組む。

Submission #1356723 - 第12回日本情報オリンピック 予選(オンライン) | AtCoder

最初同じ服を連続して着てはいけないと誤読して
サンプル不一致になる。

なお、日については今と前にしか着目する必要はないので、
dpテーブルの次元は1つ減らせます(int dp[n], next[n]でいい)。

id:keidaroo さんのblogを読んで

解法が違う…。どうなっているんだ。

maxi[i] := 最高気温がiのときに着れる一番派手な服の派手さ
mini[i] := 最高気温がiのときに着れる一番派手でない服の派手さ
これで一日ごとに「最大」を取るか「最小」を取るかで遷移させていく
再帰関数のmaiが0のとき最大を取って、1のとき最小を取っている)。
O(d)。

なるほどすごい…。
でもイマイチこれで最適解が求まる理由がよく分からない…。
中間の値を持っておいたほうが得するということはないのだろうか。

f:id:arukuka:20170616183212p:plain

・・・ウーン確かにどう動かしても、
差の絶対値なので☆のところを取ったほうが良いということはなさそう。

解説

JOI 2012-2013 予選 問題4 解説
id:keidaroo さんの解き方が発展課題の方で、
私の方が愚直に解いたものになる。

解いてみて

今でこそ何とか解けるものの、
JOI予選のときに解けたものではないです
(私は高専2年のときPCK2011予選で0完、JOI2011-12予選未参加です)。

素直に、すごいなあと思うばかりです。

ポエムはできる限り避けたいですが

※はじめに言っておきますが、皆さんにとってはこの問題は楽勝だというのは知っているので、決してイキリとかそういう風に思わないでください。誰だって自分が解けなかった問題が解けるようになると嬉しいのです。(たとえどんなに簡単な問題であろうと)

暑い日々AC - keidaroo’s diary

こういう言葉を出させるコミュニティって非常に残念ですね。

同じ問題解いているお前はどうなんだという話もありますが(まあごもっとも)
競プロを始めたばかりの頃を回想したくて解いたので攻撃的な意味合いはないです。
不快に思ったら申し訳ないです。

AOJ 2510 : 双子の読書感想文

Twin book report | Aizu Online Judge

DPだと思うけど大変そう。
最初rを2つ分けたときの大きいほうの最小値を求め、
余った時間に感想文を詰め込もうとしたが
無限にWAを重ねた。
半日頑張ってダメだったので諦めて解説を見る。

2013/Practice/模擬国内予選/講評 - ACM-ICPC Japanese Alumni Group

少し誤字

一番読むのに時間がかかる本をLとする

正しくは「一番読むのに時間がかかる本を r_L とする」

誤字じゃなかった…。rって問題文に出てくるrのことか…。
日本語を勉強しましょうね…。

本当に? と思ったけどなるほどなあ…。
考察が足りなかった。

http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=2374150#1

ウーン悔しい。