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

次に解いたのは、Bランク・スキルチェック過去問の「名刺バインダー管理」です。

一発正答でいけましたが、なかなか法則をプログラムに落とし込めず、40分もかかってしまいました。

これは、シミュレーション問題ではなく、法則を見つけることで解くことができましたが、実際に名刺バインダーの配列を作って番号を配置することでも解ける気がしました。

ひとまず、悩みつつ書いたコードは以下の通りです。

#include <stdio.h>
#include <math.h>
int main(void){
    char buf[100];
    int pocket_num, target_num;
    fgets(buf, sizeof(buf), stdin);
    sscanf(buf, "%d %d", &pocket_num, &target_num);
    
    //printf("%d %d", pocket_num, target_num);
    
    /*
        ポケットの数が3の場合の、裏表の対応
        1 <-> 6   => 足したら7 (= 3 * (2 * 1) + 1)
        2 <-> 5   => 7
        3 <-> 4   => 7
        4 <-> 3   => 7
        5 <-> 2   => 7
        6 <-> 1   => 7
        7 <-> 12  => 19 (= 3 * (2 * 3) + 1)
        ...
        10 <-> 9  => 19
        ...
        14 <-> 17 => 31 (= 3 * (2 * 5) + 1)
        
        つまり、解がxの場合、
        target_num + x = pocket_num * (2 * magic_num) + 1
        
        1ページ目は、右辺は7  -> magic_num = 1
        2ページ目は、右辺は7  -> magic_num = 1
        3ページ目は、右辺は19 -> magic_num = 3
        4ページ目は、右辺は19 -> magic_num = 3
        5ページ目は、右辺は31 -> magic_num = 5となる
    */
    
    // 何ページ目に配置されるかは、target_num / pocket_numの解の切り上げ
    int page = ceil((float)target_num / pocket_num);
    
    // 偶数ページ目のmagic_numは、そのページ数を-1する
    int magic_num = page;
    if(page % 2 == 0) {
        magic_num = page - 1;
    }
    //printf("magic [%d]", magic_number);
    
    // target_num + x = pocket_num * (2 * magic_num) + 1を
    // xについて解いた式で求める
    int x = pocket_num * (2 * magic_num) + 1 - target_num;
    
    printf("%d\n", x);
    
    return 0;
}

別解

また、以下のようにも考えられそうです。

ポケットの数が3のとき、

1 => 6 (= 3 * 2 + 1 - 1) 差は-5
2 => 5 (= 3 * 2 + 1 - 2) 差は-3
3 => 4 (= 3 * 2 + 1 - 3) 差は-1
4 => 3 (= 3 * 2 + 1 - 4) 差は1
5 => 2 (= 3 * 2 + 1 - 5) 差は3
6 => 1 (= 3 * 2 + 1 - 6) 差は5

という対応を考え、7以降は、

7 => 7 % (3 * 2) = 1
8 => 8 % (3 * 2) = 2
9 => 9 % (3 * 2) = 3
13 => 13 % (3 * 2) = 1
...

これで、target_numの該当する典型的な位置がわかれば、その数字から、上記の差を足すことで求められそうです。

終わりに

手元で例を書いていくことで、こういう変化があるなということはわかったのですが、それをプログラムへ落とし込むが難しかったです。

たぶん、もっと簡単に解く方法があるのだと思いますが、良い頭の体操にはなりましたのでよしとします。

以上、ここまで読んでいただきありがとうございました。

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?