CodeWars
离上一篇文章只过去了九天,不过做了几道难题,虽然基本都是谷歌和某人帮大忙。。
记下来好一点 不然太难了很快就忘记了
- Pyramid Slide Down
给出一个数字金字塔,求得金字塔顶部到底部的连续数字之和。
Examples:
Test.assertEquals(longestSlideDown(
[[3],
[7, 4],
[2, 4, 6],
[8, 5, 9, 3]]),
23, "should work for small pyramids");
Test.assertEquals(longestSlideDown(
[[75],
[95, 64],
[17, 47, 82],
[18, 35, 87, 10],
[20, 4, 82, 47, 65],
[19, 1, 23, 75, 3, 34],
[88, 2, 77, 73, 7, 63, 67],
[99, 65, 4, 28, 6, 16, 70, 92],
[41, 41, 26, 56, 83, 40, 80, 70, 33],
[41, 48, 72, 33, 47, 32, 37, 16, 94, 29],
[53, 71, 44, 65, 25, 43, 91, 52, 97, 51, 14],
[70, 11, 33, 28, 77, 73, 17, 78, 39, 68, 17, 57],
[91, 71, 52, 38, 17, 14, 91, 43, 58, 50, 27, 29, 48],
[63, 66, 4, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31],
[ 4, 62, 98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 4, 23]]),
1074, "should work for medium pyramids");
解决方案:
function longestSlideDown (pyramid) {
var m = [];
function funMax(x,y){
if(x<0 || y< 0|| pyramid[x][y] === undefined)return -1;
if(m[x][y] === undefined)
m[x][y] = pyramid[x][y] + Math.max(funMax(x-1,y),funMax(x-1,y-1));
return m[x][y];
}
for(var i = 0;i<pyramid.length;i++)
m.push([]);
m[0][0] = pyramid[0][0];
for(var i = 0;i<pyramid.length;i++){
funMax(pyramid.length-1,i);
}
return Math.max(...m[pyramid.length-1]);
}
自底向上遍历,寻找相加数最大的结果
2.Make a spiral
画一个N×N的不能与自身接触的蛇形螺旋出来,以二维矩阵表示(1为蛇0为空白):
Your task, is to create a NxN spiral with a given size.
For example, spiral with size 5 should look like this:
00000
....0
000.0
0...0
00000
and with the size 10:
0000000000
.........0
00000000.0
0......0.0
0.0000.0.0
0.0..0.0.0
0.0....0.0
0.000000.0
0........0
0000000000
Return value should contain array of arrays, of 0 and 1, for example for given size 5 result should be:
[[1,1,1,1,1],[0,0,0,0,1],[1,1,1,0,1],[1,0,0,0,1],[1,1,1,1,1]]
解决方案
var spiralize = function(size) {
// insert code here
let dir=[
{x:0, y:1},//右
{x:1, y:0},//下
{x:0, y:-1},//左
{x:-1,y:0},//上
];
let dir_times = 0;
let res = [];
for(let i=0;i<size;i++){
res.push([]);
for(let j=0;j<size;j++)
res[i].push(0);
}
let pos = {x:0,y:0};
let next,dnext,cur_dir;
let flag = 0;
while(true){
// 连续转两次就退出
if(flag ==2)break;
res[pos.x][pos.y] = 1;// 让当前位置标记为1
cur_dir = dir[dir_times%4]; // 当前的方向
next = {x:pos.x+cur_dir.x ,y:pos.y+cur_dir.y};// 计算下一步位置
if(!(next.x >=0 && next.x < size && next.y >=0 && next.y < size)){
// 越界转向条件
dir_times++;
flag++;
continue;
}
dnext = {x:next.x + cur_dir.x ,y:next.y+cur_dir.y};// 计算此方向下一步再下一步位置
if(dnext.x >=0 && dnext.x < size && dnext.y >=0 && dnext.y < size && res[dnext.x][dnext.y] == 1){
// 下下步在界内并且已经标记则转向,若在界外则无视
dir_times++;
flag++;
continue;
}
// 退出条件部分
dnext = {x:next.x + dir[(dir_times+1)%4].x ,y:next.y + dir[(dir_times+1)%4].y};// 计算下一步的下一个方向的位置
if(res[dnext.x][dnext.y] == 1){
// 下一步的下一个方向的位置已经被标记则也退出
break;
}
pos = next;
// 正常走了一步后就可以重置连续转向标记
flag = 0;
}
return res;
}
第一次接触这样的题。
先定义四个方向增量,和一些辅助参数。
方向参数的循环用转向次数控制,当前方向=(转向次数%4)
计算下一步位置,如果越界了,就转向,并用flag记录这次转向(flag的用处下面会说到)
还有一种转向是真的走到该转向的地方了,于是我计算了下一步再下一步的位置(下下步 的位置),如果下下步在界内并且已被标记,则意味着再走一步会碰壁。所以该转向了。
常规流程就是上面那样,编码过程中遇到的困难是如何使它结束,
结束分两种情况 一是前进发现碰壁,则转向,转向又发现碰壁,这样转向了两次flag=2了则结束(比如example中的那个5×5的)。一般来说正常通过一步后flag置0
二是前进发现碰壁,转向后发现和下一次转向碰了,则结束(比如example中那个10×10的)
接触的东西
工作中或是日常中经常会通过各种渠道接触到碎片化的新知识(对我而言的新知识),说实话我并不知道该怎么把他们消化成我自己的东西。
-
css in js ,似乎是一个很麻烦的东西,探究收获比不大
-
基础通用GPU纹理和纹理视频压缩参考编解码器
https://github.com/binomialLLC/basis_universal
https://opensource.googleblog.com/2019/05/google-and-binomial-partner-to-open.html -
Math is Fun 数学乐 逆矩阵 代数的解释,对理解图形学基础有帮助
https://www.shuxuele.com/algebra/matrix-inverse.html
https://www.shuxuele.com/