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?

リバーシの操作(縦横)

Last updated at Posted at 2025-12-17

今回は paiza の「リバーシの操作(縦横)」の問題に挑戦!


問題概要

  • H 行、横 W 列の盤面が与えられる
  • 盤面にはすでに
    • '*':自分の石が置かれているマス
    • '.'`:何も置かれていないマス
      が存在する
  • 指定されたマス (Y, X) は必ず '.' であり、ここに 新しく石を1つ置く
  • 石を置いたあと、以下のルールで石を増やす

石を増やすルール

  • 新しく置いた石 (Y, X) から
  • 上・下・左・右 の4方向をそれぞれ調べる
  • ある方向について
    • '*' → '.' → '.' → … → '*' のように、両端が自分の石 '*' ではさまれている 場合、
      → その間にある '.' をすべて '*' にする
  • 盤面の外に出る、または '*' に到達できなかった方向は何もしない
  • 連鎖的に増えた石による追加処理は行わない
    • あくまで「最初に置いた石」による1回の操作のみ

操作後の盤面を上から順に H 行出力する



入力例:

3 3 0 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, Y, X] = lines[0].split(' ').map(Number);
    const grid = lines.slice(1).map(line => line.split(''));
    
    let startRow = Infinity;
    let startCol = Infinity;
    let endRow = -Infinity;
    let endCol = -Infinity;
    
    // 縦
    for (let i = 0; i < H; i++) {
        if (grid[i][X] === '*' && i < Y) {
            startCol = i;
        } else if (grid[i][X] === '*' && i > Y) {
            endCol = i;
            break;
        }
    }
    
    for (let i = Math.min(startCol, Y); i < Math.max(endCol, Y+1); i++) {
        grid[i][X] = '*'
    }
    
    // 横
    for (let i = 0; i < W; i++) {
        if (grid[Y][i] === '*' && i < X) {
            startRow = i;
        } else if (grid[Y][i] === '*' && i > X) {
            endRow = i;
            break;
        }
    }
    
    for (let i = Math.min(startRow, X); i < Math.max(endRow, X+1); i++) {
        grid[Y][i] = '*'
    }
    
    // 出力
    grid.forEach(g => console.log(g.join('')));
});

🔍コードの流れ

  • 入力を読み込み、
  • 盤面サイズ H, W、石を置く座標 Y, X、盤面 grid を作成する
  • 縦方向・横方向で、はさむ石の 開始位置と終了位置 を記録する変数を用意する

縦方向の処理

  • X を上から下へ走査する
  • (Y, X) より 上側にある一番近い '*'startCol に記録
  • (Y, X) より 下側で最初に見つかった '*'endCol に記録して探索終了
  • startColendCol の範囲をすべて '*' にする

横方向の処理

  • Y を左から右へ走査する
  • (Y, X) より 左側にある一番近い '*'startRow に記録
  • (Y, X) より 右側で最初に見つかった '*'endRow に記録して探索終了
  • startRowendRow の範囲をすべて '*' にする

出力

  • 更新後の盤面を 1 行ずつ出力する






✨OK例:

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

const lines = [];

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

rl.on('close', () => {
  const [H, W, Y, X] = lines[0].split(' ').map(Number);
  const grid = lines.slice(1).map(row => row.split(''));

  // まず石を置く
  grid[Y][X] = '*';

  // 4方向(上・下・左・右)
  const directions = [
    [-1, 0], // 上
    [1, 0],  // 下
    [0, -1], // 左
    [0, 1],  // 右
  ];

  for (const [dy, dx] of directions) {
    let ny = Y + dy;
    let nx = X + dx;

    const path = []; // この方向で通過したマス

    // 盤面内を進む
    while (0 <= ny && ny < H && 0 <= nx && nx < W) {
        
      if (grid[ny][nx] === '*') {
          
        // はさめた → 間をすべて '*'
        for (const [py, px] of path) {
          grid[py][px] = '*';
        }
        
        break;
      }
      
      // 通過マスを保存
      path.push([ny, nx]);
      
      // 次のマスへ
      ny += dy;
      nx += dx;
    }
  }

  // 出力
  console.log(grid.map(row => row.join('')).join('\n'));
});

🔍 コードの流れ

  • 入力をすべて読み込み、
    盤面サイズ H, W と石を置く座標 Y, X、盤面 grid を作成する
  • 指定されたマス (Y, X) に石 '*' を置く
  • 上・下・左・右の 4方向を順番に調べる
  • 各方向について
    • (Y, X) の隣のマスから探索を開始する
    • 探索中に通ったマスを path に記録する
  • 探索中に
    • 盤面の外に出たら → その方向は何もしない
    • '*' が見つかったら → path に記録したマスをすべて '*' にする(はさみうち成立)
  • 4方向すべての処理が終わったら、最終的な盤面を出力する






📝まとめ

  • 二次元配列で盤面を管理すると処理しやすい
  • 処理は 4方向(上・下・左・右)を独立して考える
  • 各方向でやることは同じ
    • 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?