0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

paiza Bランク・スキルチェック過去問題「みんなでしりとり C編」を沼りながら解いた

Posted at

以下の、paiza Bランク スキルチェック過去問「みんなでしりとり」をC言語で解きました。

解答へコメントを付与して、簡単に覚書しておきます。

解くのにだいぶ難航して、合計20回くらいデバッグ出力と誤答を繰り返しました。

真っ当に順当にしりとりを判定して、シミュレーションをするという戦略をとりました。
そのためか、ソースコードは長いです。

では、最終的なコードは以下の通りです。

#include <stdio.h>
#include <string.h>
int main(void){
    
    // 入力受け取り(人数、キーワード数、発言数)
    char buf[100];
    int people_num, keyword, meme;
    fgets(buf, sizeof(buf), stdin);
    sscanf(buf, "%d %d %d", &people_num, &keyword, &meme);
    
    // 入力受け取り(キーワード一覧)
    char keywords[1000][100];
    for(int i = 0; i < keyword; i++) {
        fgets(keywords[i], sizeof(keywords[i]), stdin);
        keywords[i][strlen(keywords[i])-1] = '\0';
        //printf("%s\n", keywords[i]);
    }
    
    // 参加メンバーリスト作成(1でゲーム残留、0で敗退)
    int people[10];
    for(int i = 0; i < people_num; i++) {
        people[i] = 1;
    }
    
    // ここからゲーム開始
    
    int count = 0; // メンバーリストの現在地インデックス
    char mae = '\0'; // しりとりのための最後尾文字
    
    // 発言数分処理を繰り返す
    for(int i = 0; i < meme; i++) {
        
        int flag = 0; // ゲームへの残留/敗退判定フラグ(最初は敗退状態からはじめる)
        
        char buf[100];
        fgets(buf, sizeof(buf), stdin);
        
        // 文字列の改行が邪魔なので、改行がついていたら、削除する(改行を文字列終端に置き換える)
        if(buf[strlen(buf)-1] == '\n') {
            buf[strlen(buf)-1] = '\0';
        }
        
        // 発言文字列がキーワード一覧に存在するか確認する
        for(int j = 0; j < keyword; j++) {
            //printf(">>%s %s<<\n",buf, keywords[j]);
            if(strcmp(keywords[j], buf) == 0) {
                flag = 1; // キーワードが存在したら、フラグを残留状態へ倒す
                // キーワードの再使用は禁止なので、
                // 1文字目を文字列終端に置き換えて、簡易的に使用キーワードを削除する
                keywords[j][0] = '\0'; 
                break;
            }
        }
        
        // キーワードが存在したら、次に'z'で終わっている文字列かチェックする
        if(flag == 1 && buf[strlen(buf)-1] == 'z') {
            flag = 0; // zで終わっていたら敗退状態へ
        }
        
        //printf("[%c][%c]\n", mae, buf[0]);
        
        // フラグが残留状態だったら、しりとり条件の判定をする
        if(flag == 1) {
            // 最後尾文字が\0でないなら、しりとり条件の判定が必要
            if(mae != '\0') {
                // 最後尾文字と新しい発言の冒頭文字が一致しなかったら、しりとり失敗
                // フラグを敗退状態へ
                if(mae != buf[0]) {
                    flag = 0;
                }
            }
        }
        
        //printf("%s %d %d\n", buf, count, flag);
        
        // フラグが敗退状態だったら、メンバーリストに敗退を記録する
        if(flag == 0) {
            people[count] = 0;
            mae = '\0'; // ゲームのしりとり条件をリセットするため、最後尾文字を\0にしておく
        }
        else {
            mae = buf[strlen(buf)-1];
        }
        
        // 次の順番のメンバーを探索する
        do {
            // countをインクリメントして、人数をはみ出る場合はループで0に戻す
            count++;
            if(count >= people_num) {
                count = 0;
            }
            // 残留メンバーが1人かどうかを判定し、1人だったらゲーム終了
            int sum = 0;
            for(int i = 0; i < people_num; i++) {
                sum += people[i];
            }
            if(sum == 1) {
                break;
            }
            
        } while(people[count] != 1); // 残留状態ではないメンバーだったら、再度ループ処理(次のメンバーのチェックへ)
    }
    
    // ここから結果を出力する
    
    // 残留メンバーをカウントする
    int result = 0;
    for(int i = 0; i < people_num; i++) {
        if(people[i] == 1) {
            result++;
        }
    }
    
    printf("%d\n", result);
    
    // 残留メンバーリスト出力
    for(int i = 0; i < people_num; i++) {
        if(people[i] == 1) {
            printf("%d\n", i+1);
        }
    }
    
    
    return 0;
}

難航ポイント

難航したポイントは、

  • キーワード、発言へ付与される改行が邪魔で、判定が正常にならない
  • メンバーのターンの順番がループするのを忘れた
  • 残留メンバーが1人になったときにwhileループをbreakするのを忘れて、無限ループを起こす

こんな感じでした。

終わりに

難航ポイントを踏まえると、もうちょっと慎重に実装することが必要だなと思いました。

部分正答みたいな回答が何度もあったため、条件の吟味が必要ですね。

特に0 -> 1 -> 2 -> 0 -> 1 -> ...みたいなインデックスのループ処理を忘れやすいです。

ここを今後は意識していきたいです

0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?