LoginSignup
1
0

More than 1 year has passed since last update.

paizaラーニング レベルアップ問題集 Aランクレベルアップメニュー JavaScript マップの判定・縦横

Last updated at Posted at 2022-09-20

マップの判定・縦横 (paizaランク B 相当)

JavaScriptで解いてみました。いくつか解答例を載せたので、理解しやすいところ、しっくりくるところを参考にしてください。

解答例(上下左右判定)

上下左右ひとつひとつ調べました。

JavaScript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//盤面の行数を表す整数 H , 盤面の列数を表す整数 W
const [H,W] = lines[0].split(" ").map((num) => Number(num));
//盤面
const board = [];
for (let i = 1; i <= H; i++) {
    board.push(lines[i]);
}
//盤面全てのマスについて調べる
//y座標、行について
for (let i = 0; i < H; i++) {
    //x座標、列について
    for (let j = 0; j < W; j++) {
        //上下左右が'#'ならtrue
        let[left,right,up,down] = [false,false,false,false];
         //左端のマスの場合は「右のマスが "#"」であれば
        if (j === 0 && board[i][1] === "#") {
            left  = true;
            right = true;
        }
        //右端のマスの場合は「左のマスが "#" 」であれば
        if (j === W - 1 && board[i][W - 2] === "#") {
            left  = true;
            right = true;
        }
        //上端のマスの場合は「下のマスが '#'」であれば
        if (i === 0 && board[1][j] === "#") {
            up   = true;
            down = true;
        }
        //下端のマスの場合は「上のマスが '#'」であれば
        if (i === H - 1 && board[H - 2][j] === "#") {
            up   = true;
            down = true;
        }
        //左右のマスが”#”であれば
        if (board[i][j - 1] === "#" &&
            board[i][j + 1] === "#") {
            left  = true;
            right = true;
        }
        //上下のマスがどちらも '#' であれば
        if (i !== 0 && i !== H - 1 && 
            board[i - 1][j] === "#" &&
            board[i + 1][j] === "#") {
            up   = true;
            down = true;
        }
        //上下左右のマスが全て '#' であるマスの y , x 座標を出力
        if (left === true && right === true &&
            up   === true && down  === true) {
            console.log(`${i} ${j}`);
        }
        
    } //for j
    
} //for i

解答例(行列判定)

左右上下ではなく、行と列で調べました。

const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//盤面の行数を表す整数 H , 盤面の列数を表す整数 W
const [H,W] = lines[0].split(" ").map((num) => Number(num));
//盤面
const board = [];
for (let i = 1; i <= H; i++) {
    board.push(lines[i]);
}

//盤面全てのマスについて調べる
//y座標、行について
for (let i = 0; i < H; i++) {
    //x座標、列について
    for (let j = 0; j < W; j++) {
        
        //行列が#か判定
        let[row,colum] = [false,false];
        
         //左端のマスの場合は「右のマスが "#"」であれば
        if (j === 0 && board[i][1] === "#") {
            row  = true;
        }
        //右端のマスの場合は「左のマスが "#" 」であれば
        if (j === W - 1 && board[i][W - 2] === "#") {
            row  = true;
        }
        //上端のマスの場合は「下のマスが '#'」であれば
        if (i === 0 && board[1][j] === "#") {
            colum = true;
        }
        //下端のマスの場合は「上のマスが '#'」であれば
        if (i === H - 1 && board[H - 2][j] === "#") {
            colum = true;
        }
        //左右のマスが”#”であれば
        if (board[i][j - 1] === "#" &&
                   board[i][j + 1] === "#") {
            row  = true;
        }
        //上下のマスがどちらも '#' であれば
        if (i !== 0 && 
                   i !== H - 1 && 
                   board[i - 1][j] === "#" &&
                   board[i + 1][j] === "#") {
            colum = true;
        }
        
        //左右上下全て#ならば
        if (row && colum) {
            console.log(`${i} ${j}`);
        }
        
    } //for j
    
} //for i

解答例(python3の場合の模範解答参考)

行で、左側・左端と右側・右端をまとめ、
列で、上側・上端と下側・下端をまとめました。

const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//盤面の行数を表す整数 H , 盤面の列数を表す整数 W
const [H,W] = lines[0].split(" ").map((num) => Number(num));
//盤面
const board = lines.slice(1).map(line => line.split(""));

