更新日時で差をつけろ

もはや更新日時でしか差を付けられない

一人部屋に移った

たまにログインしてアクセス解析を見てみると特に何もないのに急にアクセスが増えることがあって面白い。

寮の部屋移動を済ませた。待ちに待った一人部屋である。今までは一つ上の先輩もしくは一つ下の後輩との二人部屋だった。 前の入居者がなかなか出て行かなかったので荷物を運び込むのが遅くなってしまった。前の入居者について文句を言いたいわけではなくて、その人はその人で来年度過ごす部屋に住んでいる人が…というのをくり返して卒業予定の5年生が早く出て行ってくれないと動けないので仕方ない話である。閉寮が早すぎるんじゃないかと思った。

荷物を運び込んで、前の二人部屋を掃除して、新しい部屋を掃除して(一応出る人が掃除することになっているとはいえ明らかにそれほどされていなかったのでやり直した)、レイアウトというほどでもないが適当に考えてモノを収納した。同級生の助けを借りても6時間弱かかった気がする。学校でもらってきたマット数十枚を掃除機で一枚一枚吸うのが大変だった。しかしながら、一人部屋の気楽さというのは移動が終わる前から始まっていた。何をどこに置くかは(だいたい)自由で一番納得いく形になるよう工夫することができて楽しい。あくまで物理的な存在という制約が課せられているのでちょうど良い難易度というか、考えの余地になる。

部屋自体は棚のサイズが2倍になった。一人当たりのコンセントの差込口が3倍の6つになった。代わりにタコ足をどこかに失くしてしまった。それでもパーキンソンの法則よろしく両方使い切ってしまうんだろうなあ。 窓を独占できるが、建物の反対側なので新幹線ではなくB寮が見える。部屋で縦に吊るしていたカナダ国旗は他にいい場所がなかったので大胆に窓側にぶら下げてみた。B寮からはこれが見えるのだろうか。見えたらどんな気持ちになるだろうか。上下逆さにしたら気づくだろうか。

ドアを閉めると自分の目に動くものは何も動いていなくて「ああ帰ってきたなあ」という感覚がとても強くなる。大阪に住んでいたときの自分の部屋がスライド式のドアで、寮もそれと同じなのがその感じを補強しているように思える(ドアを開ける方向は違う)。 目の前に他人がいるとどうしてもそっちに気持ちが向いてしまうのに対して、なんだか居場所がちゃんとそこにあるような安心感がある。

夜中に作業しないといけないことになっても相手の迷惑を考えなくていいし、好きな時間に寝て起きられる。考え事をするときに無意識に部屋の中を歩き回っても何も言われない。どうしても人に会いたくなければホワイトボードに「作業中なので入室は後にしてください」と書いて部屋の鍵を閉めてしまえる。わざわざ夜に散歩に出なくてよくなる。散歩は多分するけど。なんか言葉にするとどうでもいいようなことのように思われそう。

一方で一人部屋になっても変わらないこともある。夜中になっても物音・話し声はするし、むしろ向かいの部屋の人がスピーカーでEDMを流している上に隣は大部屋で不吉な予感しかしない。3階なので廊下にドアが設置されておらず声がよく通ってしまう。

昨年度二人部屋になったときは「人の目がある方が勉強とかできていいかな」と思っていたが全然そんなことなかった。この発見を裏付けるためにもそれなりにうまくやっていきたい。

しかし明日には寮が閉まり大阪に帰る。さらば一人部屋…

たのしい潮寮生活 2

高専 Advent Calendar 2018の6日目の記事です。

明石高専電気情報工学科2年のsei0oです。
高専への進学を検討している中学生や通学している同級生に寮がどんなところか知ってもらえればと思い書いたたのしい潮寮生活がそこそこ見られているようなので、調子にのって2つ目を出すことにしました。時間が空いているので、内容は結構変わっています。「潮寮」というのは明石高専学生寮の名前です。

2年生の視点で書きます。 2年生の視点で書きます。大事なことなので2回言いました。昨年からの差分を主に書きますので、上の記事から読むとわかりやすいと思います。 高専自体についてはあまり書きません。

公式も参照してください。みどころはやっぱり寮長からのメッセージかなあ。

