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?

名刺バインダー管理

Posted at

今回は paiza の「名刺バインダー管理」の問題に挑戦!


問題概要

状況

  • 名刺は「ファイル」に収められている。
  • 1ファイルには n個のポケット が横に並んでいて、1ポケットに「表と裏」の2枚の名刺が入っている。
  • したがって 1ファイルに 2n枚の名刺 がある。

並び方

  • 表:1〜n 番が左から順に並ぶ
  • 裏:n+1〜2n 番が左から順に並ぶ
  • ただし裏は背中合わせなので、「表の左端 ↔ 裏の右端」がペアになる。

与えられるもの

  • n(ポケット数)
  • m(調べたい名刺番号)

求めるもの

  • m番の名刺の裏側の番号」



入力例:

3 1 // n m

出力例:

6






✅OK例:

const rl = require('readline').createInterface({ input:process.stdin });
const lines = [];

rl.on('line', (input) => lines.push(input));

rl.on('close', () => {
    const [n, m] = lines[0].split(' ').map(Number);

    const file = Math.floor((m - 1) / (2 * n));
    const pos = (m - 1) % (2 * n);
    const pairPos = 2 * n - 1 - pos;
    const result = file * 2 * n + pairPos + 1;

    console.log(result);
});

全体のアイデア

  • 1つのファイルには 表 n 枚 + 裏 n 枚 = 2n 枚 が入っている。

  • m がどのファイル(0始まり)にあるかを求め、そのファイル内での位置を見れば、同じポケットの裏側の位置がすぐに求まる。

  • 実装は「0始まりに直して考える」のが楽 → m-1 を使う。




図解で理解する「バインダーの構造」

例:n = 3 の場合
→ 1ファイルには「表 3 枚 + 裏 3 枚 = 6 枚」が入っている

表から見た場合(左→右)
+---+---+---+
|  1|  2|  3|
+---+---+---+

裏から見た場合(左→右)
+---+---+---+
|  4|  5|  6|
+---+---+---+

でも実際は「ポケット」が3つあり、1つのポケットに2枚(表と裏)が背中合わせで入っている。

  • ポケット 1: 表=1, 裏=6
  • ポケット 2: 表=2, 裏=5
  • ポケット 3: 表=3, 裏=4




🔍 コードの詳しい説明

① どのファイルか?

const file = Math.floor((m - 1) / (2 * n));

  • m-1 で 0始まり に変換(例: m=10)。
  • 2*n ごとにファイルが区切られているので、商を取れば 何番目のファイルか(0始まり)になる。
    (1ファイルに 2n 枚入っているので、(m-1)/(2*n) の商でファイル番号が決まる)

例:n=3 のとき、2*n = 6

  • m = 1 ~ 6file = 0(1枚目のファイル)
  • m = 7 ~ 12file = 1(2枚目のファイル)



② ファイル内の位置

const pos = (m - 1) % (2 * n);

  • ファイル内での 相対位置(0〜2n-1) を求める。
  • そのファイルの中で左から何番目か(0始まり)
  • 0 がそのファイルの先頭(左端の表)、2n-1 がそのファイルの最後(右端の裏)。

例(n=3):

  • m=1pos=0
  • m=3pos=2
  • m=4pos=3
  • m=6pos=5

n=3 なら pos の範囲は 0〜5

図で書くとこう:

pos:   0   1   2   3   4   5 (→ 0 ~ 2n-1)
表:    1   2   3
裏:                4   5   6



③ 裏側の位置

const pairPos = 2 * n - 1 - pos;

  • 同じポケットの裏側はファイル内で鏡像の位置にある、という性質を使っている。

  • ファイル内のインデックスを 0 ~ (2n-1) とすると、「ペアは pos2n-1 – pos」 の組。

  • 直感的な考え方:左から i 番目(0始まり)のポケットの表は pos = i、同じポケットの裏は右から i 番目に相当するので 2n-1 – i
    ※ 再掲:2n-1 = そのファイルの最後(右端の裏)


例(n=3):

  • pos=0 のペア → pairPos = 5 (1 ↔ 6)
  • pos=1 のペア → pairPos = 4 (2 ↔ 5)
  • pos=2 のペア → pairPos = 3 (3 ↔ 4)
  • pos=3 のペア → pairPos = 2(裏側のカードが表側に対応)



④ 全体での番号に戻す

const result = file * 2 * n + pairPos + 1;

  • file * 2 * n でそのファイルの先頭(1始まりで言うと file*2n + 1)に相当するセットを作る。

  • pairPos を足して ファイル内での位置 を指定し、最後に +1 で 1始まりの番号に戻す。

  • そのファイルの 「基準位置」= file*2*n に、裏の位置 pairPos を足して、さらに +1 で1始まりに戻す。

  • つまり「ファイル先頭 + ファイル内の位置 + 1」= 裏側の元の番号。


例(n=3):

  • m=1file=0, pos=0, pairPos=5result = 0 + 5 +1 = 6 → 1番の裏は6番!
  • m=4file=0, pos=3, pairPos=2result = 0 + 2 +1 = 3
  • m=7file=1, pos=0, pairPos=5result = 6 + 5 +1 = 12






📝 まとめ

  • file:その名刺が入っているファイル(0始まり)
  • pos:ファイル内での位置(左から 0 .. 2n-1)
  • pairPos:同じポケットの裏側はファイル内で反転した位置 → 2n-1-pos
  • result:そのファイルの先頭に pairPos を足して 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?