//盤面全てのマスについて調べる
//y座標、行について
for (let i = 0; i < H; i++) {
    //x座標、列について
    for (let j = 0; j < W; j++) {
        
        //行と列について#か判定
        let[row,colum] = [false,false];
        
        //行について
        //左側、左端もしくは"#"ならば
        if (j === 0 || board[i][j - 1] === "#") {
            //右側、右端もしくは"#"ならば
            if (j === W - 1 || board[i][j + 1] === "#") {
                row  = true;
            }
        }
         
        //列について
        //上側、上端または"#"ならば
        if (i === 0 || board[i - 1][j] === "#") {
            //下側、下端または"#"ならば
            if (i === H - 1 || board[i + 1][j] === "#") {
                colum = true;
            }
        } 
        
        //左右上下全て#ならば
        if (row && colum) {
            console.log(i,j);
        }
        
    } //for j
    
} //for i

解答例(C++の場合の模範解答参考)

上下左右を調べるときに、移動の変化量である [-1,1] を配列 move で持つと、for文+if文2つにできます。
上下左右の全てで条件を満たすかどうかを判定するために 変数 ok を用います。
盤面内 かつ #でなかったときに、falseにします。

const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//盤面の行数を表す整数 H , 盤面の列数を表す整数 W
const [H,W] = lines[0].split(" ").map((num) => Number(num));
//盤面
const S = Array(H);
for (let i = 0; i < H; i++) {
    S[i] = lines[i + 1];
}
//移動の変化量move
let move = [-1, 1];

//盤面全てのマスについて調べる
//y座標、行について
for (let i = 0; i < H; i++) {
    //x座標、列について
    for (let j = 0; j < W; j++) {
        
        //上下左右の全てで条件を満たすかどうかを判定
        let ok = true;
        //kはmoveのインデックス,移動の変化量move[0]= -1,move[1]= 1
        for (let k = 0; k < 2; k++){

            //行方向iの移動について、move[k] = -1左 または 1右 移動した時
            //盤面内 かつ #でないなら ok=false            
            if(0 <= i+move[k] && i+move[k] < H &&
             S[i+move[k]][j] !== '#'){
                ok = false;
                break;
            }
            //列方向jの移動について、move[k] = -1上 または 1下 移動した時
            //盤面内 かつ #でないなら ok=false
            if(0 <= j+move[k] && j+move[k] < W &&
             S[i][j+move[k]] !== '#'){
                ok = false;
                break;
            }
        }
        
        //左右上下全て#ならば
        if (ok) {
            console.log(i + " " + j);
        }
    } //for j
} //for i

解答例(Rubyの場合の模範解答参考)

forEachを使いました。
左右のマスの文字が # のとき flag_row を true にします。
上下のマスの文字が # のとき flag_clm を true にします。
端の時は問題に従ってtrueになるようにしています。
flag_row && flag_clm で上下左右の全てのマスの文字 # であるかを判定できます。

JavaScript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//盤面の行数を表す整数 h , 盤面の列数を表す整数 w
const [h, w] = lines[0].split(" ").map((num) => Number(num));
//盤面
const board = lines.slice(1).map(line => line.split(""));

//盤面全てのマスについて調べる
//y座標、行rowについて
board.forEach((row, y) => {
    //x座標、列について
    row.forEach((_, x) => { //第一引数は使わないので_にしています。
        let flag_row = false;
        let flag_clm = false;
        //左右のマスの文字が # のとき flag_row を true にします。
        //端の時は問題に従ってtrueになるようにしています。
        if (x === 0 || row[x - 1] === '#') {
          if (x === w - 1 || row[x + 1] === '#') {
            flag_row = true;
          }
        }
        //上下のマスの文字が # のとき flag_clm を true にします。
        ////端の時は問題に従ってtrueになるようにしています。
        if (y === 0 || board[y - 1][x] === '#') {
          if (y === h - 1 || board[y + 1][x] === '#') {
            flag_clm = true;
          }
        }
        /*flag_row && flag_clm で上下左右の全てのマスの文字が
         # であるかを判定できます。*/
        if (flag_row && flag_clm) {
          console.log(y + ' ' + x);
        }    
    }); //forEach _ x
}); //forEach row y
1
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
1
0