はるすえすしーのぶろぐ

ブログのないようがないよう

ICPC2022 国内予選 参加記

チームTUTankhamunとして参加し、4完45位(298チーム中)でした

順位表

チーム

チーム名 "TUTankhamun" の由来 ・・・ 大学の略称TUTと、ツタンカーメン王を掛けている。スペルが覚えられないことで有名。

メンバーはecasdqina、MATSUMAT、hals。AtCoder黄水緑のチーム。

エカスドクィナくんのみ、高専時代にICPC出場経験あり。

学部SlackでICPCのチームメンバーを募集していたが、さすがに直に参加希望を言い出す勇気はなく空リプをしていたら拾っていただけたというのが参加の経緯。

~本番まで

ICPC出場経験があるらしい学部の助教さんにコーチを頼み、ABCに出たりAOJ解いたりして感覚を取り戻しつつ練習してICPCまでを過ごした。

6/25に模擬国内予選があった。出てみたら2完(A, C)でさすがにこれはまずいねという話になり、ICPC本番には「とりあえずA~Dまでは全部読んで(エカスドクィナくんが)問題の割り振りを決め、分からなかったら相談してチームワーク大切にしよう」という作戦?を立てた。

対面して相談した方がやりやすいので、本番はエカスドクィナくんの部屋に集まって迎えた。

余談だが、頭を働かせるためにラムネとかあるといいかなと思って全員分買って行ったらエカスドクィナくんも黄金糖を買っていてちょっと面白かった。松くんは空のミンティアを持っていた。

本番

開始1時間前は全然余裕だったのに、だんだんとコンテスト参加の高揚感と、一問も貢献できなかったらどうしようという緊張感で震えていたら、本番が始まった。

とりあえずABCを順に読んでいく。A問題はそのまま解けそうなので、僕より早く解けそうな松くんに担当してもらうことに。

BCを読む。B問題はシミュレーションっぽいが、実装がめんどそう&バグらせが怖いということでエカスドクィナくんが担当。

とりあえずC問題を自分の頭で考える。なんとなくDPみたいな感じがするけど、必要な状態が多すぎて爆発しそう。かといってすべての場合で最善となる並べ方も思いつかない。

するとエカスドクィナくんからC問題の考察(n≥mならずっと練習→ずっと休息、n<mなら休息するたび練習日挟む)が投げられるので、実装に取り掛かる。

A問題AC (13:56)

13:56に松くんが難なくA問題をACし、D問題以降の先読みとエカスドクィナくんの手伝い(紙上シミュレーション)に移る。

C問題のプログラムがいったん完成するも、サンプルケースが全然合わない。よく見るとn<mでも正の値が出るケースがあるのでエカスドクィナくんに報告。

すぐにそのケースでの状態を考えてくれる。どうやら休息日を等分割し、休息日の間に1日練習日を挟み、余った練習日を最後に連続させるのがよさそう && 休息日の分割数は2分割~n-1分割までループで見ていくとよさそう、と考察が投げられる。分割数が決まればその場合の値は定数時間で求まるっぽい。

B問題AC (59:22)

59:22にエカスドクィナくんがB問題をACする。またしてもサンプルケースが合わないので見てもらう。n≥m, n<mの場合分けが不要であることを指摘してもらい、さらに分割数に対する計算式にして表してくれる。

D問題AC (1:31:50)

1:31:50にエカスドクィナくんがD問題をACする。僕はC問題の実装で悩んでいて一切見てないのでわからないが、DPらしい。この時点で遅めの3完だったので、どうしても4完したい。

C問題AC (1:42:29)

ほとんどサンプルケースが合うようになったので、エカスドクィナくんも合流しておかしいサンプルケースのときのプログラムの計算値を一行ずつ確かめていく。ここで、1分割のときに悪さをしていることに気づき、for文の開始条件を変更したらサンプルケースが全部合うようになる。

データ1提出してCorrect Answer、データ2提出してCongratulation! 表示を見て思わず声が出る。1:42:29にC問題をACして4完に。この時点では33位とかだった気がする。

豊橋技科大から出ているチームが1チームしかないので、おそらく4完であれば国内予選通過できそうで一安心する(後から見ると、4完学内1位でも順位が10位下だったらかなり厳しそうだった)。

~終了

E問題に取り掛かる。グリッド構築っぽい。+と-を交互に並べて四隅を調整すればいけそう(らしい)ので、エカスドクィナくんが実装を開始するも、場合分けが多すぎるなどで断念。

G問題は構文解析が必要そうだが、そもそも構文解析が分からない上に構文解析をして何をすればいいのかが分からない。それ以降も何もわからない。

結局40分ほどは順位表を眺め、一方的に知っている競プロerのチームを応援したり、tonosamaの全完を応援したりして過ごした。ちょくちょく合計時間が少ないチームに順位が抜かれて、ちょっと不安になっていた。

国内予選を終えて

TUTankhamunは国内予選通過っぽい。やったー!12/27~28 Yokohama Regionalだ!(豊橋技科大としては2019年以来らしい)

僕のせいで予選通過ならずだったらどうしようと前日の夜は眠れなかったので、杞憂で良かったと本気で安堵した。

