LoginSignup
1
0

More than 1 year has passed since last update.

paizaラーニング レベルアップ問題集 Aランクレベルアップメニュー JavaScript へび

Posted at

へび (paizaランク A 相当)

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

解答例

はじめに時刻tと右左dの配列を作っています。

JavaScript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [H,W,sy,sx,N] = lines[0].split(" ").map(Number);
//マップ
const S = lines.slice(1, H + 1).map(line => line.split(""));

const T = [];//時刻t
const D = [];//右左d
for (let i = 1; i <= N; i++) {
    const [t, d] = lines[i + H].split(" ");
    T.push(Number(t));
    D.push(d);
}

const direct = ['N', 'E', 'S', 'W'];
let now = 0;//directの添字

//スタート位置
let [y, x] = [sy, sx];
S[y][x] = "*";

let j = 0;//Tの添字
for (let time = 0; time < 100; time++) {
    //時刻tで方向転換
    if (time === T[j]) {
        if (D[j] === "L") {
            now = (now + 3) % 4;
        } else {
            now = (now + 1) % 4;
        }
        j++;//Tの次を準備
    }
    //移動
    if (direct[now] === 'N') {
        y -= 1;
    } else if (direct[now] === 'E') {
        x += 1;
    } else if (direct[now] === 'S') {
        y += 1;
    } else if (direct[now] === 'W') {
        x -= 1;
    } 
    
    //移動先が、マップ上かつ障害物がない,自分の体もない、なら進める
    if (0 <= y && y < H && 0 <= x && x < W && S[y][x] === ".") {
        S[y][x] = "*";
    } else {
        break;
    }
    
}
console.log(S.map(row => row.join("")).join("\n"));

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

移動量の関数moveを定義しています。

const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [H,W,sy,sx,N] = lines[0].split(" ").map(Number);

const S = lines.slice(1, H + 1).map(line => line.split(""));

const td = [];////時刻t右左d
for (let i = 1; i <= N; i++) {
    const [t, d] = lines[i + H].split(" ");
    td.push([Number(t), d]);
}
let mcount = 0;//td添字

const direct = ['N', 'E', 'S', 'W'];
let dcount = 0;//directの添字

const move = (D, M) => {//D方角NESW、M左右ストレート
    //M=Rのとき
    let LR = 1;
    add = 1;
    
    if (M === 'S') {//M=S:ストレート,方向転換なしの時、真っ直ぐ
        //移動量
        if (D === 'N') {
            y--;
        } else if (D === 'S') {
            y++;
        } else if (D === 'E') {
            x++;
        } else {
            x--;
        }
    } else { //方向転換あり
        //Lのとき
        if (M === "L") {
            LR = -1;
            add = 3;
        }
        //移動量
        if (D === 'N') {
            x += LR;
        } else if (D === 'S') {
            x -= LR;
        } else if (D === 'E') {
            y += LR;
        } else {
            x -= LR;
        }
        dcount += add;//方向転換 次のために
    }
};

//スタート位置
let [y, x] = [sy, sx];//const sy,sxなのでy,xに置換
S[y][x] = "*";

for (let time = 0; time < 100; time++) {

    //時刻tで方向転換
    if (time === td[mcount][0]) {//time=t
        //方向転換の時刻になったら左右についての move を呼び出し
        move(direct[dcount % 4], td[mcount][1]);//(D, M=m)
       
        mcount++;//次のtdを準備
    //方向転換なし    
    } else {
        move(direct[dcount % 4], 'S');//ストレートS,方向転換なし、真っ直ぐ
    }    
    
    //移動先が、マップ上かつ障害物がない,自分の体もない、なら進める
    if (0 <= y && y < H && 0 <= x && x < W && S[y][x] === ".") {
        S[y][x] = "*";
    } else {
        break;
    }
    
}
console.log(S.map(row => row.join("")).join("\n"));

解答例(Python3の場合を参考)

time_lrで時刻t右左dをまとめた配列を作っています。

JavaScript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [H,W,sy,sx,N] = lines[0].split(" ").map(Number);
const S = lines.slice(1, H + 1).map(line => line.split(""));

const time_lr = [];//時刻t右左d
for (let i = 1; i <= N; i++) {
    const [t, d] = lines[i + H].split(" ");
    time_lr.push([t, d]);
}
let time_index = 0;//time_lrの添字

const direct = ['N', 'E', 'S', 'W'];
let now = 0;//directの添字

//スタート位置
let [y, x] = [sy, sx];
S[y][x] = "*";


for (let time = 0; time < 100; time++) {
    //時刻tで方向転換
    if (time_index < N && time === time_lr[time_index][0]) {
        time_index += 1;//次を準備
        if (time_lr[time_index] === "L") {
            now = (now + 3) % 4;
        } else {
            now = (now + 1) % 4;
        }
        
    }
    //移動
    if (direct[now] === 'N') {
        y -= 1;
    } else if (direct[now] === 'E') {
        x += 1;
    } else if (direct[now] === 'S') {
        y += 1;
    } else if (direct[now] === 'W') {
        x -= 1;
    } 
    
    //移動先が、マップ上かつ障害物がない,自分の体もない、なら進める
    if (0 <= y && y < H && 0 <= x && x < W && S[y][x] === ".") {
        S[y][x] = "*";
    } else {
        break;
    }
    
}
console.log(S.map(row => row.join("")).join("\n"));

解答例(Ruby の場合参考)

方向の配列move = [[-1, 0], [0, 1], [1, 0], [0, -1]]を使っています。

