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のスキルチェック過去問を解きました。

今回はこちらの「神経衰弱」です。

解いた感じ、書かれているとおりに実装して、シミュレーションすればよいだけですので簡単めでした。
(15分で一発正答でした)

入力が、h個の空白区切り1行のデータのため、そこを受けとるのがめんどくさかったです。

以下はコメントを付与した回答です。

#include <stdio.h>
#include <string.h>
int main(void){
    char buf[100];
    
    // フィールドの縦幅、横幅、プレーヤー数を取得
    int h, w, n;
    fgets(buf, sizeof(buf), stdin);
    sscanf(buf, "%d %d %d", &h, &w, &n);
    
    // カードの配置を取得
    int field[13][13];
    for(int i = 0; i < h; i++) {
        char buf[13 * 3 + 1];
        int j = 0;
        fgets(buf, sizeof(buf), stdin);
        char *ptr = strtok(buf, " ");
        while(ptr != NULL) {
            sscanf(ptr, "%d", &field[i][j++]);
            ptr = strtok(NULL, " ");
        }
    }
    
    // ターン数を取得
    int l;
    fgets(buf, sizeof(buf), stdin);
    sscanf(buf, "%d", &l);
    
    // 各ターンの記録を取得
    // [0]: 1枚目の縦位置, [1]: 1枚目の横位置, [2]: 2枚目の縦位置, [3]: 3枚目の横位置
    int log[200][4];
    for(int i = 0; i < l; i++) {
        fgets(buf, sizeof(buf), stdin);
        sscanf(buf, "%d %d %d %d", &log[i][0], &log[i][1], &log[i][2], &log[i][3]);
    }
    
    // 入力を正常に受けとれたか確認
#if 0
    printf("%d %d %d %d\n", h, w, n, l);
    for(int i = 0; i < h; i++) {
        for(int j = 0; j < w; j++) {
            printf("%d ", field[i][j]);
        }
        printf("\n");
    }
    printf("%d\n", l);
    for(int i = 0; i < l; i++) {
        for(int j = 0; j < 4; j++) {
            printf("%d ", log[i][j]);
        }
        printf("\n");
    }
#endif

    // ここから解答
    
    int result[10] = {0}; // 最終的な出力結果(プレーヤーの取り分記録)
    int player_num = 0; // 手番のプレーヤー番号(0はじまり)
    int remain = h * w; // 残りカード数(一応実装したけど、いらんかったみたい)
    
    // 各ターンをシミュレートしていく
    for(int i = 0; i < l; i++) {
        int x = log[i][0] - 1;
        int y = log[i][1] - 1;
        int X = log[i][2] - 1;
        int Y = log[i][3] - 1;
        
        // カードの表記が一致していたら、そのプレーヤーの取り分へ2枚加算
        // 残りカード数から2枚減算
        if(field[x][y] == field[X][Y]) {
            result[player_num] += 2;
            remain -= 2;
        }
        // 一致していなかったら、次のプレーヤーの番へ
        else {
            player_num = (player_num + 1) % n;
        }
        
        // 残りカード数が0になったら、ゲーム終了
        if(remain <= 0) {
            break;
        }
    }
    
    // 最終的な出力
    for(int i = 0; i < n; i++) {
        printf("%d\n", result[i]);
    }
}

書かれている通りに実装しているだけです。

プレーヤーの順番をループさせなければならないところが大事だと思いました。

(プレーヤー番号は0はじまりで)
0 -> 1 -> 2 -> 3 -> 0 -> 1 -> 2 -> ...

となるので、番号が[4]になったら[0]へ戻すので、プレーヤー数の4で割った余りをとります。

終わりに

今回は、配列等の確保が入力の最大値までとなるように気をつかったのですが、もしかしたら思い違いで、境界値を入れるとランタイムエラーを起こすかもしれません。

それでは、引き続き他の問題を練習していきます。

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?