task:
你将遇到由L,R,F及数字组合而成的字符串,通过此字符串实现移动轨迹绘制,其中 L 代表当前方向向左拐,R代表向右,F表示在当前方向前进,用 "*" 标记走过的位置,其中只有F能够产生"*",LR只有调整方向的作用,初始方向向右,并且会留下*;
字母后面接上数字表示字母会重复任意次。
示例:
LF5R5F5RFLFRFF
解答:
首先要将接收的指令转化为连续的独立的字符(指令),如接收的code为“LF5”转为“LFFFFF”,直接利用正则匹配/[LRF]\d+/g,利用 replace 替换成 (m) => m[0].repeat(m.slice(1)),m为匹配的字符串,因为是 char 和 \d+ 组合的,故而可以直接使用repeat。
然后就是轨迹绘制了,结合题意可知初始状态时应为二维数组 [["*"]] 的状态,我们要在网格上进行绘制,二维数组可以看做直角坐标系使用,但是没有负坐标轴,所以每次触发 F 绘制时,要重新校准原点。
方向与坐标变动关系为 (x+di,y+dj)
→:di = 0, dj = 1;
↑ :di = 1, dj = 0;
←:di = 0,dj = -1;
↓ :di = -1,dj = 0;
易得每次变换方向 R : [di,dj] = [-dj,di]
L :[di,dj] = [dj,-di]
完整代码:
/**
* L左转,R右转,F表示在当前方向向前进一,初始方向朝右,用*标记痕迹,F5表示走五次,类推
* 如:LF5RF
* **
* *
* *
* *
* *
* *
*/
function execute(code){
code = code.replace(/[LFR]\d+/g, (m) => m[0].repeat(m.slice(1)))
let i = 0,j = 0,col,row,di = 0 ,dj = 1,grid = [['*']];
for(let key = 0;key<code.length;key++){
col = grid[0].length;
row = grid.length;
switch(code[key]){
case "F":
[i,j] = [i+di, j+dj];
if(i<0)grid = [new Array(col).fill(" "),...grid];
if(i>=row)grid = [...grid,new Array(col).fill(" ")];
if(j<0)grid = grid.map(item=>{return [" ",...item]})
if(j>=col)grid = grid.map(item=>{return [...item," "]})
i = Math.max(0,i);
j = Math.max(0,j);
break;
case "L":
[di,dj] = [-dj,di]
break;
case "R":
[di,dj] = [dj,-di]
break;
}
grid[i][j] = "*"
}
return grid.map(item=>{return item.join('')}).join('\r\n')
}
console.log(execute('LF5R5F5'))