去年は 住めば都 とか書いてたような気がしますが、最近やっぱりそうじゃないかもしれないと思えてきました。 なんとなくAdvent Calendarの昨日の記事を読むと、

明日6日目はsei0oさんの「たのしい潮寮生活 2」です。私は通生なので詳しくありませんが、寮生がゴミ回線と虚無な飯と点呼によって精神を病むのは全国共通なんですかね?うちがひどいだけ?

うーん。否定できない。

立地

まずはデータから。

  • 校内に設置されているので教室から歩いて3分
  • 1, 2, 3年男子寮のA寮(私はここに住んでいるので、ここを中心に書きます)
  • 3, 4, 5年, 専攻科のC寮
  • 女子寮のB寮
  • 国際交流センター
    • 留学生しかいない棟(たぶん)
  • 隣に老人ホームが建ったので窓からドクターイエロー見えなくなりました

部屋

昨年は203号室、今年度は209号室です。1・2年の2人部屋で、向かいは3年生の一人部屋。 相変わらずオタクです。本棚の本をひっくり返して背表紙が見えないようにすると脳のエネルギーが節約されて快適です。 二人部屋だとだいたい2年生が冷蔵庫を買って1年生と共同で使うので、前の同部屋の先輩と同じものを買いました。 Abitelax AR-100E

後方確認

結構気分で机周りのレイアウトは変えていて、机の上にいろいろ部品を載せて開発するときは灰色の机を90度回転して黒い机と合体してL字型のようにしていました。

改修

夏休みに、2F, 3Fのそれぞれ8部屋が改装されました。そこだけキレイ。 こんな感じで境界がくっきりしています。なぜかその両脇に設置された消火器はさながら国境警備隊のようです。見てわかる通り、手前が歴史のある地区、奥が改装された地区です。

ドアに高専プロコンのポスターを貼る高専生の鑑。

なんでもタイのなんとか王女なんとか高校から留学生を恒常的に受け入れるそうで、2・3階の1人部屋が「交流スペース」になったり、寮生ホールにユニットバスが設置されたりそこそこ大きな改修がありました。1人部屋にいた人はどうなるの?ということですが、かつての談話室が2人部屋に改装されてそこに新たな1年寮生と1人部屋の2年生が入っています(今年は1年生の入寮希望者が多くて入学と同時に入寮できない人がいました)。1人部屋を追い出された2年生は若干気の毒ですね(他人事)。

「交流スペース」を利用している人はほとんどいませんテスト前になると使う人が増えました。でも先輩が通ったら作業中でも挨拶しなくちゃいけないことになっています。

また、新しいシャワー室と洗面所ができました。まだきれい。

生活

今年の1年生が利口なのか、指導寮生(寮生役員会)が軟化したのか(たぶん両方)今年は入寮後に1ヶ月ほど大声挨拶があったあとは復活していません。ありがたい。

今年の2年寮生は多いので2人部屋に収まりきらず、1人部屋になる人も出ました。進級するときにじゃんけんで確か決めたような記憶があるのですが、話し合いでボケーッとしていたら私は2人部屋になりました。1人部屋になって監視の目がなくなると生活崩壊まっしぐらなので丁度良いです(言い訳)。

昨年は「同部屋の先輩」でしたが、今年は「同部屋の後輩」。都市システム工学科(C科)の1年生です。 プライバシーにうるさい時代なので詳しくは書きませんが、私は朝型であるのに対し彼は夜型(徹夜型)です。試験期間になると消灯がなくなり彼が徹夜で課題をするので、私は耳栓とアイマスクをして寝ていました。 あとはエアコン。私は28度で使って、暑いときは26度まで下げるのが普通だと思っていましたが、ある日部屋に入ると突き刺すようなひんやりとした感覚があったのでリモコンを見てみると「18度」。聞いてみたところ、部活の後は暑くて28度ではやっていけないらしいです。28度に戻しても気づかないうちに温度が変えられているので上着を羽織って凌いでいました。他の部屋に枕を持って疎開したことも何度か。 エアコンの温度を下げるにつれて私の就寝時間が早くなり、起床が遅くなるらしいです。試されてたのか…

