コンテンツへスキップ
Blog

グラーツでのコーディング・チャレンジ:そして勝者は...

· によって grommunio
グラーツでのコーディング・チャレンジ:そして勝者は...

グラーツLinuxデイズにおいて、grommunioは高い評価を得たコーディングチャレンジを開催した。23名の参加者のうち、9名が見事な結果を発表することができました。抽選で選ばれた最優秀賞受賞者は、grommunioオフィスで賞品を受け取りました。

コーディングチャレンジ優勝者
grommunioのFabian Ortnerが幸運な勝者Andreasに700ユーロ相当の新品のSony PlayStation 5をプレゼント。

とても簡単そうでしょう?

*“この課題では、このReadmeファイルの最後にあるCoding Challengeを解くために、C/C++のコードを書いてください。MinGW64 with gcc/g++ 15.2が使用され、ローカルディレクトリに自動的にセットアップされ、以下のコマンドで使用できます。

技術者でない多くの人々には理解不能に聞こえるかもしれないが、プログラマーにとっては、少なくとも一見したところでは難しく感じない。原理的には、grommunioが盛り込んだ4つのタスクは確かに解決可能であり、23人のLinuxエキスパートが4月のある土曜日、グラーツでこのチャレンジに挑んだ。

タイムプレッシャーの中でのプログラミング

多くの参加者は、自分で書いたコードを使って正しい解を見つけなければならない制限時間に苦戦した。最初に見積もった20分という時間はあまりにも楽観的すぎることが判明し、最終的に割り当てられた40分以内に正しい解答を見つけることができた参加者はわずか9名だった。

その結果、グラーツに特別に用意された2台のウィンドウズ・マシンは、土曜日にほぼ連続的に使用され、7時間以上がチャレンジそのものに割り当てられた。

コーディング・チャレンジのセットアップ

grommunioの従業員は、コンピュータに新しいユーザーアカウントを作成し、エディタとしてVSCodeを設定し、コンパイルと提出プロセスをスピードアップするために、Windowsのcmdスクリプトを介して様々なコマンドを自動化した。

コーディング・チャレンジ・コード
grommunioが提供するツールを使って、チャレンジに成功した参加者。

*“私たちは小さなHTTPエンドポイントをセットアップし、チャレンジ・コンピューター上のシェルスクリプトと組み合わせることで、電子メールアドレスに基づいて各参加者にパーソナライズされた入力を生成し、問題を解決する試みに対するフィードバックで応答することができました “*とgrommunioのFabian Ortner氏(上の写真)は説明する。 「Readmeファイルには、プログラミング・タスクに必要なことがより詳細に記述されており、可能な限り簡単に参加できるよう、かなりシンプルで自動化されたプロセスが作成されました」

しかし、「できるだけ簡単に」という部分は長くは続かなかった。この課題では、参加者は小さな変換スクリプトを書いて、機能不全に陥ったメールサーバーを修復しなければならない。READMEでは、解決すべき4つのタスクのうちの最初のタスクがこう始まっている:

*「各行には8文字の整数倍が含まれているようなので、これを個々のバイトとして解釈してみよう。例えば

0100010001010001001010 0x44 0x51 0x4A
0100010001000001001100 => 0x44 0x50 0x4C
010000001010001001100 0x42 0x51 0x4C

*古いメールサーバーでは、電子メールをエクスポートした後、非常に単純な暗号化方法を使用していたことがわかっている。

  • テキストの各行、すなわち各バイトを取る。
  • 各行に対して、1文字ずつキーでXOR暗号化**を実行する。
  • *行がキーより長い場合は、最初の文字からもう一度キーを適用します。

さらに、頭を悩ませるような要求やタスクが続いた。正解を導き出せる参加者はごくわずかだった。

しかし、正解できなかった参加者にも楽しみがあった。最終的に、参加者全員の中から無作為の抽選で、約束のプレイステーションが贈られることになったのだ。当選者のアンドレアスは、ウィーンのDCタワー30階、グロムニオ本社に招待された。

解決策は?ここには掲載しないが、問題文の全文が書かれたREADMEファイルがこの記事の下にある。しかし、Graz Linux Daysのためにgrommunioが構築したサーバーがなければ、ちょっと想像力が必要です…。

Graz Linux Daysでのgrommunioについては、こちらの記事を参照してください。


