Σ(゚д`*;)アッ,アハァ?


修正版 ○配列 (4-698)

こなとけろ むるいのれめ 
たて★かは っん★゛しー 
すょせきさ くう、。゜・ 

--★シフト--
ぁねゃほゆ ぬわあにぇ「 
ぃおらもふ やつまちえ」 
ぅゅそよへ みりひをぉ 

修正した評価関数 (key.cpp)

//---------------------------------------------------------------------------
/// キー k の運指にかかる時間を求める
/**
ボトルネックを考えたアルゴリズム。以下のような場合、
  t7 1 608
  te 1 123
  e7 1 421
運指 te7 は、123+421=544msec では打てない。
te で 123msec, e7は421msecだが、t7は608msecと遅い。
最初の t を打った直後に、右中指は t → 7 への移動を開始する。
e を打ったとき、右中指は移動の 123msecぶんを終えた。
t→7 の移動は608msecかかるから、残りは 485msec。
e7 は421msecで打てるはずが、右中指の移動がボトルネックとなり、
結局、123 + (608-123) = 608 になる。
**/
//---------------------------------------------------------------------------
u32 CKey::GetTime(sstr k)
{
  if (k.empty()) return 0;
  u32 ret=0;
  // tPass[i] は、(i+2)個前のキーから何msecが経過したかを記録する
  const u32 NPRE=4; // 最速の2キー vs 最遅の2キー がどれくらい違うかによるが4個以上は結果が同じだった
  u32 tPass[NPRE];
  memset( tPass, 0x00, sizeof(tPass) );

  char now=0, next; // 1文字目はnow=0にしてホームからの時間を取る
  for (u32 i=0; i<k.length(); i++)
  {
    next = k[i];
    UUMAP::iterator it = mMap.find( KeyType(now, next) );
    if ( it!=mMap.end() )
    {
      u32 dt = (*it).second; // dt は (now, next) の運指にかかる時間

      // ボトルネック?
      for (u32 j=0; j<NPRE && j+2<=i+1; j++)
      {
        char c1 = j+2>i ? 0 : k[i-(j+2)]; // j=0なら2文字前、j=1なら3文字前…を取る
        u32 bt = mMap[ KeyType(c1, next) ]; // c1 (2,3,4…文字前) からnextまでの時間
        if (tPass[j] < bt) // c1の文字→next の運指に十分な時間が経過してない?
        {
          u32 remain = bt - tPass[j]; // c1→next の運指の残り時間
          dt = max(dt, remain); // 残り時間が now→next の運指より長れけばボトルネック
        }
      }

      rTL::shift( tPass, endof(tPass), +1 ); // 経過時間の配列を右にずらす
      tPass[0] = dt; // [0]には今やったのを入れて、
      for (u32 j=1; j<NPRE; j++) tPass[j]+=dt; // [1]〜は時間を加える

      ret += dt;
      now = next;
    }
    else
      now = 0; // 0にすることで次はホームからの距離で測る
  }

  return ret;
}