参加してみて、エカスドクィナくんの負担が大きすぎるので早急につよくなる(得意分野を作る)必要を感じた。3人目のマスコット枠ではないので。

終了後、お疲れ様会ということで来来亭に行った。勝ちの味がした。

ラーメン屋なのに機械があった。

高専生活振り返り

まえおき

まぁじです。3/31までに1~5年生の高専生活を振り返ろうと思ったら、ギリギリ日付が変わってしまいました申し訳ございません。


1年生

2017年4月に高専の電子情報工学科に入学しました。
高専では入学して2日後とかに泊りのオリエンテーションがあるのですが、そこで高専にデュフフオタクよりも一般人や陽の民の方が多いことに気づきました。まぁ一般人や陽キャに見えても実はオタクだったり、そもそも高専外に出れば一般人以下の人権しかなかったりしますけど

部活は友人に紹介してもらって ほぼ字面のかっこよさだけで IT研究会に入りました。たぶん少しプログラミングができるようになってゲームでも作りたいなと思っていた気がしますが、ゲーム作りの大変さを完全に舐めていますね。
入部して1ヶ月で新入部員への教育が一切行われなくなってしまい、先輩たちから何も返信が来なくなったので幽霊部員になりました。結局Processingを使ってfor文を書けるようになったくらいには成長しました。

勉強に関しては、2回目のテストで物理と専門基礎の科目で赤点を取ってしまい、どうやって親に隠すか戦々恐々としていました。2進数の負数を含む計算が一切理解できなくて本当に絶望した覚えがあります。最終成績は文系科目でカバーしてクラス2位でした。

GWぐらいからTwitterを始めたのですが、周りの人間がオタク内弁慶ツイ廃陰キャでそれに合わせてたら いつの間にかツイートしない方法を忘れてしまいました
リアルから「うるさい」「ミュートした」「Twitterやめろ」、フォロワーから「どうやったらそんなツイートできるんw」「ふぁぼ爆えぐすぎw」などと声を掛けられる日々が続きました。結局5年間Twitterはやめられませんでした。


2年生

高専では1年生が学科混合クラス、2年生~が学科でずっと同じなのでいわゆる最後のクラス替えでした。本当に席の周りに仲良い人間がおらず、Twitterでフォロワーであり少しだけ喋ったことがあったいなみちゃんとずーっと一緒にいました。

Twitterのアカウントを分けてまぁじ(@Hals_SC)が誕生したのもこの頃です。kosen17sに所属したり・一日で300ツイートしたり・高専新入生のフリをしたり・下級生の高専女子に積極的に絡みに行ったり・かわいいbotになったり・バズったり・先輩に怒られたり、Twitterにドハマりしました。

このせいで口を開けば強い否定の言葉と、「○○、~~なんだよな」という定型文しか喋れなくなり人間として退化しました。でも愉快なフォロワーはできたし歪んだインターネットリテラシーを身に着けることができたと実感しています。

Twitterサイコー!高専生はみんなTwitterをやって破滅しろ!クラスメイトから虐められて「でも僕にはよく絡んでくれるフォロワーの女の子がいるし…」とか思ってたらその子に大してかっこよくもない彼氏が出来て絶望しろ!所詮キモいけどまぁ絡んでやるか程度の仲だったことを実感しろ!

失礼しました。ちなみに2年生のお盆後あたりからバイトを始めたら店長が高専卒のブラックバイトで「バイトつらい」と「いらっしゃいませー!」しか喋れなくなり、やめたいと伝えても籍だけは置いといてくれないかと懇願され、結局3年生になってもGWやらお盆やら正月はバイトしてました。辞めれたのは正月終わってからです。


3年生

周りの普通高校生が受験で精神ワタワタ身体クタクタだったのを嘲笑いつつ、脳内では普通高校に進学したら…とありもしない妄想を考えて劣等感を抱いていたような気もします。
あと18歳という一つの境目を迎えて何か変わるのかと思いきや、家にずっといる陰キャから免許だけある陰キャに進化しただけでした。

部活に関しては、完全に幽霊部活と化していたIT研究会を潰し、先生やクラスメイトとともにプログラミング研究会という部活を立ち上げました。プロ研のメンバーとともにPCKやHITや起業家甲子園などいくつかコンテストに出場し、チームでの作業の難しさを実感しましたし成果物を認めてもらい賞をいただく嬉しさを知りました。まぁほとんどリーダーがやってくれたので私の仕事はなかったんですけど。

高専では3年生に研修旅行(前半がクラス全体での企業見学、後半が各グループに分かれての自由旅行)があり、私の学科は東京に行きました。将来はなんでもある大都会で大企業に勤めて適当にお金貰いたいな~とかいう漠然とした将来の目標を抱き、東京ディズニーランドやら長岡技科大(なぜ?)やら箱根やらを満喫して帰りました。東京着いたからフォロワー1人くらいエンカしてくれないかなぁとツイートしたら誰も来てくれず、泣きながらツイートを消して鍵垢にしました。そこからフォロワーは信用していません


4年生

今でも感染拡大が続いている新型コロナウイルス感染症(COVID-19)により、対面授業はすべてオンラインになりインターン高専祭等は総じて中止となりました。
学校行かなくていいのとか体育祭がないのとかは正直すっごい助かったんですが課題の量が多すぎて脳が爆発し、長時間集中力を保たせるのが非常に困難な体になってしまいました。一番狂った1年間だったと思います。

