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 の「移動が可能かの判定・複数回の移動」の問題に挑戦!


問題概要

  • マップの大きさ(H×W)と、移動者の初期座標 (sy, sx)、移動回数 N が与えられる
  • マップは '.'(移動可能)、'#'(障害物)で構成される
  • 続いて N 回分、L(左に曲がる)か R(右に曲がる)が与えられる
  • 移動者は 最初は「北」を向いている
  • 1 回の移動で行うこと
    ① 指示に従い左/右へ 方向転換する
    ② その向きに 1 マス進む
  • 移動できる条件
    → 移動先が マップ内 かつ '.'
  • 条件を満たせばその座標を出力
  • 条件を満たさない場合
    "Stop" を出力して 以降の移動は全て中止



入力例:

7 3 2 1 5
..#
...
...
...
..#
.#.
##.
L
L
L
L
L

出力例:

2 0
3 0
3 1
2 1
2 0






✅OK例:

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

const lines = [];

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

rl.on('close', () => {
    const [H, W, sy, sx, N] = lines[0].split(' ');
    const grid = lines.slice(1, Number(H)+1).map(line => line.split(''));
    const d = lines.slice(Number(H)+1);
    
    let movedY = Number(sy);
    let movedX = Number(sx);
    let dir = 'N';
    
    for (let i = 0; i < Number(N); i++) {
        const LR = d[i];
        
        if (dir === 'N') {
            if (LR === 'L') {
                movedX--;
                dir = 'W';
            } else { // === 'R'
                movedX++;
                dir = 'E'
            }
        }
        else if (dir === 'S') {
            if (LR === 'L') {
                movedX++;
                dir = 'E';
            } else {
                movedX--;
                dir = 'W';
            }
        }
        else if (dir === 'E') {
            if (LR === 'L') {
                movedY--;
                dir = 'N';
            } else {
                movedY++;
                dir = 'S';
            }
        } 
        else { // === 'W'
            if (LR === 'L') {
                movedY++;
                dir = 'S';
            } else {
                movedY--;
                dir = 'N';
            }
        }
        
        if (movedY >= 0 && movedY < Number(H) && movedX >= 0 && movedX < Number(W) && grid[movedY][movedX] === '.') {
            console.log(movedY, movedX);
        } else {
            console.log('Stop');
            return;
        }
    }
});

🧭 コードの処理の流れ

  1. 標準入力を1行ずつ読み取る
  2. 読み取り完了後、処理開始 (closeイベント)
  3. 1行目から
    • H: マップの高さ
    • W: マップの幅
    • sy: 初期 y 座標
    • sx: 初期 x 座標
    • N: 移動回数
      を取得
  4. 続く H 行を読み取り、 ., # が入った マップ配列gridを作成
  5. 残り N 行の入力を移動指示 d[](L or R)として取得
  6. 現在位置 (movedY, movedX) を初期値 (sy, sx) に設定
  7. 現在向き dir'N'(北)で初期化
  8. N 回分ループ
    • 指示が L なら左回転 → 1 マス進む
    • 指示が R なら右回転 → 1 マス進む
      ※ 進む方向と新しい向きは dir に応じて決定
  9. 移動後のマスが
    • マップ範囲内
    • '.'(通行可)
      なら → 座標を出力
  10. 移動不可なら "Stop" を出力し 即終了
  11. すべての移動が成功したら、全座標を出力し終了






📝まとめ

  • 向き(方向)を状態として持ち、更新しながら進む問題
  • 回転によって向きが変わるため、進む方向は毎回異なる可能性がある
  • マップ範囲外チェックと障害物チェックを毎回行うのが重要
  • 失敗時は即終了する制御(return / break
  • 文字入力を正しく配列/数値へ変換する必要がある (split, Numberなど)
  • 座標系の向きに注意
    • y:下に行くほど +
    • x:右に行くほど +
  • 「移動 → 判定」の順番






🚀 おまけ:短縮版コード

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

const lines = [];

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

rl.on('close', () => {
    const [H, W, sy, sx, N] = lines[0].split(' ').map(Number);
    const grid = lines.slice(1, H + 1).map(line => line.split(''));
    const moves = lines.slice(H + 1);

    let y = sy;
    let x = sx;

    // 0:北, 1:東, 2:南, 3:西
    let dir = 0;
    const dy = [-1, 0, 1, 0];
    const dx = [0, 1, 0, -1];

    for (let i = 0; i < N; i++) {
        const m = moves[i];

        // L = 左回転(-1), R = 右回転(+1)
        if (m === 'L') dir = (dir + 3) % 4;
        else dir = (dir + 1) % 4;

        const ny = y + dy[dir];
        const nx = x + dx[dir];

        if (ny >= 0 && ny < H && nx >= 0 && nx < W && grid[ny][nx] === '.') {
            y = ny;
            x = nx;
            console.log(y, x);
        } else {
            console.log('Stop');
            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?