今年だけの話とはいえ、工事も個人的には結構負担でした。土日でもお構いなくカンカンカンカン聞こえるので、部屋の中ではずっとイヤーマフか耳栓をしていました。試験前やプロコンなどでピリピリしているときは、工事でなくとも同部屋の喋り声・口笛だけでもイライラします(ごめんな…)。余計な衝突を避けるためにも 一人になる方法や五感を遮断する方法は作っておいたほうがよい です。自己管理大切。常に周りに人がいる状態は一人っ子にはつらい。 図書館にこもって作業するのもオススメです。学校の図書館と明石市の西部図書館が近くにあります。西部図書館には苫米地英人の本が置いてあったこと以外覚えていませんが、学校の図書館には「CPUのつくり方」みたいな専門書も結構置いてあって良いです(良い)。

これくらいかな。あっ、(男子の) 風呂 を忘れていましたね。半年以上前にレジオネラ菌が発生した影響で毎日18:00ごろから数回消毒液のようなものが浴槽の壁から出てくるのですが、これが臭い臭い。ときたま身体が痒くなることもありますがこれは多分気のせい。1,2年生は17:30からしか風呂を使えないので、18:00までの30分が鍵となります。20:00ぐらいに行けば臭いは薄まっているでしょうが、その時間帯はすでにお湯がヌルいんだよなぁ… 早く改善されることを祈るばかりです。

…嘘です。新設されたシャワー室しか使ってないのでもうどうでもいいです。元来シャワーだけというのは好きではありませんが、静けさと部屋からの近さを考えればシャワーの圧勝です。実際、同じ階の人の半数近くがシャワーのみで生活しています。

人間関係

少なくとも通学生に比べれば寮生は親密になります(多くの場合)。私はそうです。 いろいろチームで課外活動をするにあたっても、寮生なら直接部屋に突撃して進捗を強要できます。SlackとかDMで連絡してもスルーする人いるからねえ(自戒の意味を込めて)。

他の部屋の一年生には「209仲良いっすよねえ」と言われるのでそれなりにうまくできているんでしょう。「1年生、入寮直後は不安だろうなあ」と思ってたくさん私のほうから話しかけたのはあるとはいえ…。他の2年生から話を聞くと、「ほとんど話してない」「何考えてるかわからん」というのもあるので、相性ばかりはどうしようもないです。でもそんなときは他の部屋に篭もれば大丈夫です。 バーチャルCTF班などと題して夜に部屋に集まって情報工学研究部CTF班の活動をするなどというのは楽しいです。こうでもしないと人が来ない

まとめ

いろいろ書きましたが、なんとかするぞという意志を持てばなんとでもなります。 寮務や先輩、同級生に相談しつつ反抗的な態度を取らなければ十分快適に寮生活が送れます。

高専アドカレ、明日は@lz650sssさんが「高専生はもっと積極的に勉強会に行くべき」という記事を書かれるそうです。

そういえば12/16の大和セキュリティでキャンセルが出たので、久しぶりに勉強会に行けます。わーい。明石高専IT系勉強会も引き継ぐことになったので続けていきたいですねー。

全国高専プロコンに参加した #procon29

第29回全国高専プロコン に参加した。阿南高専が主管校。そこの学生さんたちがスタッフとしていろいろ大変だったらしい。

昨年は競技部門だったが、今年は明石高専・課題部門「スマートコンシェルジュ」としてブースに立った。5人チーム。 結論から書くと、受賞はなかった。学生間の相互投票では1位だったが、投票の母数はそんなに多くないはず。

もしかすると他のコンテストにこれを出すかもしれないので、プロダクトの詳細はぼやかして書く。ところで、チームメンバーが思いっきりプロダクトの実装をTwitter上で質問していたので少しヒヤヒヤした。何もなかったのでよかった。おそらく自分がちょっと過敏だっただけ。

予選まで

学内でプロコンの案内が出て、「あーまあ今年はいいかな」と思っていたところで昨年一緒にプロコンに出たM君に誘われた。アイデアはあるらしい。「うーん、それって面白いのか?」と思いつつ手伝うつもりで出ることにした。今思えばこの手伝うつもり、って心構えが無責任さの現れだよなーと思う。もうちょっとしっかり考えておけばよかった。実装は楽しかった。 学内予選があったが、候補が自分たちのチームだけだったのでそのまま予選資料に着手した。たしか実装はほとんどしていなかったと思う。スマートスピーカーを使ったプロダクトだったので、Amazon Echo, Google Homeの比較をしてみたり…という段階だったはず。放課後に研究室に集まって作業の割り振りとか設計の話してた。