高専プロコンにも一応本選出場しました。
ほかの高専の発表を聞いた私は「ほへ~やっぱ高専生ってすげ~~… (自分除く)」になりました。結果として惨敗だったのですが、ほかのコンテストに持っていったら最優秀賞取れたので校長賞ももらいました。もう二度と高専プロコンに関わりたくないなというのが今の感想です(次の年の茨城高専チームでのいざこざも含め)。

あと、中学3年生から付き合ってきた彼女と別れました。


5年生

編入に関してやりたいことはあれども漠然としており、そして4年生でだらけ癖がついてしまった私には何か月も勉強し続けて本番が一回勝負で決まるなんて怖すぎて選べませんでした(家の問題もありましたが)。結局推薦で高専延長戦大学にいくことにし、無事合格しました。

卒研は担当教員もテーマも希望通りで、早めに編入試験を終えたので5年生のかなり多くの時間を卒研に取り組んでいたと思います。
ただし先輩からの引継ぎメモが一切役に立たなかったりひとつの課題を何とか解決すると教員から2,3個課題が降ってきたりと大半はラズパイの前でウーウー唸ってました。
教員からの勧めで研究会発表を行って研究奨励賞をいただき、またレター投稿を行って採録されたのは情報系の人の役に立つ研究を続けていきたいというモチベになりました。


おわりに

黎明期のVtuberにハマって古参面したり、Twitterに毒されてコミュニケーションが取れなくなったり、インターネットで知り合った女に生活を破壊されたり(誇大)、爆破予告で休校になったり、大雪×2でも休校になったり、シャニマスを好きになってかわいいしか言えなくなったり、軽率にツイートして先輩方からお𠮟りを受けたり、高専界隈に加わって口出して中心に入れたような気がしたり、拾い画ツイートでバズったり、令和になる際にネタツイをしたら公式モーメントで取り上げられたり、競技プログラミングに入れ込んで周りの友達に布教したらレーティング抜かれて凹んだり、ブラックバイトに勤めてしまい精神がゴリゴリ削られて辞めたくても辞められなかったり、高専祭実行委員になって裏方から支えたり、部活を立ち上げてコンテストに出場したり、コロナで2年以上潰されたり、研究会で汗ダラダラになりながら発表して痛いところを偉い先生に質問されて焦ったり、フォロワーたちが三角関係になって巻き込まれたり、友達が急に釣り垢始めて腹切れって言われたり、卒業式で優秀学生として表彰されたり、とにかくたくさんすべて違う方向の経験ができた濃い5年間だったと思います。こう見るとTwitterが思い出の半分を占めている気がしますが…。

Hals_SCは高専タツイでできているといっても過言ではないため、これからTwitterをやっていけるか不安です。なんだったらまだ夏休み明けとか高専に向かいそうな気がしています。高専在校生のみんなー!まだまぁじくんに絡んでくれるかなー!?

ピコピーン!

f:id:halss:20220401001540p:plain


ああすみませんもうやめます……高専と、関わってくれたみなさんありがとうございました……これからはコンテンツ性をもっと磨いて子供部屋ネタツイおじさんになろうと思います。

新しいノートPCを買いました

まえおき

まぁじです。大学に行くのでそろそろ新しいノートPCが欲しくなってきました。

今まで使ってたやつ

高専2年の冬休みにノートPCを購入し、今まで使ってきたので3年間お世話になったことになります。 ちなみにスペックはintel Core i3(8世代)、メモリ8GB、SSD 128GB+HDD 1TBのHP Pavilion 15インチです。1.9kgあります。
(Pavilion 15-cs0 HP Pavilion 15-cs0021TU ベーシックモデルらしい)

要件

13インチで軽い(15インチ/約2kgは重い)、i5 or Ryzen5以上(目安として大学在学中は使えそうなレベル)、メモリ8GB以上(できれば16GB)、SSD 512GB or 1TB、予算10万円ぐらい

で探しました。最初は色々なサイトをはしごして、LenovoのYoga SlimやらThinkpadやら比較したりしてたんですが探すのが面倒になったのとHP社で下取りしてくれるっぽいんでHPに限って探すことにしました。HPの下取りプログラムに関してはメインページに書かれていないんですがここに書いてあります。→https://jp.ext.hp.com/campaign/personal/others/replace/


そしてHPの公式サイトで出会いました。

HP ENVY x360 13-ay くんに……!

HPのノートPCの中で最上位モデルであるENVY!ぐるりと回るコンバーチブルディスプレイ!Ryzen5以上搭載!1.25kgの軽さ!そしてデザインがかっこいい!(これが…親バカ??)

というわけで、主にデザインに一目惚れして購入することにしました。ちなみに最後の最後まで0.99kgの軽量モデルであるHP Pavilion Aeroと迷ってました。HPのノートPCのランクはSpectre(マスターピース) > ENVY(プレミアム) > Pavilion(スタンダード) > 無印(エントリー)です。

できるだけ安く買いたい!!

どうせなら10万円以下で買いたいので(結局買えなかったんですが)、セールやクーポンその他お得情報を漁った結果