コーディングチャレンジの手順

この課題では、この Readme の最後にある課題を解決するために、. \srcmain.cpp 内に C/C++ コードを記述する必要があります。この課題では MinGW64 と gcc/g++ 15.2 を使用します。gcc/g++ 15.2 はローカルディレクトリに自動的にセットアップされ、以下のコマンドで使用できます。

同梱のスクリプトには4つの重要なコマンドがある:

1.メールアドレスを登録し、20分タイマーを開始する:

.\glt.cmd start`.

2.コードをビルドするだけなら

. \glt.cmd build.

3.コードをビルドして実行し、その出力をターミナルに出力するには:

コードをビルドして実行し、その出力をターミナルに出力するには: . \glt.cmd build_and_run.

4.ソリューションをビルド、実行、送信するには

ソリューションをビルド、実行、サブミットするには: . \glt.cmd submit

ソリューションのビルドに使用されるコマンドは、デフォルトで最適化が有効になっていません:

g++.exe -static -O0 -g -std=c++17 srcmain.cpp -o build/app.exe.

チャレンジ

チャレンジを開始するには、まずあなたのメールアドレスを user.txt ファイルに入力し、次に start コマンドを使用して入力を取得します。これは、抽選に当たった場合にあなたに連絡するためだけに使用します。あなたのコードで result 変数を変更し、それが正しいかどうかをチェックするために submit コマンドを実行するだけです。

すごい。移行中にE-Mailはどうなったんですか?新しいメールサーバーのセットアップ中に、どういうわけかEメールが壊れてしまいました。数行に分割されたバイナリ・シンボル(あなたの入力)で構成されているようです。1行に8の整数倍のシンボルがあるようなので、個々のバイトとして解釈してみましょう。例えば

01000100010001001010 0x44 0x51 0x4A
0100010001000001001100 => 0x44 0x50 0x4C
010000001010001001100 0x42 0x51 0x4C

古いメールサーバーでは、電子メールをエクスポートした後、実に単純な暗号化を使用していたことがわかっている:

  • テキストの各行、つまり各バイトを取る。
  • 各行を文字単位でキーとXORする。
  • 行がキーより長い場合は、単純に最初の文字からキーを再利用する。
0x44 ^ g = 0x23 0x51 ^ r = 0x23 0x4A ^ o = 0x25
0x44 ^ g = 0x23 0x50 ^ r = 0x22 0x4C ^ o = 0x23
0x42 ^ g = 0x25 0x51 ^ r = 0x23 0x4C ^ o = 0x23

その方が期待できそうだが、まだ文字化けが多い…。

以前の古いメールサーバーでは、個々の文字値のオフセットにすでに問題があり、オフセットは2つの事柄に依存していました:

  • メールアドレスの水平チェックサム
  • 行内の文字のインデックスと行番号

当時、サーバーはメールアドレスのすべてのバイト値を単純に足し合わせることで、水平方向のチェックサムを計算していました。

[email protected] => (m=109) + (a=97) + (x=120) + ... = 2888

次に、各文字の正のオフセットは、チェックサムから行内の位置を引いて計算されます。したがって、このエラーを修正するには、各バイトからオフセット値を差し引く必要があります。さらに、これらのオフセットは、各行の後に1文字ずつ左にシフトされる。

0x23 - (2888 % 1) = '#' 0x23 - (2888 % 2) = '#' 0x25 - (2888 % 3) = '#'
0x23 - (2888 % 2) = '#' 0x22 - (2888 % 3) = ' ' 0x25 - (2888 % 1) = '#'
0x23 - (2888 % 3) = '#' 0x23 - (2888 % 1) = '#' 0x25 - (2888 % 2) = '#'

これで正しいメッセージのように見える!しかし、正しいアルゴリズムであることを確認するために、オフセット値 の要素ごとの積と使用されている各キー文字の文字値を計算し、メッセージ内の各 #文字について合計する必要がある。とrは捨てる。

    (g=103)*0 + (r=114)*0 + (o=111)*2
+ (g=103)*0 + (o=111)*0
+ (g=103)*2 + (r=114)*0 + (o=111)*0 = 428

この要素ごとの積の和を結果変数に書き込んで、コーディング・チャレンジを終了する必要がある!

幸運を祈る!