Marhjong win check: ver 0.1

%a.out 1112345678999
Initial:1112345678999
 [OK]:(99)(*111)(*123)(456)(789)
 [OK]:(99)(*123)(*111)(456)(789)
 [OK]:(*22)(111)(345)(678)(999)
 [OK]:(11)(12*3)(*345)(678)(999)
 [OK]:(99)(111)(23*4)(*456)(789)
 [OK]:(*55)(111)(234)(678)(999)
 [OK]:(11)(123)(45*6)(*678)(999)
 [OK]:(99)(111)(234)(56*7)(*789)
 [OK]:(*88)(111)(234)(567)(999)
 [OK]:(11)(123)(456)(78*9)(*999)
#include <stdio.h>
#include <stdlib.h>

#define PIECE_KINDS 9
#define PIECE_CHAR(id) ('1'+(id))
// place -1 at the end margin for sentinel
typedef int Hand[PIECE_KINDS+2];

// 111-type triplet id
#define TRIPLET_ID_111(i) (i)
// 123-type triplet id
#define TRIPLET_ID_123(i) (100+i)
// hack: also print a pair
#define TRIPLET_ID_PAIR(i) (1000+i)

// hypothesical draw
int one_drawn;
static void print_triplet(int id);


// Check if given hand has one pair plus (4-ntriplet) triplets
//  May call itself recursively.
//
//  input:
//  Hand hand: hand data to check
//  int start: hand has no triplets nor pair in a range 0 .. start-1
//  int pair_idx: -1 if pair is needed. pair_idx!=-1. When we already have a pair, pair_idx= piece id
//  int ntriplet: number of triplets we already have
//  int *triplets: id's of triplets we already have
bool Win(Hand hand, int start, int pair_idx,int ntriplet, int *triplets)
{
    int i=start;
    bool result = false;

    if(ntriplet==4 && pair_idx !=-1)
    {
	// Win!
	printf(" [OK]:");
	print_triplet(TRIPLET_ID_PAIR(pair_idx));
	for(i=0;i<4;i++)
	{
	    print_triplet(triplets[i]);
	}
	printf("\n");
	return true;
    }

    while(hand[i] != -1)
    { 
	//skip
	if(hand[i]==0)
	{
	    i++;
	    continue;
	}

	//fork: possible pair found
	if(hand[i] >=2 && pair_idx == -1) 
	{
	    hand[i]-=2;
	    result |= Win(hand, i+1, i, ntriplet, triplets);
	    hand[i]+=2;
	}

	//fork: possible 111-type found
	if(hand[i]>=3)
	{
	    hand[i]-=3;
	    triplets[ntriplet] = TRIPLET_ID_111(i);
	    result |= Win(hand, i, pair_idx, ntriplet+1, triplets);
	    hand[i]+=3;
	}

	//fork: possible 123-type found
	if(hand[i+1]>0 && hand[i+2]>0)
	{
	    hand[i]--;
	    hand[i+1]--;
	    hand[i+2]--;
	    triplets[ntriplet] = TRIPLET_ID_123(i);
	    result |= Win(hand, i, pair_idx, ntriplet+1, triplets);
	    hand[i]++;
	    hand[i+1]++;
	    hand[i+2]++;
	}
	i++;
    }//while

    // no more piece in hand
    return result;
}

// I/O routnes

void print_hand(Hand hand)
{
    int i,j;
    for(i=0;i<PIECE_KINDS;i++)
    {
	for(j=0;j<hand[i];j++) putchar(PIECE_CHAR(i));
    }
    printf("\n");
}

void print_triplet(int id)
{
    putchar('(');
    // hack: also print a pair
    if(id>=1000)
    {
	id-=1000;
	if(id==one_drawn)putchar('*');
	putchar(PIECE_CHAR(id));
	putchar(PIECE_CHAR(id));
    }
    else
    if(id>=100)
    {
	id-=100;
	if(id==one_drawn)putchar('*');
	putchar(PIECE_CHAR(id));
	if(id+1==one_drawn)putchar('*');
	putchar(PIECE_CHAR(id+1));
	if(id+2==one_drawn)putchar('*');
	putchar(PIECE_CHAR(id+2));
    }
    else
    {
	if(id==one_drawn)putchar('*');
	putchar(PIECE_CHAR(id));
	putchar(PIECE_CHAR(id));
	putchar(PIECE_CHAR(id));
    }
    putchar(')');
}

int main(int argc, char **argv)
{

    int i;
    if(argc!=2)exit(1);
    Hand hand;
    for(i=0;i<PIECE_KINDS;i++)hand[i]=0;
    //sentinel
    hand[PIECE_KINDS]=hand[PIECE_KINDS+1]=-1;

    // input
    for(i=0;i<13;i++)
    {
	if(argv[1][i]==0)exit(1);
	int kind=argv[1][i]-'0';
	if(kind<1 || kind>9)exit(1);
	hand[kind-1]++;
    }

    printf("Initial:");
    print_hand(hand);

    int triplets[4];
    // hypothesical one draw loop
    for(i=0;i<PIECE_KINDS;i++)
    {
	one_drawn=i;
	int j;
	// hypothesical one draw
	hand[i]++;

	//start from 0, pair= -1, triplets=0
        Win(hand, 0, -1, 0, triplets);
	hand[i]--;
    }
}