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?

「ビームの反射」を解くために:part2

Posted at

今回は paiza の「「ビームの反射」を解くために:part2」の問題に挑戦!

「ビームの反射」では、壁にビームが当たった時の反射方向を求める必要があるので、これを練習してみる!


問題概要

■ 問題の内容

  • 箱の中を進む ビームの進行方向の変化 をシミュレーションする問題。

  • ビームは 最初「右向き」 に進み、
    各区画にある「鏡」または「空白」に応じて方向を変えたり、そのまま通過したりする。
    与えられた N 個の区画を順に処理し、その都度の進行方向を出力する。


■ 入力

N
x_1
x_2
...
x_N
  • N:壁(または区画)の数
  • x_i は以下のいずれか
    • '_' → 鏡なし(そのまま進む)
    • '/' → 右上がり鏡(反射で進行方向が変わる)
    • '\' → 右下がり鏡(反射で進行方向が変わる)

■ 出力

  • 各区画を通過または反射したときのビームの向きを、毎回出力する。

方向表現:

  • 右向き → '1 0'
  • 左向き → '-1 0'
  • 上向き → '0 -1'
  • 下向き → '0 1'



入力例:

5
\
\
_
\
\

出力例:

0 1
1 0
1 0
0 1
1 0






✅ OK例:

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

const lines = [];

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

rl.on('close', () => {
   const N = Number(lines[0]);
   const x = lines.slice(1);

   let beam = '1 0'; // 初期方向は右向き

   for (let i = 0; i < N; i++) {
       const mirror = x[i];

       if (mirror === '_') {
           console.log(beam);
       } else if (mirror === '/') {
           // / の反射ルール
           if (beam === '1 0') beam = '0 -1';
           else if (beam === '-1 0') beam = '0 1';
           else if (beam === '0 -1') beam = '1 0';
           else if (beam === '0 1') beam = '-1 0';
           console.log(beam);
       } else if (mirror === '\\') {
           // \ の反射ルール
           if (beam === '1 0') beam = '0 1';
           else if (beam === '-1 0') beam = '0 -1';
           else if (beam === '0 -1') beam = '-1 0';
           else if (beam === '0 1') beam = '1 0';
           console.log(beam);
       }
   }
});

💡 コードの流れ

① 標準入力の準備

  • readline を使って入力を1行ずつ読み込む。
  • すべての入力を lines 配列に保存。

② 入力終了時の処理 (rl.on('close'))

  • 1行目(lines[0])から壁の個数 N を取得。
  • 2行目以降(lines.slice(1)) に各壁の記号 '_', '/', '\' を格納した配列 x を作る。

③ 初期状態の設定

  • 最初のビームの向きを右向き "1 0" として変数 beam にセット。

④ 全ての壁を順番に処理(forループ)

  • 各壁の種類を mirror に取り出す。

⑤ 鏡が '_'(空白)なら

  • 鏡が '_'(空白)なら
  • 方向は変わらないので、そのまま beam を出力。

⑥ 鏡が '/' の場合

  • 進行方向を「/」反射のルールに従って変更:

    • 入射方向 → 反射後方向
      • 右(1 0)→ 上(0 -1
      • 左(-1 0)→ 下(0 1
      • 上(0 -1)→右(1 0
      • 下(0 1)→左(-1 0
  • 更新後の beam を出力。


⑦ 鏡が '\' の場合

  • 進行方向を「\」反射のルールに従って変更:

    • 入射方向 → 反射後方向
      • 右(1 0)→ 上(0 1
      • 左(-1 0)→ 下(0 -1
      • 上(0 -1)→右(-1 0
      • 下(0 1)→左(1 0
  • 更新後の beam を出力。


⑧ 全ての壁を処理し終えたら終了






✅ ベクトル版

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

const lines = [];

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

rl.on('close', () => {
   const N = Number(lines[0]);
   const x = lines.slice(1);

   // 初期のビーム方向(右向き)
   let dx = 1;
   let dy = 0;

   for (let i = 0; i < N; i++) {
       const mirror = x[i];

       if (mirror === '/') {
           // 「/」の場合:dx, dy を入れ替えて両方の符号を反転
           [dx, dy] = [-dy, -dx];
       } else if (mirror === '\\') {
           // 「\」の場合:dx, dy を入れ替える
           [dx, dy] = [dy, dx];
       }

       // "_" の場合はそのまま通過(変更なし)
       console.log(`${dx} ${dy}`);
   }
});

💡 コードの流れ

① 入力(省略)

② 初期状態の設定

  • ビームの初期方向をベクトルで表現:
    • dx = 1, dy = 0(右向き)
      • dx, dy の意味:
        → 右 (+1, 0)、左 (-1, 0)、上 (0, -1)、下 (0, +1)

③ 全ての壁を順に処理(forループ)

  • 各壁の種類を mirror に代入。

④ 鏡が '/' の場合

  • 進行方向を / に反射させるために、
[dx, dy] = [-dy, -dx];

として dx, dy を入れ替え、両方の符号を反転。

これにより進行方向が正しく反転する。

⑤ 鏡が '\' の場合

  • \」は逆向きの斜め鏡。
[dx, dy] = [dy, dx];

として dxdy を単に入れ替える。

⑥ 鏡が '_' の場合

  • 反射しない(方向そのまま)。

⑦ 各ステップの進行方向を出力

  • 反射後または通過後の (dx, dy) を "dx dy" 形式で console.log

⑧ ループ終了でプログラム完了






📝まとめ

  • ビームの初期方向は「右向き」
    → (dx, dy) = (1, 0) または "1 0"
  • 鏡ごとに方向の変換ルールがある
    • '/' : [dx, dy] = [-dy, -dx](両方の軸を入れ替えて符号反転)
    • '\' : [dx, dy] = [dy, dx](軸を単純に入れ替える)
    • '_' : 変更なし(通過)
  • 進行方向は4方向だけ
    • 右 (1,0) / 左 (-1,0) / 上 (0,-1) / 下 (0,1)
  • 各ステップで反射後の方向を即時出力
    console.log(${dx} ${dy});
  • ベクトルで方向を管理するとシンプル
    • 条件分岐を減らせて、数学的にスッキリ書ける。
    • 反射は「軸の入れ替え+符号の変化」で表現できる。
  • テキスト入力の注意
    • \\(バックスラッシュ)は文字化けしやすいので、サンプル入力からコピペ推奨。




僕の失敗談(´;ω;`)と解決法🐈

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?