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?

【マップの扱い 3】マップの判定・縦横斜め

Posted at

今回は paiza の「【マップの扱い 3】マップの判定・縦横斜め」の問題に挑戦!

前と違うのは、周囲1マスの縦横斜めではなくて、縦横斜めのラインすべてを書き換えること!


問題概要

〇 入力

  • 盤面の行数 H と列数 W
  • 盤面 S_0 … S_(H-1)
  • 操作対象の座標 y, x

〇 処理内容

  • 指定座標 (y, x) と 同じ縦・横・斜めにあるすべてのマス を対象とする
  • 対象マスの文字を書き換える
    • .#
    • #.
  • 座標系は左上を (0,0)、下方向が y、右方向が x

〇 出力

  • 処理後の盤面 H 行を出力



入力例:

3 3
##.
###
...
0 0

出力例:

..#
..#
#.#






❌ NG例:

 // 処理する座標
    const targets = new Set();


    // 縦
    for (let i = 0; i < H; i++) {
      targets.add([i, x);
    }

    // 横
    for (let i = 0; i < W; i++) {
      targets.add([y, i]);
    }

    // 斜め
    for (let i = 0; i < Math.max(H, W); i++) {
      if (y + i < H && x + i < W) targets.add([y+i, x+i]);
      if (y + i < H && x - i >= 0) targets.add([y+i, x-i]);
      if (y - i >= 0 && x + i < W) targets.add([y-i, x+i]);
      if (y - i >= 0 && x - i >= 0) targets.add([y-i, x-i]);
    }

Set は「参照の一意性」で判定するため、例えば、[1,2][1,2] でも別物として扱われる。

よって配列のまま Set に入れても重複を除外できない。






✅ 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 [y, x] = lines[H+1].split(' ').map(Number);
    
    const map = lines.slice(1, H+1).map(line => line.split(''));
    
    
    // 処理する座標
    const targets = new Set();


    // 縦
    for (let i = 0; i < H; i++) {
      targets.add(`${i},${x}`);
    }

    // 横
    for (let i = 0; i < W; i++) {
      targets.add(`${y},${i}`);
    }

    // 斜め
    for (let i = 0; i < Math.max(H, W); i++) {
      if (y + i < H && x + i < W) targets.add(`${y+i},${x+i}`);
      if (y + i < H && x - i >= 0) targets.add(`${y+i},${x-i}`);
      if (y - i >= 0 && x + i < W) targets.add(`${y-i},${x+i}`);
      if (y - i >= 0 && x - i >= 0) targets.add(`${y-i},${x-i}`);
    }


    // 処理
    for (const pos of targets) {
      const [ty, tx] = pos.split(',').map(Number);
      map[ty][tx] = map[ty][tx] === '.' ? '#' : '.';
  }

    
    // 出力
    map.forEach(row => console.log(row.join('')));
});
  • 座標を 文字列化(${y},${x}) して Set に格納。

  • 最後に split(',').map(Number) で数値に戻せば良い。

  • Math.min(H, W)(y, x) が盤面の角 にある場合、斜めに移動できる距離は 最大で 縦 H か横 W のどちらか 小さい方 まで必要になる。






🗒️ まとめ


〇 盤面は2次元配列で管理

〇 重複座標の扱い

  • JS の Set は配列やオブジェクトを参照で判定するため、
    例:[1,2][1,2] は別物扱いになる

  • 解決策:座標を文字列化して格納
targets.add(`${y},${x}`);
  • 最後に split(',').map(Number) で数値に戻して処理する

〇 縦・横・斜めの列挙方法

  • 縦: for (let i=0; i<H; i++) targets.add(${i},${x})
  • 横: for (let i=0; i<W; i++) targets.add(${y},${i})
  • 斜め: for (let i=0; i<Math.max(H,W); i++) と 境界条件チェック

〇 書き換え処理は三項演算子で簡潔に

map[ty][tx] = map[ty][tx] === '.' ? '#' : '.';

〇 出力は join で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?