HPの学割(44000円オフ) < 週末限定セール(47000円オフ) < 価格ドットコム限定モデル(50400円オフ)

だということに気づきました。価格ドットコム限定モデルに関してはこのページもしくは価格ドットコムから見れます。だいたい一番お得です。

さらにいろんなサイトを巡ると、「10万円以上の購入で5%オフ!」みたいなクーポンも拾ってこれるのでこれを拾ってきて適用します。

僕の場合は3年間延長保証や公式スリーブも勢いでつけたので、総額で125,360円でした。高。

とどいた

口座からお金が引き落とされる音を聞きながら、到着を待ちます。

即納モデルなので、7日ほどで届きました。HPのロゴを見た瞬間にテンションが上がります。

はいかっこいいー!!!!!!!!!!!!!!!画像ではちょっと明るく見えるけどマットブラックで最高!!ここから一生愛し合っていこうね…!

ヒンジにENVYって書いてあるんですよ!前からも後ろからもENVYを誇れるってワケ!

おわりに

最終的に購入したのは

HP ENVY x360 13-ay1000の
CPUがAMD Ryzen 7 5800U モバイル・プロセッサー,
ストレージが1TB SSD (PCIe NVMe M.2),
メモリが16GB オンボード,
グラフィックスはプロセッサ搭載のAMD Radeon(らしい)

です。リンクはこっちから。

ノートPC買うぐらいならデスクトップ買ってもいいのでは?みたいな値段になったんですけど、まぁかっこいいから無問題。YouTubeで音楽流しながらVSCodeでプログラミングしながらAtCoder Problems開いてもファンファン言いません。

所感として、持ち運びは楽々で指紋認証もスピーディなんですが、ちょっとまぶしい気がするのと黒い画面だと僕の顔ががっつり映り込みます。物理カメラオフスイッチやミュートが手軽なのはいいですね。あとEnterキーたちのさらに隣にhome / pg up / pg dn / end キーがあるのはだいぶ邪魔なので、KeySwapソフトつかって消してます。

このブログもHP ENVYくん使って書きました。これからがんばろうね。

GitHub Pagesを使ってカスタムドメインを設定する (+Gandi.netのDNSレコード設定について)

こんにちは。まぁじです。

前回はGandi.netを使って独自ドメイン『hals.one』を取得しました。⇒Gandi.netで独自ドメイン『hals.one』を取得した - はるすえすしーのぶろぐ

ドメイン名を取得しただけでは自由にサイト運営とかはできません。おそらく取得したドメインにアクセスすると [your domain].oooは既にGandi.netによって登録されています。 みたいなページに飛ぶかと思います。スクショは撮り忘れました。

とりあえず無料で、形のあるサイトを簡単に使いたいなら、GitHubリポジトリを作成するだけで簡単に静的サイトのホスティングできるGitHub Pagesを使うのがいいと思います。今回はGitHub Pagesを使って独自ドメイン(今回は hals.one )に静的サイトをホスティングさせてみます。

GitHub Pagesとは

GitHub Pages Docsによると

GitHub Pages is a static site hosting service that takes HTML, CSS, and JavaScript files straight from a repository on GitHub, optionally runs the files through a build process, and publishes a website.
訳: GitHub Pages は、GitHub上のリポジトリからHTML、CSSJavaScript のファイルを直接取得し、オプションでビルドプロセスを実行し、ウェブサイトを公開する静的サイトホスティングサービスです。

You can host your site on GitHub's github.io domain or your own custom domain. For more information, see "Using a custom domain with GitHub Pages."
訳: GitHubgithub.ioドメインや独自のカスタムドメインでサイトをホストすることができます。詳しくは、"Using a custom domain with GitHub Pages" をご覧ください。

というわけで、HTML・JS・CSSからなる静的サイトをホスティングしてくれるサービスで、デフォルトはgithub.ioドメインで公開されるってことらしいです。
じゃあ作成していきましょう。

GitHubリポジトリの作成

GitHubのアカウントを作成/ログインします。以下GUIで操作しますが、CUIで操作できた方がいいと思います。"git Windows"とか"git VSCode"とかで検索してみてください。

f:id:halss:20220305221739p:plain

Newボタンを押して新しいリポジトリを作成します。リポジトリ名はあなたのドメイン名とかmy-siteなどわかりやすいものがいいです。
リポジトリはPublicにしないといけなかった気がするので、Publicにします。他にこだわりがなければそのまま「Create repository」ボタンを押します。

f:id:halss:20220305222235p:plain

すると空っぽのリポジトリが生成されるので、https://github.com/[your account]/[repository name]/new/mainにアクセスしてGUIから、もしくはコマンドラインからindex.htmlを作成してcommit, pushします。

GUIから

ファイル名にindex.htmlを指定し、HTMLをちょろっと書きます。

f:id:halss:20220305223941p:plain

書けたらコミットしてやります。詳細は空欄でいいですがコミット名は一応埋めておきます。するとリポジトリにindex.htmlが追加されます。

f:id:halss:20220305224049p:plain

コマンドラインから

公式を参考にするとこんな感じです。

echo "<h1>Welcome to my website!</h1>" >> index.html
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/[your account]/[repository name].git
git push -u origin main

