Sun Dec 13 14:46:11 JST 2015

CODERUNNER 2015 本戦

(一瞬だけ) (スコアの上昇速度で) 輝けた

解法

APIを使う練習のつもりで、次のプログラムをひとまず書いて動かそうとする

  1. 国から受注
  2. 社員を割り当てる

ちょっとルールを理解してきれてなかった.

  1. 期間内に仕事をこなせるぎりぎりの人間を割り当てるように変更
  2. ギリギリOKな人間を割り当てたはずなのに、何故かエラー (この人間だと納期に間に合わない) が帰ってきた

getinfo

その時点での、自分の情報を得るAPI. これは、別のプログラムとして、1.1秒ごとに取得させて利用した.

TOKEN=9F7RPQP86817D3PJMIAQES8L0XLN6FZ9
while :; do
  curl -s http://game.coderunner.jp/getinfoJson?token=$TOKEN > tmp.json
  mv tmp.json info.json
  date;
  sleep 1.1
done

わざわざ書くほどのものでもないけど. 最後の1時間くらい、このAPIが頻繁に (1/10の確率) 死ぬようになった. そうすると古い情報で社員を割り当てるので、しょっちゅう、「その社員は既に働いています」エラーが出た.

  timeout 1 curl -s http://game.coderunner.jp/getinfoJson?token=$TOKEN > tmp.json &&
    mv tmp.json info.json

に変更した. timeout コマンド便利. curl のタイムアウトのオプションとかいちいち覚えてられないです.

知見

  1. 自分たちで仕事が出来るならそれが一番良い
  2. 外注に出す行為はリスク
  3. 国から仕事を受けるのは運ゲー
  4. 外注から仕事を取るのが賢い

プログラム

最終的なプログラムはこれ.

fs = require 'fs'
{execSync} = require 'child_process'
info = require './info.json'

exec = (com) ->
  execSync(com).toString()

TOKEN = '9F7RPQP86817D3PJMIAQES8L0XLN6FZ9'

int = (x) -> x | 0

# [仕事のID] [納期までの残り時間(秒, 小数点以下切り捨て)] [仕事量] [仕事の種類] [報酬] [賠償]
[tid, time, w, k, reward, risk] =
  exec("curl -s http://game.coderunner.jp/taketask?token=#{TOKEN}").split(' ').map(int)
console.warn "受注: #{[tid, time,w,k,reward,risk]}"
fs.appendFileSync 'log', [tid, time,w,k,reward,risk]
fs.appendFileSync 'log', '\n'

## 外注
#
outsource = ->
  cost = reward * 0.7
  cost = cost | 0
  console.warn "* 外注: cost = #{cost}"
  exec "curl -s 'http://game.coderunner.jp/outsource?task=#{tid}&orderReward=#{cost}&token=#{TOKEN}'"

## 内
#
inner = ->
  workers = []
  info.workers.forEach (w, i) ->
    return if w.time > 0
    workers.push { id: w.id, speed: w.speed[k] }
  workers.sort (a,b) -> b.speed - a.speed

  qs = []
  sum = 0
  ok = false

  for i in [0 ... workers.length]
    qs.push workers[i].id
    sum += workers[i].speed
    if sum * time > (w*1.2)
      ok = true
      break

  if qs.length > 8
    ok = false

  console.warn "* 割り当て: #{qs} (#{sum})"
  if ok
    res =
      exec "curl -s 'http://game.coderunner.jp/assign?token=#{TOKEN}&task=#{tid}&worker=#{qs.join(',')}'"
    console.warn res
    if res.indexOf('Error:') is 0
      do outsource
  else
    console.warn '* 割り当て無理'
    do outsource

do inner

延べて2時間程度はプログラムを書き続けてたのに、結果的に書いたのはこれだけと思うと、しょぼい. 他の人のはどんなだろう.

実況

2015/12/12 2:30 PM - 5:30 PM

coderunner来た

— /c/ympfh (@cympfh) December 12, 2015

pic.twitter.com/cIHrsqqBZv

— /c/ympfh (@cympfh) December 12, 2015

positive score

— /c/ympfh (@cympfh) December 12, 2015

(長い負スコアから偶然脱却したときのコメント)

なんかこれあっという間にnegative score に吸い込まれるな

— /c/ympfh (@cympfh) December 12, 2015

(うん、だってバグってるからね)

すごい重力

— /c/ympfh (@cympfh) December 12, 2015

(割り当てに失敗した仕事を放置してたので一気に賠償してた)

正直 「外注する」って言葉、どちら側の言葉なのかわからなくない?

— /c/ympfh (@cympfh) December 12, 2015

(外注に出す、外注を受ける、って言ってくれればいいのに)

一時的にポジティブスコア来てもあるとき一気にツケが回収されるように、ネガティブに吸い込まれる

— /c/ympfh (@cympfh) December 12, 2015

マイナス無限 pic.twitter.com/QiSUlYXuON

— /c/ympfh (@cympfh) December 12, 2015

(自分の点数の折れ線グラフ smooth bezier)

くっっっっっっっっっっっっっそバグってた

— /c/ympfh (@cympfh) December 12, 2015

(プログラム変更してるはずなのにprinfデバッグもできないぞ、おかしいなあ、と思ったら違うファイル触ってた、みたいなタイプのバグです)

中途半端な順位で終わることが容易に想像着く pic.twitter.com/73R2lmBpVb

— /c/ympfh (@cympfh) December 12, 2015

(まともにスコアを稼ぎはじめたので、様子見のために、自分と一位と割と上位の人のスコアを比較し始める. 実はコレと同じグラフを描いてくれるためのツールが用意されてたらしい)

getinfoたまに死ぬ

— /c/ympfh (@cympfh) December 12, 2015

(他の何よりも使うAPIなんですよ、これ)

Error: Some workers are still working 連発するから困るなあ

— /c/ympfh (@cympfh) December 12, 2015

数時間前の順位にようやく戻ってこられた pic.twitter.com/TZzYlT9wfR

— /c/ympfh (@cympfh) December 12, 2015

(じわりじわりと、親に顔向け出来る順位に来たので安心してトイレに立つ頻度が増える)

来てるんじゃないですかこれ #coderunner2015 pic.twitter.com/QMmdkjJ6Rf

— /c/ympfh (@cympfh) December 12, 2015

22年間人生プレイしてきたけど人生は運

— /c/ympfh (@cympfh) December 12, 2015

(もうこれ以上プログラムを変更する気はない、という意思表明です)

頼む!今終ってくれ! pic.twitter.com/qTBUajSyqQ

— /c/ympfh (@cympfh) December 12, 2015

(バグが取れてからは、メインのプログラムに一切変更せずにここまで来たので浮かれた)

凋落 pic.twitter.com/lWbwtpAuxB

— /c/ympfh (@cympfh) December 12, 2015

(最後の30分、外注天国になっていたらしく、外注から美味しい仕事を引き受けるほうが点数が稼げたようです)

pic.twitter.com/jysxQd6lTA

— /c/ympfh (@cympfh) December 12, 2015

(最終スコア)

pic.twitter.com/OUt2UVMibH

— /c/ympfh (@cympfh) December 12, 2015

(最終スコア)