JavaScript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [H,W,sy,sx,N] = lines[0].split(" ").map(Number);

const board = lines.slice(1, H + 1).map(line => line.split(""));

const turns = lines.slice(H + 1).map(line => line.split(" ").map((val, i) => 
    i === 0 ? Number(val) : val));//時刻t右左d

const move = [[-1, 0], [0, 1], [1, 0], [0, -1]];
let now = 0;//moveの添字

//スタート位置
let [y, x] = [sy, sx];//const sy,sxなのでy,xに置換
board[y][x] = "*";
let [t, d] = turns.shift();

for (let time = 0; time < 100; time++) {

    //時刻tで方向転換
    if (t === time) {//time=t
        if (d === 'L') {
            now += 3;
        } else {
            now += 1;
        }
       
        if (turns.length > 0) {
            [t, d] = turns.shift();
        }//次のturndを準備
    } 
    //移動
    ny = y + move[now % 4][0];
    nx = x + move[now % 4][1];
    
    //移動先が、マップ上かつ障害物がない,自分の体もない、なら進める
    if (!(0 <= y && y <= H - 1 && 0 <= x && x <= W - 1 && 
        board[ny][nx] !== "#" && board[ny][nx] !== "*")) {
        break;
    }
    [y, x] = [ny, nx];
    board[y][x] = '*';
}
console.log(board.map(row => row.join("")).join("\n"));

解答例(python3の場合を参考)2

はじめにtime_lrで時刻と右左をまとめた配列を作っています。

const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

let [H,W,sy,sx,N] = lines[0].split(" ").map(Number);
const s = lines.slice(1,H + 1).map((line) => line.split(""));

const time_lr = lines.slice(H + 1, H + N + 1).map(line => line.split(" "));
let time_index = 0; //方向転換の回数

const directions = ["N","E","S","W"];
let now_direction = 0;

s[sy][sx] = '*';

for (let t_now = 0; t_now <= 99; t_now++) {
    //方向転換の時刻になったら
    if (time_index < N && String(t_now) === time_lr[time_index][0]) {
        const d = time_lr[time_index][1];
        time_index += 1;
        //方向転換
        if (d === "L") {
            now_direction = (now_direction + 3) % 4;
        } else {
            now_direction = (now_direction + 1) % 4;
        }
    
    }//if time_index
    
    // 1 マス身体を伸ばす。
    if (directions[now_direction] === "N") {
        sy -= 1;
    } else if (directions[now_direction] === "E") {
        sx += 1;
    } else if (directions[now_direction] === "S") {
        sy += 1;
    } else if (directions[now_direction] === "W") {
        sx -= 1;  
    } 
    
    //移動できるようなら s[sy][sx] = "*" とマスを書き換え、
    //できないようならループを抜けます。
    if (sx < 0 || W <= sx || sy < 0 || H <= sy || s[sy][sx] !== ".") {
        break;
    } else {
        s[sy][sx] = '*';
    }    
        
}//for t_now

//マップを出力
console.log(s.map(elm => elm.join("")).join("\n"));


解答例

蛇が行動100回するループの中で、方向転換をするかforループで調べています。

JavaScript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//マップの行数 H と列数 W 
//現在の座標 sy , sx , 方向転換の回数 N
const [H,W,sy,sx,N] = lines[0].split(" ").map((v) => Number(v));

const map = lines.slice(1,H + 1).map((line) => line.split(""));

//現在の y, x 座標
let [y,x] = [sy,sx];
map[y][x] = '*';

//へびははじめ北を向いています。
const directions = ["N","E","S","W"];
let now_direction = 0; //向きを決めるインデックス

//時刻 0 から 99 までの間、へびは各時刻に次の行動を最大 100 回とります。
let stop = false; //途中で止まったか判定
for (let time = 0; time <= 99; time++) {
    //方向転換をおこなう時刻の場合、
    //指定の向きに方向転換したのち 1 マス身体を伸ばす。
    
    //方向転換を行う時刻か調べる
    for (let turn = 1; turn <= N; turn++) {
        
        //方向転換をおこなう時刻 t_i と方向転換の向き d_i 
        const t = Number(lines[H + turn].split(" ")[0]);
        const d =        lines[H + turn].split(" ")[1];
    
        //もし方向転換を行う時刻ならば
        if (time === t) {
            //方向転換をする
            if (d === "L") {
            now_direction = (now_direction + 3) % 4;
            break;
            } else {
            now_direction = (now_direction + 1) % 4;
            break;
            }
        }//if time=t
        
    } //for turn 方向転換完了
  
    // 1 マス身体を伸ばす。
    if (directions[now_direction] === "N") {
        y -= 1;
    } else if (directions[now_direction] === "E") {
        x += 1;
    } else if (directions[now_direction] === "S") {
        y += 1;
    } else if (directions[now_direction] === "W") {
        x -= 1;  
    } 
   
    //移動先がマップの範囲外
    if (x < 0 || W <= x || y < 0 || H <= y) {
        stop = true;
        break;
        
    //移動先が障害物か自分の身体   
    } else if (map[y][x] === "#" || map[y][x] === '*') {
        stop = true;
        break;
        
    //移動終了時にへびの体のあるマスを '*' に
    } else {
        map[y][x] = '*';
    }
    
  //止まったらfor_timeループ抜ける
    if (stop) break;

} //for time

//マップを出力
console.log(map.map(elm => elm.join("")).join("\n"));
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