オフラインでリアルタイムに「どう書く」をやるイベント第二回
http://atnd.org/events/30900
の、参考問題
http://qiita.com/items/9d80de41903775296ca6
の解答例。C言語(C99)で。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ENDOF(x) (x+sizeof(x)/sizeof(*(x)))
typedef struct data_t
{
char const * src;
char const * expected;
} data_t;
data_t data[]={
{"3:5b8","3:de0"},
{"1:8","1:8"},
{"2:8","2:4"},
{"2:4","2:1"},
{"2:1","2:2"},
{"3:5d0","3:5d0"},
{"4:1234","4:0865"},
{"5:22a2a20","5:22a2a20"},
{"5:1234567","5:25b0540"},
{"6:123456789","6:09cc196a6"},
{"7:123456789abcd","7:f1a206734b258"},
{"7:fffffffffffff","7:ffffffffffff8"},
{"7:fdfbf7efdfbf0","7:ffffffffffc00"},
{"8:123456789abcdef1","8:f0ccaaff78665580"},
{"9:112233445566778899aab","9:b23da9011d22daf005d40"},
};
void clear_bits( char * rs )
{
for( char * p=rs ; *p ; ++p ){
*p='0';
}
}
int int_from_nibble( char c )
{
char sz[2]={0};
sz[0]=c;
return strtol( sz, 0, 16 );
}
_Bool bit_at( char c, int pos )
{
return !!( int_from_nibble(c) & (8>>pos) );
}
typedef struct bitpos_t
{
int nibble_pos;
int bit_in_nibble;
} bitpos_t;
bitpos_t bitpos_from_xy( int x, int y, int len )
{
bitpos_t result;
int bit_pos=x+y*len;
result.nibble_pos = bit_pos/4;
result.bit_in_nibble = bit_pos%4;
return result;
};
_Bool get_bit( char const * p, int x, int y, int len )
{
bitpos_t pos=bitpos_from_xy( x, y, len );
return bit_at( p[pos.nibble_pos], pos.bit_in_nibble );
}
char to_nibble( int val )
{
return val<=9 ? val+'0' : val-10+'a';
}
void set_bit( char * p, int x, int y, int len )
{
bitpos_t pos=bitpos_from_xy( x, y, len );
int old=int_from_nibble( p[pos.nibble_pos] );
p[ pos.nibble_pos ] = to_nibble( old | (8>>pos.bit_in_nibble ) );
}
char * bitrot( char const * q )
{
char * result = strdup(q);
char const * qs = strchr( q, ':' )+1;
char * rs = qs-q+result;
int len = atoi( q );
clear_bits( rs );
for( int y=0 ; y<len ; ++y ){
for( int x=0 ; x<len ; ++x ){
if ( get_bit( qs, x, y, len ) ){
set_bit( rs, len-y-1, x, len );
}
}
}
return result;
}
int main()
{
for( data_t const * it = data ; it != ENDOF( data ) ; ++it ){
char * result = bitrot(it->src);
if ( 0 != strcmp( it->expected, result ) ){
printf( "***NG***" );
}
printf( "%s -> %s\n", it->src, result );
free( result );
}
return 0;
}
無駄なことは書いてない気がするけど長い。
C言語の宿命か。
今回はあまり C99 特有の機能は使わなかった。
問題を作った時は C言語向きかな なんて思っていたんだが、解いてみるとそうでもない感じ。
もう少し楽に書けると思っていたんだけど。