史上最大のコーディングスキル判定(Cでも書いた)

Cでも書いてみた。ロジックがわかってるのに正味80分くらいかかった。

配列をなんやかやするのが面倒そうだったので数牌を個数で管理する方法に変更。

Cで書いたけどアセンブリですねこれは。

まだCのほうが楽に書けるけど、Rubyのほうがきっとずっと楽に楽しく書けそう。

#include <stdio.h>

void slice_melds(char* uniq, char* form, int restofform)
{
  int i;
  if(restofform == 23)
    puts(form);
  else
  {
    i=0;
    while( uniq[i]==0) i++;
    /* 一番小さい牌がコーツを構成していると仮定して探索 */
    if(uniq[i]>=3)
    {
      sprintf(form + restofform, "(%d%d%d)", i+1, i+1, i+1);
      uniq[i] -= 3;
      slice_melds(uniq, form, restofform+5);
      uniq[i] += 3;
    }

    /* 一番小さい牌がシュンツを構成していると仮定して探索 */
    if(i<7 && uniq[i] > 0 && uniq[i+1] > 0 &&  uniq[i+2] > 0)
    {
      uniq[i]--; uniq[i+1]--; uniq[i+2]--;
      sprintf(form + restofform, "(%d%d%d)", i+1, i+2, i+3);
      slice_melds(uniq, form, restofform+5);
      uniq[i]++; uniq[i+1]++; uniq[i+2]++;
    }
  }
}

int main(int argc, char* argv[])
{
  char tehai[14];
  char uniq[9] = { 0 }; /* 数牌の個数 */

  char form[24] = { 0 }; /*テンパイ形の文字列*/
  int restofform = 0; /*テンパイ形の未確定部分のトップ*/

  int i,j;

  sprintf( tehai, "%.13s", argv[1]);
  for( i = 0; i < 13; i++ ) uniq[tehai[i]-'1']++;

  /* 雀頭なし(つまり単騎待ち) */
  /* ・1個取り除いて、残り12個が4メンツ構成するパターンを探索 */
  for( i=0; i<9; i++)
  {
    if(uniq[i] == 0) continue;
    sprintf(form+restofform, "[%d]", i+1);
    uniq[i]--;
    slice_melds(uniq, form, restofform+3);
    uniq[i]++;
  }

  /* 雀頭あり */
  /* ・雀頭を取り除いた後、任意にトイツやターツを取り除き、残り9個が3メンツを構成するパターンを探索 */
  for( i=0; i<9; i++)
  {
    if(uniq[i] < 2) continue;

    /* 雀頭を取り除く */
    sprintf(form+restofform, "(%d%d)", i+1, i+1);
    uniq[i] -= 2;
    restofform += 4;

    for( j=0; j<9; j++)
    {
      if(uniq[j] == 0) continue;

      /* トイツを見つけたらそれを待ち(シャボ)として残り9枚で3メンツを構成するパターンを探索する */
      if(uniq[j] >= 2)
      {
        sprintf(form+restofform, "[%d%d]", j+1, j+1);
        uniq[j] -= 2;
        slice_melds(uniq, form, restofform+4);
        uniq[j] += 2;
      }

      /* 2枚連番を見つけたらそれを待ち(ペンチャンまたはリャンメン)として残り9枚→3メンツの探索 */
      if(j<8 && uniq[j+1]>0)
      {
        sprintf(form+restofform, "[%d%d]", j+1, j+2);
        uniq[j]--; uniq[j+1]--;
        slice_melds(uniq, form, restofform+4);
        uniq[j]++; uniq[j+1]++;
      }

      /* カンチャンのターツを見つけたらそれを待ちとして残り9枚→3メンツの探索 */
      if(j<7 && uniq[j+2]>0)
      {
        sprintf(form+restofform, "[%d%d]", j+1, j+3);
        uniq[j]--; uniq[j+2]--;
        slice_melds(uniq, form, restofform+4);
        uniq[j]++; uniq[j+2]++;
      }
    }
    restofform -= 4;
    uniq[i] += 2; /* 取り除いた雀頭を戻す */
  }
  return 0;
}