【マップの扱い 4】マップのナンバリング (paizaランク B 相当)
解説
問題文の図は、入力例1のH=4 W=4 D=1ではなく、
入力 H = 3, W = 4, D = 1 ~ 4なので、これでテストした方がよい。
問題文の図を見ながら、法則性を見つけて実装していく。
D=1のときは、ナンバリングのスタートが、0列目固定で、0行目、1行目、2行目と移り変わる。
H-1行までいったら行固定で、今度は1列目,2列目,3列目と移り変わる。
スタートから斜め右上にナンバリングしていく。行は-1、列は+1している。
斜めの最大移動数は、HかWのうち小さい方-1。
マップからはみ出ないようにして、ナンバリングする。
D=2の時は、
0行目固定、列全部ナンバリング、
1行目固定、列全部ナンバリング、
としていく。以下同様
D=3の時は、
0列目固定、行全部ナンバリング、
以下同様。
D=4の時は、ナンバリングのスタートが、
0行目固定で、0列目、1列目、2列目と移り変わる。
W-1列目までいったら、列固定で、今度は1行目、2行目と移り変わる。
ナンバリングは、スタートから左下にいく。行は+1、列は-1している。
D=1と同様に、最大の移動数はHかWのうち小さい方-1。
マップからはみ出ないようにして、ナンバリングする。
デバックは、入力例1~4において、D=1~4についても行うとより確実。
なお、ifで場合分けをしているが、switchでも可能。
解答例
変数について、iは行、jは列、aが斜めで使用するようにした。
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//盤面の行数を表す整数 H , 盤面の列数を表す整数 W
const [H, W, D] = lines[0].split(" ").map(Number);
//マップ
const S = Array(H).fill().map(row => row = Array(W).fill());
let num = 1;//ナンバリング用変数
if (D === 1) {
//j=0,0<=i<H-1
for (let i = 0; i < H; i++) { //i行
//斜め右上に
for (let a = 0; a < Math.min(H, W); a++) { //斜めa
if (i - a >= 0 && 0 + a < W) { //マップ内
S[i - a][0 + a] = num;
num++;
}
}
}
//i=H-1,1<=j<W
for (let j = 1; j < W; j++) { //j列
//斜め右上に
for (let a = 0; a < Math.min(H, W); a++) { //斜めa
if (H - 1 - 1 >= 0 && j + a < W) { //マップ内
S[H - 1 - a][j + a] = num;
num++;
}
}
}
} else if (D === 2) {
for (let i = 0; i < H; i++) { //i行
for (let j = 0; j < W; j++){ //j列
S[i][j] = num;
num++;
}
}
} else if (D === 3) {
for (let j = 0; j < W; j++) { //j列
for (let i = 0; i < H; i++) { //i行
S[i][j] = num;
num++;
}
}
} else if (D === 4) {
//i=0,0<=j<W-1
for (let j = 0; j < W; j++) { //j列
//斜め左下に
for (let a = 0; a < Math.min(H, W); a++) { //斜めa
if (0 + a < H && j - a >= 0) { //マップ内
S[0 + a][j - a] = num;
num++;
}
}
}
//j=W-1,1<=i<H
for (let i = 1; i < H; i++) { //i行
//斜め左下に
for (let a = 0; a < Math.min(H, W); a++) { //斜めa
if (i + a < H && W - 1 - a >= 0) { //マップ内
S[i + a][W - 1 - a] = num;
num++;
}
}
}
}
console.log(S.map(row => row.join(" ")).join(("\n")));