Slackでゴルフ場を作ったよ
遊んでくれると嬉しいよ
背景・動機
- 元々は@fmy が社内のコミュニケーションツール上で開催してたよ
- エンジニア数百人で黙々とランキング更新戦が行われ、1byteを巡る攻防に皆業務を忘れ必死だったとか
- 簡単にSlack APIに置き換えられたので公開してみたよ
- Node学園 25時限目でも宣伝してみたよ
参加方法
Google formで(Slackで使う)メアドだけ入力すれば数分後にSlackからinviが届くよ
※GAS(Google Addon Script)で自動化したよ: 公開Slack用 自動招待フォーム by GAS
遊び方
- slackにloginしたらgeneral channelに入るけど、generalはランキングを公開する目的の場所だから、まずはx-codegolfってbotをクリックしてDIRECT MESSAGE(以下DM)を繋ごう
- general部屋でコードを投げないよう注意してね!皆から丸見えになるよ!
- general部屋での質問や雑談も歓迎だよ!
- DMを繋ぐと自動的にHELPが表示されるよ
- HELPは
help
とかbotに打てば何度でも見れるよ。色んな文字列で反応するから試してみてね。 -
node-slack-sdkを使っているなら
RTM_EVENTS.IM_CREATED
で実現できたよ
- HELPは
-
v
とかversion
って打てば使える言語とそのバージョンの一覧が見れるよ
-
q 1
って打てば問1の問題文が、q 2
って打てば問2の問題文が見れるよ
- 問1をpythonで解く時は
1 python
って問題番号+言語を書いて改行して、解答の初めと終わりをシングルクォート3つで括って投稿してね。- シングルクォート3つで括るとSlackが引用ぽく表記するよ(syntax highlightはないよ)
- botの正規表現でシングルクォート3つを引っかけてるよ。改行は無視するよ(解答中の改行は1byteで数えるよ)
- https://github.com/slack-codegolf/platform/blob/master/index.js#L171
- ちなみに入力欄での改行はCtrl+Enterでできるよ
- サーバーサイドでテストされて、成功か失敗かバイト数と一緒に通知が来るよ
- Byte数を縮めて上位5位以内になれば、general部屋でランキングが更新されて(∗´꒳`)ドヤァできるよ
- 問題を全部解いていればその言語の総合ランキングの対象にもなるよ
- ランキングは問題別・言語別でいつでも確認できるよ。botのHELPを見てね。
特徴
- 投稿するcodeは公開されないし保持してない
- general channelにランキングとバイト数だけが表示
- サイエンスチックな解き方とか、どんな解き方をしてもバレないし問題ないよ
- 圧倒的な結果を見せつけてからの(∗´꒳`)ドヤァはクセになるよ
- 運営が勝手に「ランキング上位の人のコードを発表〜」とかできないよ
- 正確には現状はherokuのlogにstraceの結果が残ってるけど、無料プラン・無料アドオンだから保持期間は7日間だけだよ
禁止事項
- 答えをcatする行為
- 権限で制御
- ネットワーク経由で答えを送信する行為
- ネットワーク遮断
ifconfig $(ifconfig | fgrep encap:Ethernet | awk '{print $1}') down
- ネットワーク遮断
- bash以外のすべての言語で外部コマンド禁止
- straceを用いて子ps監視
strace -f -e execve $COMMAND < ${INPUT}/$file
- straceを用いて子ps監視
- しかし現状は......
- システム構成
- herokuのsudo不可とか「docker使える!」と言いつつapp内でdockerコマンドが使えるわけじゃない制限のせいで(ry
- 人が増えたらサーバー借りてちゃんとやるよ。Mastodon化もしたいよ
Codegolf Tips
Nodejs
ex ascii
次の文字列を出力してください。
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
JavaScriptなら
63 Byte
j=''
for(i=33;i<127;)j+=String.fromCharCode(i++)
console.log(j)
Node Core API
Buffer便利だよ
51 Byte (43 Byteまで縮められるよ)
console.log(Buffer.alloc(94,33).map((v,i)=>v+i)+"")
stdin
下記のように書けるよ
// 文字コードを指定すればstring
s=require('fs').readFileSync('/dev/stdin','UTF8');
// 文字コードを指定しなければBuffer
b=require('fs').readFileSync('/dev/stdin');
// 引数はfdも可能、bufferはmap処理できる
require('fs').readFileSync(0).map(v=>{});
// eventで受けてもいい(bはBuffer)
process.stdin.on('data',b=>{});
Python
下記の記事を参考にしたよ。
他にもたくさん有効な方法があるから、公式DOCとかも読んでね。