第五回オフラインリアルタイムどう書く( http://atnd.org/events/32979 )。
問題は下記 URL。
http://nabetani.sakura.ne.jp/hena/ord5dahimi/
で。
当日その場で書いたもの( http://qiita.com/items/6faf952a90659b736037 )があまりにもひどいので書きなおしたのがこれ。
// use "-std=c99"
# include <stdio.h>
# include <stdlib.h>
# include <memory.h>
# include <string.h>
# include <math.h>
char const ORDER[]="3456789TJQKA2o";
enum{ JOKER = 13 };
int strength( char const * card )
{
return strchr( ORDER, card[1] ) - ORDER;
}
int compareByStrength(const void *va, const void *vb)
{
char const * a=va;
char const * b=vb;
return strength(a) - strength(b);
}
char const * firstCard( int s, char const * cards )
{
for( char const * p=cards ; *p ; p+=2 ){
if ( s==strength(p) ){
return p;
}
}
return 0;
}
int population( size_t bits ){
int r=0;
for( int b=1 ; b<=64 ; b<<=1 ){
r+=!!(bits&b);
}
return r;
}
void addAvailables( char * result, int s, int count, char const * cards, char const * postfix )
{
char const * begin = firstCard( s, cards );
if ( ! begin ){
return;
}
char const * end=begin;
for( ; *end && s==strength( end ) ; end+=2 );
int sample = ( end-begin ) / 2;
if ( sample<count ){
return;
}
for( size_t bits=1 ; bits<(1<<sample) ; ++bits ){
if ( count != population( bits )){
continue;
}
if ( * result ){
strcat( result, "," );
}
strcat( result, postfix );
for( int i=0 ; i<sample ; ++i ){
if ( bits & (1<<i) ){
strncat( result, begin+i*2, 2 );
}
}
}
}
char const * solve( char const * input )
{
char * f = strdup( input );
char * inHand = strchr( f, ',')+1;
inHand[-1]=0;
int nofCardsInHand = strlen( inHand ) / 2;
int nofCardsInPlay = strlen( f )/2;
char * result = calloc( pow( nofCardsInHand+1, nofCardsInPlay+1 ), nofCardsInHand*2+1 );
qsort( f, strlen( f )/2, 2, compareByStrength );
qsort( inHand, strlen( inHand )/2, 2, compareByStrength );
int jokerAsWildcard = 1<nofCardsInPlay && firstCard( JOKER, inHand );
for( int r=strength( f )+1 ; r<14 ; ++r ){
addAvailables( result, r, nofCardsInPlay, inHand, "" );
if ( jokerAsWildcard && r!=JOKER ){
addAvailables( result, r, nofCardsInPlay-1, inHand, "Jo" );
}
}
free( f );
if ( !*result ){
*result='-';
}
return result;
}
int compare(const void *a, const void *b)
{
return *(char*)a - *(char*)b;
}
int is_same( char const * a, char const * b )
{
// いい加減だけど、だいぶ正しい。
size_t len = strlen(a);
if ( len != strlen(b) ){
return 0;
}
char * a1 = strdup(a);
char * b1 = strdup(b);
qsort(a1, len, 1, compare );
qsort(b1, len, 1, compare );
int r = 0==strcmp( a1, b1 );
free( a1 );
free( b1 );
return r;
}
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,", "-" );
/*#7*/ test( "ST,D6S8JoC7HQHAC2CK", "Jo,C2,CK,HA,HQ" );
/*#10*/ test( "Jo,HAC8DJSJDTH2", "-" );
/*#30*/ test( "D4H4S4C4,S6SAH6HAD6DAC6CAJo",
/*#32*/ test( "JoS8D8H8,S9DTH9CTD9STC9CAC2", "H9C9D9S9" );
return 0;
}
再帰呼び出しを bit 演算で回避した。
テストが成功したかどうかの判断はまだ不完全だが、C99 なら 対費用効果としてこのあたりが落としどころかと。