GitHub Pagesを有効化

最低限のHTMLが用意出来たら、リポジトリのSettings>Pagesに移動します。

f:id:halss:20220305224840p:plain

Pagesのソース(どのブランチ・ディレクトリを発行するか)を選べます。今回はブランチはmain、ディレクトリはrootを指定します。
Saveボタンで保存し発行に取り掛かってくれます。

f:id:halss:20220305225113p:plain

10秒もしないうちにサイトが[your account].github.ioもしくは[your account].github.io/[repository name]に発行されると思います。

f:id:halss:20220305225606p:plain
雑なつくり

カスタムドメイン設定

github.ioにサイト生成されていることを確認したら、Cusstom Domainの入力欄にあなたの独自ドメインを入力します。ただし必ずwwwを付けてください。僕が調べた限りではwwwがないとちゃんとカスタムドメイン設定できないです。

f:id:halss:20220305225758p:plain f:id:halss:20220305230326p:plain

保存したらGandi.netの方のDNSレコードサイトに移動します。

f:id:halss:20220305234032p:plain

テキストモードにしてDNSレコードをいくつか編集します。念のためバックアップを取得しておくといいです。 How to set up DNS records on gandi.net to use a custom domain on Github Pages · GitHubを参考にDNSレコードを編集します。

DNSレコード 追加・削除
@ 1800 IN A 185.199.108.153 追加
@ 1800 IN A 185.199.109.153 追加
@ 1800 IN A 185.199.110.153 追加
@ 1800 IN A 185.199.111.153 追加
@ 10800 IN A 217.70.184.38 削除
www 10800 IN CNAME [your account].github.io. 追加
www 1800 IN CNAME webredir.vip.gandi.net. 削除

ゾーンファイルを保存したらDNSレコードが保存されるかと思います。

少し時間はかかりますが、http://www.[your domain].ooohttps://www.[your domain].oooにアクセスするとindex.htmlの内容が表示されてるかと思います。多分。 今後はGitHubリポジトリにコミットするとあなたのサイトが更新されます。

ちなみにPagesの設定でHTTPSを有効化することもできます。ただし1日くらいかかるみたいです。 f:id:halss:20220305233144p:plain

おわりに

独自ドメインに静的サイトを生成するやり方を書きました。GitHub Pagesは静的サイトのみですしリポジトリ内容が他人から見えてしまうので、アクティヴでクリエイティヴなサイトが作りたいのであればReactとかNuxtとか考えなきゃいけないんですかね?(今のところはp5.jsを導入して背景を動かしてるだけ)

面白いサイトを作るセンスをください、さようなら

Gandi.netで独自ドメイン『hals.one』を取得した

おひさしぶりです。まぁじです。

Twitterでつよつよ人間(人間かも怪しい)のプロフィールを見ていると

会社/言語/言語/言語/スキル/スキル/フロントorバックエンド/実績/実績
📍つよつよ企業 🔗つよつよ.dev

みたいな感じで目が滑るまぶしすぎて見れないほどの実績とスキルがたくさん並んでませんか?さらにURL欄に自分のドメインが貼ってあるのうらやましくなりませんか?僕はめちゃくちゃ羨ましいです。

てことでGandi.netを使って「hals.one」っていう独自ドメインを取得しました。 まだ何にも整備してないです。あと2023年以降にはリンク切れしてるかもしれないです。

なんでGandi.netなの

お名前.comとかGoogle DomainsとかXdomainとかNameCheapとかドメイン取得サービスは色々あるんですが、

  • ある程度安い
  • 新規契約料金と更新料金が見やすいところにある
  • メールサーバが無料で2つついてくる
  • 契約後に大量のセールスメールが来ることがない(これは某.comですが)
  • 無料でwhois情報公開代行(デフォルト)やDNSSECができる

という理由でGandi.netを選びました。メールサーバ欲しいもんね。

ドメイン名取得方法

ドメイン名を探す

https://www.gandi.net/ja にアクセスします。シンプルでいいですね。

f:id:halss:20220220154227p:plain
Gandi.net トップページ

入力欄にTLD (トップレベルドメイン=.com / .dev / .one など)を入力するとその説明や料金が見れます。

f:id:halss:20220220154711p:plain
.oneの説明
f:id:halss:20220220154741p:plain
.oneの料金

もしくは入力欄にドメイン名にしたい文字列だけ打ち込むと、TLDをいろいろ表示してくれます。カートボタンを押すとカートに追加できます。

  • ○○円 / 年の場合は初回取得・更新で同じ値段がかかります。
  • ○○ 円 1年間 | 翌年度以降 ×× 円 / 年の場合は初回取得が○○円で、更新するのに××円かかります。

ccTLD(国別トップレベルドメイン=.fr / .jpとか)や個別に条件があるもの、また翌年度以降の価格がすごく高いものはやめておいた方がいいかもです。 f:id:halss:20220220161709p:plain

友達紹介プログラムを使う

Gandi.netには友達紹介プログラムがあり、 紹介リンクを生成して送信

リンクを踏むと
初年度のドメイン取得料金が20%オフ
ホスティングが6カ月間75%オフ