予選資料提出の2週間前ぐらいに資料を作り始めた。M君が作ったのをベースに担当の先生のアドバイスを組み込んでいく感じで進めた。文章を考えたり図を作って入れたりするのが面倒だった。定期試験がすぐ後にあって結構焦っていたのを覚えている。急にPCの調子が悪くなって寮の貧弱無線LANに接続できなくなったので学校で作業したんだっけ。なんとかギリギリで提出して、「いやーもっと早くからやっておけばよかった」みたいな話をしていたら通ってた。驚いた。通過ランクはBなので予選では11~20位のどこかということになる。審査員のコメントは(自分は)無視した。

本選まで

この予選資料を基にして実装を進めることになった。つまり予選資料として提出するまでほとんど具体的に設計、というより実装する機能がまとまっていなかった。チームメンバー間の技術レベルに差があったので「一人でやったほうが早い」病に苦しめられた。分担してみるとそんなことなかったんだけれど。

自分は途中で留学したのもあって10月始まってからグオーっと開発した。ソースコード提出が終わってから本選までのコミット数が、予選通過後からソースコード提出前のそれより多い。寮の消灯を伸ばしてもらって開発することもあった。同部屋さんごめんなさいとも思ったが普段冷房で散々な目にあっているのでお互い様である。本当にヤバくて「プロコン行きたくない〜〜〜」とかむちゃくちゃなこと言ってた。ピリピリしてた。

そんなわけで(自分の)累計開発期間は1ヶ月と少し。

出発〜本選1日目

購入しておいたバスチケットを競技部門含めたみんなに配って前日入りした。車内でもLANが使えた。実装しようとPCを開いたら酔った。ホテルの無線LANはまさかの暗号化なしだった。階ごとにルーターが違う方法で設置されていて面白かった。会場にいくと東京高専のオタクが突如現れて怖かった。2人で自撮りした。夕食は中華そばの店に行った。腹が満たされて少し焦りが和らいだ。出た瞬間に雨降ってきてびしょ濡れになった。

結局徹夜した。実装の関所を越えたところだったのでサクサク進んで楽しかった。MONSTERのCUBA LIBREがすごく美味しかった。なんだこれ。

朝は食欲がなかったが体力を使う日だとわかっていたのでそれなりにしっかりホテルの朝食をとった。よくわからないアニメが流れていた。前日に運び込んでいないので、荷物を忘れていないか心配だった。

会場に向かうバスでも「帰りたい〜〜もう無理や〜」と気分だったが、いざブースに立ってみれば幸か不幸か案外マシな反応が得られるものである。一安心した。メンバーのプレゼンもうまくいったらしい。手書きで機械学習アピールをしだすの面白かった。する意味はなかったんじゃないかと思うが。

スマートスピーカーは物理的なインターフェースを少なくするために無線LAN経由で設定を行うが、会場ではいろいろなAPが立てられていて実機を動作させられなかった。仮に設定できていたとしても、会場の騒音ではうまく音声認識ができたとは思えない。あらかじめ予想はしていたがどういう騒音対策をとればよいかわからず何もできなかった。結局当日はAlexa Skill Kitが提供しているスマートスピーカーのシミュレータ上でデモを行った。

あと会場の電気を使っていいよと言われるまでルータで有線LANを構築できなかったのでRaspberry Pi等の設定も遅れた。こうしたトラブルに見舞われて最初の1時間強は展示できなかった。

Twitterで知り合った他の高専の人にも会った。名刺をたくさん交換した。ぐるーっとブースを回ってみたが自ブースが気が気でなくてじっくりとは見ていない。

終わるころには話し疲れて「帰りたい〜〜」って言ってた。学生交流会はいつも通りすごかった。Twitter大事。夕食はカレー。

本選2日目

急遽作ったポスターを貼った。事前にポスター作ってないチームって今思ってもクレイジー。靴下を持っていくのを忘れて靴を直接履いていたら靴擦れしたので途中からブースの外では裸足だった。痛かった。

