LoginSignup
1
0

More than 5 years have passed since last update.

第2回 オフラインリアルタイムどう書くの参考問題の解答例。C で。

Posted at

オフラインでリアルタイムに「どう書く」をやるイベント第二回
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言語向きかな なんて思っていたんだが、解いてみるとそうでもない感じ。
もう少し楽に書けると思っていたんだけど。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0