これを使って購入すると送信した側にも650円ほどのクーポンがもらえます。
アカウントの作成だけで招待リンクが作成でき、アカウント作成自体もメールアドレスのみでいいので誰かに招待してもらうといいでしょう。僕に言ってくれたらやります(Twitter)。

f:id:halss:20220220162609p:plain

カートに追加

招待リンクを貰ってサイトに飛んだら、メールアドレス・パスワード・アカウント名を入力してGandi.netに登録orログインします。

次に欲しいドメイン名を検索してカートに追加し、支払いに進みます。多分住所や姓名(ローマ字)が必要になると思います。この時点ではまだクレカ情報は求められません。

ここで取得するドメイン名・登録期間・利用規約・料金などを確認設定できます。画像ではha1s.oneというドメイン名を取得しようとしてます。 デフォルト設定では期間が「1年間」、自動更新はオフになっています。

f:id:halss:20220220164131p:plain

例えば2022/2/20に1292円で取得したとすると、1年後の2023/2/20の少し前(通知は30日前とか)までに更新するかどうかを選択し、更新する場合はさらに追加で1292円(※取得料金と異なる場合もある)支払う必要があります。

期間を例えば2年間に変更すると、2年分の料金2584円を一括で支払って2024/2/20まで自分のものです。

自動更新をオンにすると、更新期日に登録しておいた請求先から自動で引き落としされ、ドメインの利用時間が延長されます。

友達紹介プログラムでは1年間でしか新規取得できないので、デフォルト設定のままで購入しましょう。

支払方法を選択

支払方法は、PayPal、銀行振込、暗号通貨、クレジットカードから選択できます。
クレジットカードの種類はVisa、MasterCard、American Express、JCB、Maestroです。
ちなみに↑のICチップがついているならデビットカードでもいけました。

f:id:halss:20220220170313p:plain

「クレジットカードで支払う」ボタンを押すとカード番号とかを選択する画面に遷移します。

f:id:halss:20220220170651p:plain

入力して支払いを確定すれば購入完了です。

f:id:halss:20220220171900p:plain
請求書

https://admin.gandi.net/domain/にアクセスするとドメイン名が登録できていることが分かります。

f:id:halss:20220220205259p:plain

ドメインの各種設定

ドメイン名をクリックすればドメインの各種設定ができます。

f:id:halss:20220220205512p:plain

初めはメールが「無効な状態」になっていますがメールボックスタブを押してメールを有効化します。

無料で3GBのメールボックスを2つ設定可能です。

f:id:halss:20220220210335p:plain

メアドとパスワードの設定が必須で、エイリアスはいくつでも設定可能です。
エイリアスはいわゆる転送設定みたいなもので、me[@]hals.oneエイリアスhalssc[@]hals.oneを設定すると、後者に届いたメールが前者のメールボックスに転送されます。 パスワード、エイリアスは後から変更可能です。

f:id:halss:20220220210641p:plain

リダイレクト設定

また、リダイレクト/サブドメイン設定タブからリダイレクトを無限に?設定できます。 http➞https、wwwあるなしの永続的リダイレクト設定しておくといい…と思います。

ただ、httpsを含んだリダイレクト設定しようとすると毎回無料SSL証明書を発行しようとして通知が大変なことになりますが、1時間も待てば直ると思います。

おわりに

今はGitHub Pagesでカスタムドメインに静的ページを発行して表示させています。
それはまた今度書けたらいいなと思います。

Gandi.netで発行したカスタムドメインGitHub Pagesで発行する方法はhttps://pages.github.com/How to set up DNS records on gandi.net to use a custom domain on Github Pages · GitHubを参考にしました。

ところで、かっこいいJSライブラリとかCSSとかテンプレートとかありませんか? 本当に何もなくて困っています。⇩ f:id:halss:20220220213942p:plain

NITIC_CTF_2 writeup

NITIC CTF(36h, 9/5 12時~9/6 24時)に1人で参加して1701ポイントで62位でした~。
今までcpawCTFとかpicoCTFはやったことあったけど、リアルタイムでのコンテストは初めてだった。

f:id:halss:20210907231224p:plain

f:id:halss:20210907231245p:plain

f:id:halss:20210907231309p:plain

初めてのwriteupです。

▶目次

Web

web_meta (100pt)

ブラウザから覗いても何もないけど、拡張ツール開いてみるとflag is ...って書いてある。

▶Flag

nitic_ctf{You_can_see_dev_too1!}

long flag (200pt)

Flagがありそうだけど表示されてないっぽいので拡張ツール開いてpタグの中を見る。 <span>n</span><span>i</span>...とたくさん書いてあるので全部コピーして置換ツールとかで消去する。

▶Flag