デモ審査とマニュアル審査があった。まあまあうまくいったが、一部完成度の低さが露見する場面があってつらかった。

冒頭で述べた通りチームの受賞はなかった。詫間強いなー。阿波踊りが思っていた以上に長かった。なんかすごかった。でもやっぱり依然として早く帰りたかった。

その後

バスまで時間を潰す必要があったが、徳島駅前のどこかで作業しようと場所を探したが手持ちのMacのバッテリー残量が3%だったので適当に100均あたりをうろうろした。 バスで隣に座ったメンバーが悔しいと言っていた。そうだねえと言おうとしたが、まあこの作業量なら当然の結果だよなという思いもあったので何も言わなかった。

徳島の街並みはちょっと古いのがよかった。

同日にロボコンの地区大会(?)もあった。明石Aチームが全国進出した。すごい。 翌日になってロボコンの話のあとに「そういえば、」のノリでプロコンの話題を振られるのも、それに対して「ダメだったよー」と返すのもこたえた。


個人でまとめていた反省点は箇条書きでも3700文字ぐらいになっていた。たとえば、技術レベルの差があるのは割り切って、予算あるんだし本でも読んでもらえばよかったんじゃないかなあと思っている(そうすれば当人が暇になることも無力感を覚えることもなかったかもしれない)。何かメンバーが困っている時に直接口で説明すると疲れるし、部屋に来られても集中できないのでまずはSlackで話してもらうようお願いしておいたのはよかった。

Trelloを使ってタスク管理をしてみたが常用していたのは自分だけだった。そういうツールが必要になるレベルにすら全体の作業量が達していなかったのかもしれない。すぐ忘れる性格なので個人的には助かった。

昨年の記事を読み直すかぎり結構つらそうな書き方をしているが(たぶん自戒の意味を込めてきつく書いたような気がする)、それに比べて今年は諦めがついたというか「ないものはない」という考えで落ち着いているように思える。メンバーも高専祭実行委員会・インターン・FE/AP試験で忙しかったし。(ただの言い訳じゃないかという人もいるかもしれないけれど知ったこっちゃないです。学びがあったのでそれで僕は今年はそれでいいと思ってます。)SecHack365でトレーナーの方に教えていただいたこともこの辺に影響を与えていそう。

来年はもうちょっと計画的に進めていきたい。出るかわからないとはいえ。 プロコンに参加した人も運営の人もお疲れ様でした。

angstromCTF 2018 に参加した

sei0o, @yfba_, @6Lgug, @cotton392, @Tako_Mochiii でチームを組みました(BiPhone)。

angstromCTF 2018 に出ました。

自分は1630pts取って合計2465ptsで37位、景品を受け取る資格があるアメリカ在住の高校生のチームならば6位と7位の間でした。

低難度の問題が案外すぐ尽きてしまってCTFに意欲を示していた2人が1問も解いてないのがアレ。yfba_が予想以上に熱心にやってた。
slots, Very ez cipher, Washington, Hellcode, Bank Ropperyは解きたかったなあ。
逆にFile Storer, Madlibsは過去のCTFでの知見を活かせたので良かった(両方web...)。

Discordグループをメモとおしゃべりに活用した。楽しかった。

解いた10問のwrite-upはScrapboxに置いてあります

3/5

午前中はAtCoder Omedesを作っていた。Elixirのリハビリ。コンテストごとにレート色が上がった人を祝福してくれます。
午後からはx86エミュレータをElixirで作っていった。条件分岐をif-elseでやるか、ガードでやるか、もしくはループをEnumで実現するかパターンマッチ+再帰で書くか迷う。
HTTPoisonなどを読んでみるべきだろうか。コードリーディングは若干苦手だが…
The BEAM Bookというのもあるみたい。

群論なんかこわくない」「バイナリで遊ぼう」も100ページ弱まで進んだ。
アーベル群とか部分群とか出てきて本格的になってきた。
アセンブリ短歌が想像以上に面白い。でも自分では思いつかないなぁ…

本を読むのは楽しいけど、ちゃんと身につけるようにしたい。どうやったらいいのかわからないからとりあえず手を動かすようにはしている。
pwnもcryptoも最近してないしそれに関して言えばよくない。もっと集中してスピード上げたい。

