LoginSignup
1
1

More than 5 years have passed since last update.

第27回オフラインリアルタイムどう書く「分岐と行き止まり」の C言語による実装

Last updated at Posted at 2014-11-08

問題 http://nabetani.sakura.ne.jp/hena/ord27raswi/
解答リンク集 http://qiita.com/Nabetani/items/23ebddb44f0234e7fb15
イベント http://yhpg.doorkeeper.jp/events/16017

で。

当日お見せした実装。

出題者の気分としては、かなり簡単な問題のつもり。

ruby で事前に実装しておいたんだけど、当日その場で C99 に移植した。

// clang -std=c99 -Wall solve.c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

struct ans{  char m[ 3*9 ]; };

bool can_go( char from, char to, char const * src )
{
  if ( strchr( src, from ) ){
    return false;
  }
  if ( from==to ){
    return true;
  }
  char * ways[] = {
    "1ag", "ab", "bc5", "c46",
    "2dh", "dec", "e5",
    "3bf", "fg", "gceh", "h4i", "i6", 0
  };
  for( int i=0 ; ways[i] ; ++i ){
    char const * way = ways[i];
    if ( from==way[0] ){
      for( int j=1 ; way[j] ; ++j ){
        if ( can_go( way[j], to, src )){
          return true;
        }
      }
    }
  }
  return false;
}

struct ans solve( char const * src )
{
  struct ans ans={{0}};
  for( char from='1' ; from<='3' ; ++from ){
    for( char to='4' ; to<='6' ; ++to ){
      if ( can_go( from, to, src ) ){
        if ( ans.m[0]!=0 ){
          strcat( ans.m, "," );
        }
        char path[3]={ from, to };
        strcat( ans.m, path );
      }
    }
  }
  if ( ans.m[0]==0 ){
    ans.m[0]='-';
  }
  return ans;
}

void test( char const * src, char const * expected )
{
  struct ans ans = solve( src );
  bool ok = strcmp( ans.m, expected )==0;
  printf( "%s : %s->%s ( %s )\n", 
    ( ok ? "ok" : "***NG***"),
    src, ans.m, expected );
}

int main()
{
/*0*/ test( "befi", "14,16,24,26" );
/* 中略 */
/*44*/ test( "bdefgi", "24" );
}

地図をどうコードに表現するかで幾つか選択肢がある。

の3つの選択肢があるんだけど(他にもあるかも)、これは最初に挙げた「分岐情報を持つ」という戦略。

で。
計算量へのケアが全然なく、いろいろひどい感じではある。

ways から way を引くところは hash か二分探索にすべきだし、道をたどる際には重複して探さないようにメモ化すべき。strcat を使うと無駄な計算が生じるので、末尾へのポインタを持っておくべき。

最初は switch〜case を書いていたんだけど、途中で飽きて、こういう形になった。

とはいえ、地図のサイズは決まっているので、今回はこれで十分。

計算量という点では十分だけど、ソースコード出来という観点で見ると、solve が複雑すぎるなとは思う。文字列処理を別の関数に出すべきだね。

struct ans{ char m[ 3*9 ]; }; は、C言語で長さの上限がわかっている文字列を使う際のイディオム。このように構造体の中に配列を入れておくと返戻値としてそのまま使えるし、バッファオーバーランしにくいので便利。

1
1
1

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
1