今回は paiza の「裏返せる可能性(斜め)」の問題に挑戦!
問題概要
- 縦
H行、横W列の盤面 - 指定されたマス (
Y,X) に 石を 1 つ置く - 盤面の各マスは次のルールで文字を決める
ルール
- 石を置いたマス
(Y, X)→'!' -
(Y, X)を通る 斜め方向(4方向) にあるすべてのマス →'*' - 上記以外のマス →
'.'
座標について
- 左上が (0, 0)
- 下方向が y の正
- 右方向が x の正
条件に従って作成した盤面を 上から順に H 行出力 する
入力例:
3 3 0 0 // H W Y X
出力例:
!..
.*.
..*
✅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 = Array.from({ length: H }, () => Array(W).fill('.'));
grid[Y][X] = '!';
const direction = [
[-1, 1],
[1, 1],
[1, -1],
[-1, -1]
]
for (const d of direction) {
const [dy, dx] = d;
let ny = Y + dy;
let nx = X + dx;
while (0 <= ny && ny < H && 0 <= nx && nx < W) {
grid[ny][nx] = '*';
ny += dy;
nx += dx;
}
}
grid.forEach(g => console.log(g.join('')));
});
🔍 コードの流れ
- 標準入力を1行ずつ読み込み、配列
linesに格納する - 入力の1行目から、盤面の高さ
H、幅W、石の座標 (Y,X) を取得する - すべて
'.'で埋めたH×Wの盤面gridを作成する - 石を置くマス
(Y, X)に'!'をセットする - 斜め4方向(右上・右下・左下・左上)を表す移動量を
directionに定義する - 各斜め方向について処理を行う
- 現在位置を
(Y, X)の1マス先に設定する - 盤面の範囲内にいる間、同じ方向に進み続ける
- 通過するマスを
'*'にする
- 現在位置を
- すべての斜め方向の処理が終わったら
- 盤面を1行ずつ文字列にして出力する
✅OK例 2:
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 = Array.from({ length: H }, () => Array(W).fill('.'));
for (let i = 0; i < H; i++) {
let row = '';
for (let j = 0; j < W; j++) {
if (i === Y && j === X) {
row += '!';
} else if (Math.abs(i - Y) === Math.abs(j - X)) {
row += '*';
} else {
row += '.';
}
}
console.log(row);
}
});
|i - Y| === |j - X|
が成り立つとき、
(Y, X) から見て「縦に進んだ分」と「横に進んだ分」が同じなので、
そのマスは必ず斜め方向にある。
ポイント
- 斜め = 縦の差と横の差が同じ
- 全方向対応 → 絶対値
- 中心マスは別処理
📝まとめ
- 斜め方向は 4方向 ある
- 斜め移動は
(dy, dx)の組で表せる- (-1, 1):右上
- (1, 1):右下
- (1, -1):左下
- (-1, -1):左上
- ある方向に対して
- 1マスずつ同じ (
dy,dx) を足しながら進む - 盤面の外に出るまで
'*'を置き続ける
- 1マスずつ同じ (
- 中心マス
(Y, X)は'*'にしてはいけないため 必ず別処理で'!'にする - 別解として
- 全マス走査 + 条件分岐 でも解ける
-
Math.abs(i - Y) === Math.abs(j - X)
→(Y, X)から見て斜め方向にあるマス
- 絶対値を使うことで、4方向すべてを 1つの条件式 で表現できる