IOLは書類をやっとポストに入れてきた。通るかな?

3/3: 閉寮

閉寮なので家に帰った。1ヶ月後には後輩ができるのか…
久しぶりに浴槽に浸かれた。素晴らしい。

なんとなく図書館に行った。x86エミュレータの本が目当てだったけど他にもいろいろ面白そうなのでついつい8冊借りてしまった…
割と薄めの本ばっかりだしルータ本と線形代数本とTOEICあってもなんとかなるでしょ!w

  • 自作エミュレータで学ぶx86アーキテクチャ Twitterでおすすめされているのを見た。著者の人すごい…。個人的に表紙にキャラクター載ってるとちょっとアレ。かわいいとはいえ。
  • 群論なんかこわくない 対話形式で進める群論の入門の本。適当に数学書の棚に行ったらあった。すでに60ページほど読んだ。
  • APIデザイン ケーススタディ Rubyのメソッドを作る際に考えられたことをコミッタの人が書いてる
  • リンカ・ローダ 実践開発テクニック 半年前だったらまず手に取らなかったであろう本。というか全部そう。実際にリンカを作るので楽しそう。
  • ソーシャル・エンジニアリング コミュ力を身に着けたい(誤った動機
  • バイナリで遊ぼう! どこかでおすすめされてた本。俳人になりてえ
  • Linuxカーネルソースコード」を読み解く たまたま見かけたので。ブートプロセスを取り上げた本もあったけどちょっと難しそうなのでこっちで慣れることにした。
  • インターネットフォレンジック 某氏に影響されて借りた。実例が載っているので良い。
  • 学んでみよう! 記号論 SAT/SMTソルバがここしばらくマイブームで、目次にCNFという文言があったので借りた。ポップなタイトルと表紙とは裏腹に中身はガチっぽい。

他にもシェル芸でCMSを作る本とか大じゃない方の熱血アセンブラ入門とかあったけど量が量なので見送り。

EasyCTF IV の MalDropper を解きたくてC#のデコンパイラを入れたいのにILSpyが動いてくれない。困った...

IOLの1次予選はとりあえず感想を紙に書き写して、解法も半分ぐらい書き終わった。これで伝わるといいんだけれど。
「1000字も書けねえ〜」とか言ってる割にはこの日記は1000字ぐらいあるんだよな。

Chocolate Cookie 解説

バレンタインの直前に思いついたので、チョコレートのパッケージに混入させてURL渡したりTwitterに投げてみたりしたんですが結局誰も解けなかった・解かなかったみたいです…難易度が高すぎただけなのか、はたまたエスパーだったのか…

問題

http://o0i.es/chocolate に置いてあります。

想定解法

開発者ツールなどでページのHTMLを見てみます。
まず<div id='message'>があり、<input type='checkbox'> が7x7のマスを構成しています。
その後に<span> が大量に配置されています。そしてその間に{が1つ配置されています。
checkboxをオンにすると色が濃くなってチョコチップっぽくなります。
適当にオンオフしていくと下の文字が変化したりしなかったりします。

しかし、ここには<script>が見当たりません。どのようにして<span>の文字を変えているのでしょうか?また、Here's a chocolate cookie...という文字列もHTMLファイルには記述されていません。どこから来ているのでしょうか?

ページタイトルに「CSS: Chocolate Sugoku Suki」とあることですし、CSSを見てみましょう。
style.cssrules.cssを読み込んでいるようです。

まずは前者から。先頭にいきなりFLAGの形式が書かれています。FLAG{s.........}ですね。
<div id='message'>の内容もここから来ています。
CSS--name: valueの形で変数を作ることができます。他のプロパティで参照するときはvar(--name)のようにして参照します。#0099ffなどだいたい何でも入れられます。

:root {
  --message: "Here's a chocolate cookie for you, find FLAG" /* FLAG{s.................} */ "!";
  --cacao: "C";
  --ushio: "h";
  --banana: "1";
}
 
...
 
#message::after {
  content: var(--message); 
}

続きを見てみましょう。

span:first-of-type::after {
  content: counter(f, upper-alpha);
}
 
span:first-of-type+*::after {
  content: counter(v, upper-alpha);
}
 
span:first-of-type+*+*::after {
  content: counter(j, upper-alpha);
}
 
span:first-of-type+*+*+*::after {
  content: counter(y, upper-alpha);
}
 
...
 
span:first-of-type+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*::after {
  content: counter(e, lower-alpha) var(--banana);
}
 
...
 
span:first-of-type+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*::after {
  content: '}';
}

span:first-of-typeでページ内の一番最初の<span>を選択し、隣接セレクタ+とユニバーサルセレクタ*を組み合わせて次の要素を取っています。
span:first-of-typeなら1番目、span:first-of-type+*なら2番目、span:first-of-type+*+*なら3番目…という感じです。
そしてそれの::after疑似要素・contentプロパティを使って何らかの文字を表示しています。実際に表示される文字はここで決定されるようです。

通常はcontent: "new!";のように文字列を使用することが多いですが、ここではcounter()を用いています。カウンタは、主に<li>でリスト表記をするときに番号を自動で割り振るために使われるものです。MDNが詳しいです。
デモも置いておきます。

たとえば1番目ではfカウンタの数値をupper-alpha、つまりアルファベットの大文字にして表示しています。何も指定しない場合は数字が出力されます。
途中でvar()を使ってはじめに定義した変数を表示している部分もあります。

これらを読んでいくと、<span>で表示されるそれぞれの文字は以下のカウンタの値と固定値で出来上がることになります。'で囲っているのが固定値です。

f v j y '{'(spanの間) g q(数値) h n l k(数値) c 'h'(--ushio) i o r 'C'(--cacao) p t d e '1'(--banana) s u(数値) '}'

fvjy{g.....}のカウンタの値を先程のFLAG{s......}と対応させることができればFLAGがわかるということです。

ゴールがわかったので、次にrules.cssを見てみましょう。
似たようなコードが繰り返されています。

input:nth-of-type(3):checked ~
input:nth-of-type(8):not(:checked) ~
input:nth-of-type(34):checked {
  counter-increment: h 3 g 1 r 3 f 1 k 2;
}
 
...

input:nth-of-type(N)でN番目のcheckboxを選択し、それぞれがON(:checked)かOFFかでスタイル(もはやスタイルではない)を適用するか決めています。
~はその要素以降の兄弟要素に対して適用されます。

この場合だと、「ONになっている3番目のcheckbox」の後ろに「OFFになっている8番目のcheckbox」があり、さらに後に「ONになっている34番目のcheckbox」がある場合に適用されます。
つまり、「3番目がON」かつ「8番目がOFF」かつ「34番目がON」ならば適用するという意味だとわかります(以降これをルールと呼びます)。

counter-incrementはその名の通りカウンタをインクリメントするのですが、後ろに数値を指定することで増加数を自由に変えられます。ここではh += 3, g += 1, r += 3, f += 1, k += 2という感じです(カウンタの中身はあくまで数値で、表示するときにアルファベットにしているだけです)。
試しに問題ページで3,8,34番目を操作してみると変化がわかりやすいと思います。

このrules.cssのすべてのルールに合うようにすればFLAGが出てくるのでしょうか?

…答えはNOです。
もういくつか見てみると以下のinput:nth-of-type(2)のように、互いに矛盾しているルールがあります。FLAG{sという文字列にするために使うルールと使わないルールがあり、その組み合わせを求める必要があります。

input:nth-of-type(2):not(:checked) ~
input:nth-of-type(39):checked ~
input:nth-of-type(44):not(:checked) {
  counter-increment: n 3 s 3 f 1 d 3;
}
 
input:nth-of-type(2):checked ~
input:nth-of-type(6):checked ~
input:nth-of-type(16):not(:checked) {
  counter-increment: p 2 f 1 k 2 j 3;
}

でもどうやって求めるのでしょうか?
全探索? O(249) = 562949953421312通りなので厳しいですね。

制約充足問題 で検索してみましょう! wikipediaを引用します。

制約充足問題(せいやくじゅうそくもんだい、英: Constraint satisfaction problem, CSP)は、複数の制約条件を満たすオブジェクトや状態を見つけるという数学の問題を指す

これの例としてよく挙げられるのは数独です。それぞれのマスを変数として、「ヨコの行・タテの列・3x3の正方形に1~9を1回ずつしか使えない」という制約を満たすような数字の入れ方を求める制約充足問題になります。
この数字を求める、つまり問題を解いてくれるスゴイものがSAT/SMTソルバと呼ばれるものです。
代表的なSATソルバにminisatがあります。SAT ソルバー 入門 がわかりやすいのでおすすめです。

ただ、SATソルバでは真偽の制約(aがtrue, bがfalse, かつcがfalse…)しか扱えないので直接扱うには大変な場合があります。対してSMTソルバは内部でSATソルバを呼び出しますが、整数の大小・「AならばB」などを制約として扱う構文を備えているのでSATよりもシンプルに書くことができます。
パズルをSugar制約ソルバーで解く も見てみると雰囲気がつかめると思います。

さて、それではこの問題にはどのような制約があるでしょうか?

  • 3つすべてのcheckboxが条件を満たしてはじめて、ルールが有効になり、それに応じてそれぞれのカウンタに加算する
    • 逆に、「ルールを使わないときは加算しない」「ルールで指定されていないカウンタには加算しない」(見落としがちです)
  • f v j y gカウンタの値はそれぞれF L A G sに対応する数値になる

この2つです。
1番目の制約は、たとえば以下のルールがあったとき

 input:nth-of-type(2):not(:checked) ~
 input:nth-of-type(39):checked ~
 input:nth-of-type(44):not(:checked) {
   counter-increment: n 3 s 3 f 1 d 3;
 }

このように変換できます(擬似コードです)。

rule_satisfied ← not(input[2]) and input[39] and not(input[44])
if rule_satisfied then n += 3, s += 3, f += 1, d += 3, (それ以外) += 0
if not rule_satisfied then (すべてのカウンタ) += 0

…と言いたいところですが、SMTソルバはtrue/falseで表現される制約を解くためのものなので、n += 3のように「変数に逐次値を足していってから比較する」ということができません。私もここで詰まり2日ほど考えた末「あとから全部まとめて和をとって比較する」ようにすればうまくいくことに気づきました。

具体的には以下のようにルールごとの増分を記録する配列を作り、制約をかけます(普通の代入とそっくりです)。

rule_satisfied ← not(input[2]) and input[39] and not(input[44])
if rule_satisfied then
  table[rule1][n] == 3, table[rule1][s] == 3, table[rule1][f] == 1, table[rule1][d] == 3,
  table[rule1][それ以外] == 0
if not rule_satisfied then table[rule1][すべてのカウンタ] == 0

そして、これを用いれば2番目の制約が表現できます。fカウンタの値はそれぞれのルールでの増分の和になるので、table[rule1][f] + table[rule2][f] + table[rule3][f] ... table[ruleN][f]として表現できます。

table[rule1][f] + table[rule2][f] + table[rule3][f] ... table[ruleN][f] == 'F'
table[rule1][v] + table[rule2][v] + table[rule3][v] ... table[ruleN][v] == 'L'
table[rule1][j] + table[rule2][j] + table[rule3][j] ... table[ruleN][j] == 'A'
table[rule1][y] + table[rule2][y] + table[rule3][y] ... table[ruleN][y] == 'G'
table[rule1][g] + table[rule2][g] + table[rule3][g] ... table[ruleN][g] == 's'

あとはこの2つをプログラムに落とし込むだけです!
私はz3というSMTソルバを使って解きました。GitHubにRubyでのコード例を載せています(あんまりきれいじゃないね…)。

実行するとFLAG{sという文字が現れるようなルールの組み合わせと、それらを満たすcheckboxのオンオフ、計算されたFLAGが出力されます。
実際のページでやってみると…うまくできました! FLAG{s0rry4Ch3apCh0co1at3}がFLAGです。

その他

  • 最初のバージョンではルールの数が20しかなく、O(220)で組み合わせるルールの全探索が可能でした
  • ルールを増やしたところ解が複数になってしまい削減できなかったため苦肉の策としてFLAGの1文字目を指定しました
    • これのせいで全探索の計算量減っちゃうかも?誰かおしえて
  • Xmas Contest 2017 I問題を解くために調べているときに思いつきました
  • CSSはチューリング完全