task:
上一题:RobotScript#2:实现循环指令的重复化(字符串扩展)并画出轨迹
基于RobotScript#2,(*)2 等价 **,示例如下:
F4L((F4R)(F4L)2)2(F4R)2F4
解题:
只要将“()”祛除即可,不考虑输入字符串异常的情况下,最开始想到的是转成AST,用text记录文本,()最为层级分割,但是没能解答出来,于是用正则递归处理字符串,直到字符串中不存在括号。
关键代码如下:
function flatCode(code){
if(code.indexOf('(')>-1){
code = code.replace(/\([^=\)\()]*\)\d*/g,item=>{
const index = item.indexOf(')')
if(index===item.length-1)return item.slice(1,index);
else return item.slice(1,index).repeat(item.slice(index+1))
})
if(code.indexOf('(')>-1)return flatCode(code)
}
return code
}
完整代码:
/**
* L左转,R右转,F表示在当前方向向前进一,初始方向朝右,用*标记痕迹,F5表示走五次,类推
* 如:LF5RF
* **
* *
* *
* *
* *
* *
*/
function execute(code){
code = flatCode(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')
}
function flatCode(code){
if(code.indexOf('(')>-1){
code = code.replace(/\([^=\)\()]*\)\d*/g,item=>{
const index = item.indexOf(')')
if(index===item.length-1)return item.slice(1,index);
else return item.slice(1,index).repeat(item.slice(index+1))
})
if(code.indexOf('(')>-1)return flatCode(code)
}
return code
}
console.log(execute('F4L((F4R)(F4L)2)2(F4R)2F4'))