nitic_ctf{Jy!Hxj$RdB$uA,b$uM.bN7AidL6qe4gkrB9dMU-jY8KU828ByP9E#YDi9byaF4sQ-p/835r26MT!QwWWM|c!ia(ynt48hBs&-,|3}

Pwn

pwn monster 1 (100pt)

netcatを使ってnc 35.200.120.35 9001にアクセスするとポ〇モンバトル的なのが始まる。 自分のモンスターのHP/ATKは100/10なのに相手のHP/ATKは9999/9999とめっちゃ不利、普通に負ける。 名前入力の際に長い文字列をぶち込んでやればスタックを破壊してHP/ATKを最強にできるので、勝つ。 (monster 2のATKをマイナスにすると敵を回復させすぎて死ぬって解説面白い、解けなかったんだけども…)

▶Flag

nitic_ctf{We1c0me_t0_pwn_w0r1d!}

Misc

Excel (100pt)

配布されたエクセルファイル開いて、Ctrl+Fで「nitic」で検索するとU869にフラグがある。

▶Flag

nitic_ctf{plz_find_me}

image_conv (200pt)

nitic_ctf{ }とだけ書かれたpngファイルが配布される。
最初$ file after_flag.pngとかしてたけど唐突にペイントツールとかで塗りつぶしたらフラグ出てきた。

▶Flag

nitic_ctf{high_contrast}

Rev

protected (200pt)

$ file challすると実行ファイルらしいので実行してみるとパスワード聞かれる。合ってるとFlagがもらえるっぽい。$ strings challするとsUp3r_s3Cr37_P4s5w0Rdという怪しい文字列が出てくるのでパスワードとして入力するとフラグが得られる。
やらかし大臣なのでnitic_ctf{sUp3r_s3Cr37_P4s5w0Rd}をして1WA…

▶Flag

nitic_ctf{hardcode_secret}

Crypto

Caesar Cipher (100pt)

暗号文fdhvdurot13.comで適当に試していくとフラグを見つけられる。タイトル通り。

▶Flag

nitic_ctf{caesar}

ord_xor (300pt)

Pythonファイルとテキストファイルが配布される。テキストファイルの中身はnhtjcZcsfroydRx`rl。 XORは2回繰り返すと元に戻るので、os.environ[“FLAG”]をテキストファイルの中身に入れ替えるだけでフラグが得られる。

import os
flag = ""
with open("./flag","r") as f:
    flag=f.read()

def xor(c: str, n: int) -> str:
    temp = ord(c)
    for _ in range(n):
        temp ^= n
    return chr(temp)

dec_flag = ""
for i in range(len(flag)):
    dec_flag += xor(flag[i], i)
print(dec_flag)

▶Flag

nitic_ctf{ord_xor}

もしかしてnanigasi_sanはFlagを作るのが下手なんですか?

tanitu_kanji (300pt)

Pythonファイルとテキストファイルが配布される。テキストファイルの中身はl0d0pipdave0dia244im6fsp8xPythonファイルは10文字の暗号化形式formatとFLAGを環境変数から取り出し、formatのi番目が”1”ならalphabets→after1、それ以外ならalphabets→after2に変換しているらしい。 復号化はformatを210通りをbit全探索でやってみてafter1→alphabetsとafter2→alphabetsを試す。

import os
alphabets = "abcdefghijklmnopqrstuvwxyz0123456789{}_"
after1 = "fl38ztrx6q027k9e5su}dwp{o_bynhm14aicjgv"
after2 = "rho5b3k17pi_eytm2f94ujxsdvgcwl{}a086znq"

with open("./flag","r") as f:
    flag = f.read()

def reconv(s: str, table: str) -> str:
    res = ""
    for c in s:
        i = table.index(c)
        res += alphabets[i]
    return res

for bit in range(1<<10):
    dec_flag = flag
    format = ""
    for j in range(10):
        if (bit & (1<<j)):
            format += "1"
        else:
            format += "0"

    for f in format:
        if f == "1":
            dec_flag = reconv(dec_flag, after1)
        else:
            dec_flag = reconv(dec_flag, after2)

    if dec_flag[0:9]=="nitic_ctf":
        print(dec_flag)

▶Flag

nitic_ctf{bit_full_search}

解けなかったやつ

300pt : password(+fixed), pwn monster 2~3, braincheck, report or repeat, summeRSA
500pt : Is it Shell?, baby_IO_jail

ちょっと難しいレベルの問題から上の知識が一切なかったので撃沈。

summeRSA (300pt)

RSA暗号で暗号化された文cと公開鍵e,Nが与えられる。平文mがthe magic words are squeamish ossifrage. nitic_ctf{〇〇}でありFlagの中身は7文字であることがわかっている。 7文字全通り試してe乗してmod Nをとった結果がcと一致したらOK!みたいな脳筋コード書いたけどとけなかった。 Coppersmith’s Attackは検索したけど実装できなくて死

using Primes
function main()
    N = 139144195401291376287432009135228874425906733339426085480096768612837545660658559348449396096584313866982260011758274989304926271873352624836198271884781766711699496632003696533876991489994309382490275105164083576984076280280260628564972594554145121126951093422224357162795787221356643193605502890359266274703
    e = 7
    c = 137521057527189103425088525975824332594464447341686435497842858970204288096642253643188900933280120164271302965028579612429478072395471160529450860859037613781224232824152167212723936798704535757693154000462881802337540760439603751547377768669766050202387684717051899243124941875016108930932782472616565122310

    ans = "the magic words are squeamish ossifrage. nitic_ctf{"
    abc = "!\"#\$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[/]^_`abcdefghijklmnopqrstuvwxyz{|}~"
    len = length(abc)
    for i in 1:len,j in 1:len,k in 1:len,l in 1:len,n in 1:len,m in 1:len,o in 1:len
        res = join([ans,abc[i],abc[j],abc[k],abc[l],abc[n],abc[m],abc[o],"}"])
        m_res = parse(BigInt, bytes2hex(Vector{UInt8}(res)), base=16)
        if m_res^e % N == c
            println(hex2bytes(string(m_res, base=16)))
            return
        end
    end
end

main()

感想・反省?

(そもそもwriteupって感想書いていいものなのかよくわからないけど…)
nanigasi_sanをはじめ茨城高専の運営の皆さんお疲れさまでした。自分としては、CTFに親しみを持たせつつ学ばないといけない事柄を示してくれるコンテストで有難かったです。
反省は、Ghidraの使い方忘れて逆コンパイルはできないわ、RSA暗号の解き方がわかっても実装できないわ、nanigasi_sanの300点しか解けないわで慌てすぎてTwitterしかすることがなくなってました。反省します。

【Julia】ABC198-D "Send More Money"

問題ページ - ACコード

制約きっっっっっっっっつ…20敗 f:id:halss:20210509231225p:plain

解き方(簡単なやつ)

まず覆面算に使われているアルファベットがいくつあるかカウントし、10個より多かったらUNSOLVABLEと出力。
次にDFSで各アルファベットにどの数字を割り当てるか探索しチェック、見つかったらそれを変換して終了。 詳しいやり方ははまやんさんのユーザ解説を読むといいと思う。

普通に書いてみる

 _____ _     _____
|_   _| |   | ____|
  | | | |   |  _|
  | | | |___| |___
  |_| |_____|_____| 残念!

考えたこと

  • 型注釈をとりあえず全部のローカル変数につける
  • 関数の引数をできるだけ減らす
  • 辞書を配列に書き換える
  • 時間計測して4.5secくらいかかってたらその時点でUNSOLVABLEする→失敗
  • for文の順番を1:10から10:-1:1に変更する→失敗
  • よくアクセスするインデックスを変数に保存しておく
  • ソースコード内でかわいくお願い♡する→成功?
  • 人力ループアンローリングする→成功
  • 成立しないときは早めに枝刈りする

おわりに

数か月ぶりに競プロしたら異次元になっててつらかった ペナ記録最多更新したかもしれん アスキーコードはLinuxにfiglet入れてやりました

ACコード

#        _                          _    ____   _
#  _ __ | | ___  __ _ ___  ___     / \  / ___| | |
# | '_ \| |/ _ \/ _` / __|/ _ \   / _ \| |     | |
# | |_) | |  __/ (_| \__ \  __/  / ___ \ |___  |_|
# | .__/|_|\___|\__,_|___/\___| /_/   \_\____| (_)
# |_|

# ----------solution----------
function main()
    s1,s2,s3=input(),input(),input()
    s11,s21,s31=s1[1],s2[1],s3[1]
    d::Vector{Char}=fill(' ',26)
    used::Vector{Char}=fill(' ',10)
    chara::Vector{Char}=sort(unique(s1*s2*s3))
    l::Int=length(chara)
    if l>10
        println("UNSOLVABLE")
        return
    end
    function check()
        # for i=10:-1:1
        #  used[i]!=' ' && (d[used[i]-'a'+1]='0'+i-1)
        # end
        if used[1]!=' '
            d[used[1]-'a'+1]='0'
        end
        if used[2]!=' '
            d[used[2]-'a'+1]='1'
        end
        if used[3]!=' '
            d[used[3]-'a'+1]='2'
        end
        if used[4]!=' '
            d[used[4]-'a'+1]='3'
        end
        if used[5]!=' '
            d[used[5]-'a'+1]='4'
        end
        if used[6]!=' '
            d[used[6]-'a'+1]='5'
        end
        if used[7]!=' '
            d[used[7]-'a'+1]='6'
        end
        if used[8]!=' '
            d[used[8]-'a'+1]='7'
        end
        if used[9]!=' '
            d[used[9]-'a'+1]='8'
        end
        if used[10]!=' '
            d[used[10]-'a'+1]='9'
        end
        if d[s11-'a'+1]=='0' || d[s21-'a'+1]=='0' || d[s31-'a'+1]=='0'
            return false
        end
        i1::Int=int(join([d[i-'a'+1] for i=s1]))
        i2::Int=int(join([d[i-'a'+1] for i=s2]))
        i3::Int=int(join([d[i-'a'+1] for i=s3]))
        if i1+i2!=i3 || iszero(i1) || iszero(i2) || iszero(i3)
            return false
        end
        println(i1)
        println(i2)
        println(i3)
        return true
    end
    function dfs(n::Int)
        if n==l+1
            return check()
        end
        for i=10:-1:1
            if used[i]==' '
                used[i]=chara[n]
                if dfs(n+1)
                    return true
                end
                used[i]=' '
            end
        end
        return false
    end
    if !dfs(1)
        println("UNSOLVABLE")
    end
end

# --------input func----------
lines=readlines()
input()=popfirst!(lines)
int(s::AbstractString)=parse(Int,s)
ints(s::AbstractString)=map(x->parse(Int,x),split(s))
ints(s::AbstractString,sp)=map(x->parse(Int,x),split(s,sp))
main()

f:id:halss:20210302234341p:plain
これは唐突なJuliaねこ