第五回オフラインリアルタイムどう書くの回答例(C99)

第五回オフラインリアルタイムどう書く( http://atnd.org/events/32979 )。
問題は下記 URL。
http://nabetani.sakura.ne.jp/hena/ord5dahimi/
で。
当日その場で書いたもの。
コメントなど若干手直ししてあるが、ほぼそのまま。

```C:dahi.c
// use "-std=c99"
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>

int strength( char const * c )
{
    char rep = c[1];
    char m[]="3456789TJQKA2o";
    return strchr( m, rep ) - m;
}
int strengthm( char const * c )
{
    int jo = strength( "Jo");
    int cand = strength( c);
    if ( cand == jo ){
        return strength( c+2);
    } else {
        return cand;
    }
}

char const * dahi_1( char const * f, char const * inHand )
{
    int hc = strlen( inHand )/2;
    char const * ret=calloc( hc*3+3, 1 );
    int fs = strength( f );
    for( int h=0 ; h<hc ; ++h ){
        if ( fs < strength( inHand+h*2)){
            if ( *ret ){
                strcat( ret, ",");
            }
            strncat( ret, inHand+h*2, 2 );
        }
    }
    if ( *ret==0 ){
        strcat( ret, "-");
    }
    return ret;
}
int legal( char const * c )
{
    char const * end = c+strlen( c );
    int jo = strength( "Jo");
    int s=0;
    for( char const * p=c ; p<end ; p+=2 ){
        int sc=strength( p );
        if ( sc==jo ){
            continue;
        }
        if ( s==0 ){
            s=sc;
        } else {
            if ( s!=sc ){
                return 0;
            }
        }
    }
    return 1;
}
char const * dahi_2( char const * f, char const * inHand )
{
    int hc = strlen( inHand )/2;
    char cand[5]={0};
    char const * ret=calloc( hc*hc*3+9, 1 );
    int fs = strengthm( f );
    for( int h=0 ; h<hc ; ++h ){
        for( int h1=0 ; h1<h ; ++h1 ){
            memset( cand, 0, sizeof(cand) );
            strncat( cand, inHand+h*2, 2);
            strncat( cand, inHand+h1*2, 2);
            if ( legal( cand ) && fs < strengthm( cand )){
                if ( *ret ){
                    strcat( ret, ",");
                }
                strcat( ret, cand );
            }
        }
    }
    if ( *ret==0 ){
        strcat( ret, "-");
    }
    return ret;
}
char const * dahi_3( char const * f, char const * inHand )
{
    int hc = strlen( inHand )/2;
    char cand[7]={0};
    char const * ret=calloc( hc*hc*hc*7+9, 1 );
    int fs = strengthm( f );
    for( int h=0 ; h<hc ; ++h ){
        for( int h1=0 ; h1<h ; ++h1 ){
            for( int h2=0 ; h2<h1 ; ++h2 ){
                memset( cand, 0, sizeof(cand) );
                strncat( cand, inHand+h*2, 2);
                strncat( cand, inHand+h1*2, 2);
                strncat( cand, inHand+h2*2, 2);
                if ( legal( cand ) && fs < strengthm( cand )){
                    if ( *ret ){
                        strcat( ret, ",");
                    }
                    strcat( ret, cand );
                }
            }
        }
    }
    if ( *ret==0 ){
        strcat( ret, "-");
    }
    return ret;
}
char const * dahi_4( char const * f, char const * inHand )
{
    int hc = strlen( inHand )/2;
    char cand[9]={0};
    char const * ret=calloc( hc*hc*hc*hc*9+9, 1 );
    int fs = strengthm( f );
    for( int h=0 ; h<hc ; ++h ){
        for( int h1=0 ; h1<h ; ++h1 ){
            for( int h2=0 ; h2<h1 ; ++h2 ){
                for( int h3=0 ; h3<h2 ; ++h3 ){
                    memset( cand, 0, sizeof(cand) );
                    strncat( cand, inHand+h*2, 2);
                    strncat( cand, inHand+h1*2, 2);
                    strncat( cand, inHand+h2*2, 2);
                    strncat( cand, inHand+h3*2, 2);
                    if ( legal( cand ) && fs < strengthm( cand )){
                        if ( *ret ){
                            strcat( ret, ",");
                        }
                        strcat( ret, cand );
                    }
                }
            }
        }
    }
    if ( *ret==0 ){
        strcat( ret, "-");
    }
    return ret;
}
char const * solve( char const * in )
{
    char * f = strdup( in ); // TODO: memory leak!
    char * inHand = strchr( f, ',' )+1;
    inHand[-1]=0;

    int cardCount = strlen( f )/2;
    switch( cardCount ){
        case 1:
            return dahi_1( f, inHand );
        case 2:
            return dahi_2( f, inHand );
        case 3:
            return dahi_3( f, inHand );
        case 4:
            return dahi_4( f, inHand );
        default:
        return strdup("-");
    }
}
int is_same( char const * a, char const * b )
{
    // 不十分にも程があるが、時間の都合でこの程度で我慢した。
    return  strlen(a) == strlen(b);
}

void test( char const * in, char const * expected )
{
    char const * ac = solve( in );
    if ( ! is_same( ac, expected) ){
        puts( "**FAIL**");
    }
    printf( " : %s\n    %s\n    %s\n", in, ac, expected );
    free( ac );
}

int main()
{
    /*#1*/ test( "DJ,", "-" );
    /*#2*/ test( "H7,HK", "HK" );
    /*#17*/ test( "JoC8,H6D7C5S9CQH9STDTCAD9S5DAS2CT", "CTDT,H9D9,S9D9,DACA,CTST,H9S9,DTST" );
    /*#22*/ test( "D8H8S8,CQHJCJJoHQ", "JoCQHQ,JoHJCJ" );
    /*#28*/ test( "H5C5S5D5,C7S6D6C3H7HAH6H4C6HQC9", "C6D6S6H6" );
    /*#32*/ test( "JoS8D8H8,S9DTH9CTD9STC9CAC2", "H9C9D9S9" );
    // テストの大半を省略
    return 0;
}
```

カードの枚数が可変であることに対しては再帰呼び出しで対応するのが筋だが、
制限時間内に確実に書けるものをということでコピペで増やした枚数固定の関数を４つ用意した。

無様でもいいからまず動くものを、ということで。

メモリリークはひどいと思うけど。