サイボウズでAndroidサマーインターンに参加したお話
こんにちは。こちらの記事では2023年8/21~9/1の期間に参加させていただいた、サイボウズ株式会社さんのAndroid2weekサマーインターンシップについて書き留めたいと思います。
参加までの経緯
私は普段、個人でkotlinを用いたAndroidアプリ開発を行っています。そこで実務レベルでAndroidアプリ開発を経験できるインターンシップを探していました。加えて現在修士1年であるため、就活の観点からもインターンシップを探していました。 4月頃にサポーターズ経由でサイボウズのインターンシップ説明会を知り、参加することにしました。リモートで実施されていましたが、社員さんの気さくな雰囲気やインターンの紹介から、この会社のインターンに参加したいと思うようになりました。
選考
選考は書類選考->面接->参加決定 の流れでした。 面接ではインターン説明会に登壇されていた社員さんに面接していただき、緊張することなく行えました。
事前顔合わせ
インターン参加が決定した後、他のインターン生との顔合わせイベントがありました。イベントは本社オフィスで行われました。メンターさんや人事さんはもちろん、同じAndroid2weekコースのインターン生や、Android1weekコース、iosコースのインターン生とも交流でき、インターンの雰囲気を感じ取れるイベントでした。
インターン
インターンは自分を含めたインターン生3名とメンターさん3名の計6名を基本に行われました。インターンでは主に以下の内容を行いました。
- ウォーミングアップ
- スクラム開発
- LT会
- 成果発表
- その他イベント
ウォーミングアップ
インターン開始後、まずはウォーミングアップとしてJetpack Composeのコンポーネントに触れました。はじめはインターン生が各々実装し、メンターさんがGithubでレビューをする形でした。その後、インターン生がモブプログラミング形式でJetpack Composeに無いMaterial Componentを実装しました。実際に作ったコンポーネントはListTile, 折りたたみリスト, SliverAppBar, Cardの4つでした。ウォーミングアップではJetpack Composeの再確認とモブプログラミングの練習が行えました。
スクラム開発
ウォーミングアップが終わったあと本格的にプロダクト開発がはじまりました。サイボウズでは一週間でワンスプリントとして開発が行われています。今回開発したプロダクトはサイボウズOfficeのAndroidアプリです。こちらのすでにリリースされているアプリに機能追加を行いました。 開発の大まかな流れとしては、バックログの確認->取り組むプロジェクトバックログアイテム(PBI)を選択->デザイン確認->実装->レビュー->修正->デザイナーさんの確認->品質管理 といった流れで行われました。 PBIは朝会などでPMさんやデザイナーさんQAさんと確認することでチームメンバー全員で情報共有する体制が整っていました。 実装はKotlinやいくつかのライブラリを使用したインターン生同士のモブプログラミングで行われました。すでに実装されていたり、似たような機能の実装がなされていたので、それらのコードを使用する形で大きく詰まることなく実装できました。 またテストコードをJUnitやmockKを使用して実装する機会がありました。個人開発ではなかなか書くタイミングがないテストコードですが、これを機に習慣的に書いていこうという気持ちになりました。
LT会
メンバーの交流を兼ねたLT会が実施されました。私は趣味のメモリースポーツについて発表しました。 ja.wikipedia.org
成果発表
インターン最終日に各コースの成果発表会が開催されました。他のコースでどのようなことが行われたか知る、良い機会となりました。
その他イベント
社長の青野さんとお話できる雑談会があり、サイボウズという会社を経営していくうえでの心構えなどを知ることができました。
最後に
2週間という期間でしたが、メンターさんや社員の方々と交流させていただいて、エンジニアとして視界が開けたと思います。今回のインターンの経験を糧にエンジニアとしての能力を向上させていきたいと思います。 本当にありがとうございました。
picoCTF 2019: Java Script Kiddle
picoCTF 2019: Java Script Kiddle
リンク
https://jupiter.challenges.picoctf.org/problem/58112/
問題
keyをformに入力してSubmitすると画像が表示される。画像にフラグがあるから適切な画像構築してね。
Solution
サイトのJavaScript読むと、pngを構築する関数assemble_png()
が確認できる。
var bytes = []; $.get("bytes", function(resp) { bytes = Array.from(resp.split(" "), x => Number(x)); }); function assemble_png(u_in) { var LEN = 16; var key = "0000000000000000"; var shifter; if(u_in.length == LEN) { key = u_in; } var result = []; for(var i = 0; i < LEN; i++) { shifter = key.charCodeAt(i) - 48; for(var j = 0; j < (bytes.length / LEN); j++) { result[(j * LEN) + i] = bytes[(((j + shifter) * LEN) % bytes.length) + i] } } while(result[result.length - 1] == 0) { result = result.slice(0, result.length - 1); } document.getElementById("Area").src = "data:image/png;base64," + btoa(String.fromCharCode.apply(null, new Uint8Array(result))); return false; }
var bytes
はhttps://jupiter.challenges.picoctf.org/problem/58112/bytesの値を配列に代入している。
つまり上記のコードは、
pngファイル:
以下の8バイトの signature から始まる
89 50 4E 47 0D 0A 1A 0A
signatureのあとにIHDRというchunkがあり, 以下の8バイトのデータが続く
00 00 00 0D 49 48 44 52
ということからresult
の最初の 16 個の値が確定するのでkey
の候補を絞り込むことができる。
result
の最初の16個は, 以下のJavaScriptのコードの j = 0
のときなので、
var result = []; for(var i = 0; i < LEN; i++) { shifter = key.charCodeAt(i) - 48; for(var j = 0; j < (bytes.length / LEN); j++) { result[(j * LEN) + i] = bytes[(((j + shifter) * LEN) % bytes.length) + i] } }
result[i]
がbytes[(key*LEN) % bytes.length + i]
と等しいかを見ればよい。もし等しければ、その時のkey
の値は解の候補となる。
import requests r = requests.get('https://jupiter.challenges.picoctf.org/problem/58112/bytes') _bytes = [int(x) for x in r.text.split()] # png header result = [ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, ] for i in range(16): print("{:02d}".format(i) + "th possible key is: ", end="") for key in range(10): if result[i] == _bytes[(key * 16) % len(_bytes) + i]: print("{:x}".format(key), end=" ") print() dp = [[] for _ in range(20)] dp[0].append("") for i in range(16): for key in range(10): if result[i] == _bytes[(key * 16) % len(_bytes) + i]: for d in dp[i]: dp[i + 1].append(d + str(key)) for d in dp[16]: print(d)
結果:
00th possible key is: 4 01th possible key is: 8 02th possible key is: 9 03th possible key is: 4 04th possible key is: 7 05th possible key is: 4 06th possible key is: 8 07th possible key is: 4 08th possible key is: 8 09th possible key is: 5 6 10th possible key is: 1 2 11th possible key is: 6 12th possible key is: 7 13th possible key is: 1 14th possible key is: 0 15th possible key is: 4 4894748485167104 4894748486167104 4894748485267104 4894748486267104 プロセスは終了コード 0 で終了しました
出力された4つのkeyをformに入力するとQRコードが生成されるので、それがflagとなる。
参考
TOEICで700点取る#2
Day 2
真偽不明の情報に踊らされた翌日、研究室の教授に詳細を聞いたところやはり真偽不明だった。ただ院試は英語でのプレゼンなので、やはり英語は学ぶべきである。よって当初の予定通りTOEIC700点を目指す。
やったこと
・トレーニングTOEICアプリ
play.google.com
のPart5Chapter1Lesson1~3を行った。
・上記レッスンで分からなかった英単語をAnkiに登録。
今後の表記
TOEICアプリ → Part1 Chapter1 Leasson1 = P1C1L1
E - Virus Tree 2
URL
問題
N個の頂点とN-1本の辺がある。頂点をK色の絵の具で塗り分ける。ただし2つの頂点の距離が2以下なら異なる色となる。このときの塗り分け方は何通りか?
解法
公式解説にあるように、頂点 x とその親が既に塗られているとき、x の子の数を cx とすると、x の子の塗り分け方はK−2Pcx 通りある。これをdfsで求める。
コード
C - Max GCD 2
E - Transformable Teacher
URL
問題
N人の身長Hiが与えられる。Nは奇数。そこにM個の自分の身長の候補Wiが与えられる。N+1人でペアを作ったときの、身長差の合計の最小値を求めよ。
解法
ペアを作るときに身長差が最適になるには、小さい順に並べて先頭からペアを作ることである。そこにクエリごとの自分の身長を最適な場所(lowerboundでわかる)にWを挿入し、身長差の合計を高速に計算したい。
身長差の合計は累積和を用いて計算する。左右からの累積和を用いて
left[i] = Hの左i個までの身長差の合計
right[i] = Hの右i個までの身長差の合計
としてWの挿入位置の左側にHがi個あったとすると
iが偶数の時:left[i]+right[N-i-1]+(Hi-W)
iが奇数の時:left[i-1]+right[N-i]+(W-Hi-1)
となる。
コード
https://atcoder.jp/contests/abc181/submissions/27480833