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?

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

0
Last updated at Posted at 2025-11-02

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

「ビームの反射」では、箱の区画を移動していき、通過回数を求める必要があるので、これを練習する問題を解いていく!


問題概要

箱の中にある各マスには、
ビームの「進行方向を指示する文字」が書かれている。

記号:指示の意味

  • R : ビームの向きを右にする
  • L : ビームの向きを左にする
  • U : ビームの向きを上にする
  • D : ビームの向きを下にする
  • S : ビームの向きを変更せず、直進させる

🚀 ビームの動作ルール

  • ビームは 左上のマス (0,0) に対して
  • 左の外部から右向き(→) に撃ち込まれる。
    → 最初の進行方向は R(右)
  • ビームが箱の外に出た時点で終了。
  • 通過したマスの回数 を出力。

🧮 入力形式

H W
s_1
s_2
...
s_H
  • H: 高さ(行数)
  • W: 幅(列数)
  • s_i は長さ W の文字列で、
    各文字は R, L, U, D, S のいずれか。



入力例:

3 5
SSDUR
ULSSS
LSRSU

出力例:

9






✅OK例:

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

rl.on('line', (input) => lines.push(input));
rl.on('close', () => {
    const [H, W] = lines[0].split(' ').map(Number);
    const s = lines.slice(1).map(line => line.split(''));

    let x = 0;
    let y = 0;
    let dir = 'R'; // 初期方向は右向き
    let count = 0;

    while (true) {
        // 範囲外に出たら終了
        if (x < 0 || x >= W || y < 0 || y >= H) break;

        const cell = s[y][x];
        count++;

        if (cell === 'R') dir = 'R';
        else if (cell === 'L') dir = 'L';
        else if (cell === 'U') dir = 'U';
        else if (cell === 'D') dir = 'D';
        // 'S' の場合は向きを変えずに進む

        // 次の位置に進む
        if (dir === 'R') x++;
        else if (dir === 'L') x--;
        else if (dir === 'U') y--;
        else if (dir === 'D') y++;
    }

    console.log(count);
});

💻 コードの流れ

  1. 入力受付の準備
    • readline モジュールで標準入力を受け取る準備をする。
    • 入力行を lines 配列に順次格納。
  2. 入力完了時 (close イベント発火)
    • 最初の1行目(lines[0])から高さ H と幅 W を取得。
    • 例: "3 4" → H=3, W=4
    • 残りの行(マップ部分)を2次元配列 s に変換。
    • つまり、s[y][x] で各マスの文字(R/L/U/D/S)が取れるようにする。
  3. 初期状態を設定
    • ビームの開始位置を (x, y) = (0, 0) に設定。
      (左上スタート)
    • 進行方向 dir"R"(右向き)に設定。
    • 通過したマスのカウント count = 0
  4. ループでビームを進める
    • while (true) で無限ループを開始。
    • まず、範囲外チェック。
      → 画面外に出たら break でループ終了。
  5. 現在のマスを確認
    • const cell = s[y][x]; で現在位置の文字を取得。
    • 通過回数をカウント:count++
  6. マスの内容によって進行方向を変更
    • R → 右向き (dir = 'R')
    • L → 左向き (dir = 'L')
    • U → 上向き (dir = 'U')
    • D → 下向き (dir = 'D')
    • S → 向きを変えずにそのまま進む(dirはそのまま)
  7. 次のマスへ進む
    • 現在の dir に応じて (x, y) を更新。
      • 右:x++
      • 左:x--
      • 上:y--
      • 下:y++
  8. 次ループへ → 範囲外になったら終了
  9. 結果出力
    • 通過したマスの総数 countconsole.log() で出力。






📝まとめ

1️⃣ 入力は文字列→2次元配列化
s[y][x] でマスを直接参照できるように。

2️⃣ 初期向きは常に「右」
→ 左上マスに左側から入る。

3️⃣進行方向の更新はマスの文字で決まる

4️⃣ 移動処理の基本構造

if (dir === 'R') x++;
else if (dir === 'L') x--;
else if (dir === 'U') y--;
else if (dir === 'D') y++;

5️⃣ ループの終わりは「範囲外チェック」だけでOK
if (x < 0 || x >= W || y < 0 || y >= H) break;

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?