新版 Firefox 试玩

记不清楚从什么时候开始使用 Firefox 的,用的第一个版本应该是 v3.6,当时觉得 Firefox 可定制性很强,可以按照自己的喜好折腾主题、样式、功能,也就逐渐迷上了火狐浏览器。也是大概在那期间(11年),自己开始业余时间学习 JavaScript,动手写一些 Greasemonkey 的脚本拓展网站功能。不过很遗憾,因为觉得 Firefox 的扩展入门比较难(后来开发 Chrome 扩展就发现非常容易),也就一直没有机会折腾一个扩展玩玩。

每一个曾经的 “Firefox” 粉应该都折腾过用户样式(Stylish)、油猴脚本(GreaseMonkey)、手势操作(FireGestures)、拖拽( Drag to go?)、下载以及标签定制这些扩展吧,这些也是当时 Firefox 受到大家追捧的很重要一个原因,几乎整个界面和功能都可以定制。当时甚至一度沉迷 Vimperator(以及Pentadactyl),打算不用鼠标,全键盘操作浏览器。

不过后来 Google Chrome 出现了,因为它非常简单、好用、启动快,而且自己也越来越不喜欢折腾,就叛变了,一直到换成 Mac 系统。现在主力是默认的浏览器 Safari,iMac、MacBook、iPhone、iPad 多个设备上基本可以保持一致的体验,开箱即用,Safari 我基本也没安装扩展,甚至广告过滤的扩展也没安装。

继续阅读

Leetcode 3. Longest Substring Without Repeating Characters

继续做把第三题的解题思路放上来。第三题的目的是求字符串内最长的不重复子串,两个要求非常清晰。下面是题目的描述:

Given a string, find the length of the longest substring without repeating characters.

Examples:

Given "abcabcbb", the answer is "abc", which the length is 3.

Given "bbbbb", the answer is "b", with the length of 1.

Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.

思路:

假设子串的初始下标为 i,结束下标为 j。i 和 j 的初始值均为 0。j 开始一次往后遍历,如果这个字符串没有重复字符,那么 j 会一直走到最后,此时最长子串就是字符串本身。实际情况没有那么理想,我们主要分析这类场景。当处于 j 位置的字符和子串之前的字符重复(假设位置为 k),那么就应该停下,并且更新最长子串的长度(假设最长长度为 max),j 继续往后走,同时 i 的位置需要挪到重复字符之后,即 k+1 处。直到遍历到字符串的最后。

继续阅读

LeetCode Problem 2 - Add Two Numbers

继续第二道题目,下面是问题描述:

You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8

这个问题比较简单,基本上解题思路是比较清晰的。输入是两个链表,链表的元素都是单个数字(0-9),要求将两个列表的相应节点数字相加,并作为结果链表返回。

这个题咋看可以马上开始解答,但是在此之前还是有一些需要注意的地方。第一点是,题目并没有说明链表的长度,所以 A 和 B 两个链表可能不一定相同长度,那么如果一个链表更长,那么相加怎么处理呢?这里就考虑直接返回即可,相当于+0。第二点是,如果相加溢出怎么处理,其实题目的例子里面已经很清晰了,溢出会发生进位,依次向后处理。第三点是,如果最后一位发生进位呢,这点容易被遗忘,需要新增一个节点。

继续阅读

LeetCode Problem 1 - Two Sum

最近开始在 LeetCode 网站上刷题,准备练练脑子。因为经常不动脑,感觉快生锈了。这个是第一题,比较简单。所有的解题代码都放在 Github 上。

问题描述:

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:
Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

题目描述的很清楚了,就是要从整数列表里面找出符合需求的两个数字,他们之和等于给定的目标值。输入是整数列表,输出是两个数字下标的列表。从给的例子上看,我们可以假设返回的列表,下标小的放在前面,比如是 [0, 1] 而不是 [1, 0]。那假如没有找到符合要求的数字呢,应该返回什么呢?题目里面没有明确说明,我自己觉得这里应该返回一个空值。

继续阅读

Bash function 还能这么玩

今天看到一篇讲 Bash function 的有意思的文章,原文在这里

在 Bash 中一般我们这么定义一个函数:

function name () {
  ...
}

这是非常常见的写法,包括我自己在内,一直把他当做类似 Python、C 等语言一样的函数定义语法。实际上这里{ ... }并不代表函数体或者函数的作用域。它只是代表里面的内容是一组命令的集合。了解这点之后,接下来就有一些比较好玩的写法了。

比如下面的函数作用是测试文件是否存在,这里就没用大括号:

function fileExists () [[ -f $1 ]]

或者

function isEven () (( $1 % 2 == 0 ))

还有下面的用法:

function name () (
  ...
)

继续阅读

优雅部署 Google Adsense 广告代码

去年就曾经申请过 Google Adsense 的广告,但是貌似审核没通过,一直留有遗憾(没有尝试过好奇)。今年突然起了兴致重新申请,审核持续了将近一周,意外地竟然通过了。

在申请之前,需要在页面上加上一段代码。最好加到 head 里面,因为 Google Adsense 的代码片段加了 async 属性会后台异步加载,不会影响页面渲染。代码例如:

<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<script>
  (adsbygoogle = window.adsbygoogle || []).push({
    google_ad_client: "ca-pub-xxxxxxxx",
    enable_page_level_ads: true
  });
</script>

其中 "ca-pub-xxxxxxxx" 是你的 publisher id(Adsense 账户里面看到的是没有 ca- 前缀的,搞不懂区别是什么)。

审核通过之后就是可以再 Adsense 网站创建广告单元,然后复制代码到你自己的网站上,不出意外很快就可以显示广告了。广告代码大概是这样子的:

<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- 侧栏自适应2 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-xxxxx"
     data-ad-slot="yyyyy"
     data-ad-format="horizontal"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

继续阅读

非插件实现面包屑导航功能

最近开始整理 WordPress 的插件,发现有些插件功能越来越重,比如 Yoast SEO 的插件,出于个人洁癖就把他删除了。但是目前网站原来的 Breadcrumbs 导航功能是这个插件提供的,所以就开始查找替换方案。网上搜索发现一片文章介绍的比较具体 --- 《WordPress实现面包屑导航的方法》,博主其实也是参考了国外网友的非插件实现

以下代码都是基于 Dimox 的原创,我只是在他基础上做了微调,改动不大:

继续阅读

最近的变化

好久没有写技术博客了,刚才看归档页面,15 年写了一篇,16 年也写了一篇,实在汗颜。不过这个博客对我来说是一个非常宝贵的财富,所以不出意外我会一直维护下去。争取今年可以继续写一些文章。

这两年博客写得少,主观原因确实是在技术上投入的精力减少了,虽然我也有在看一些技术文章,但是沉淀落实到纸面(博客)上的几乎没有。一方面原因是平时工作比较忙,非工作时间也更多开始陪伴家人(想想 Dota 也是大半年没玩了)。另外一方面是,大概两年前我开始带团队,这两年的时间我更多得在摸索怎么带好一只团队,纠结、彷徨、探索一路走来,更加关注团队同学的技术和个人能力的成长。最近忘记是知乎还是微博上看到一篇,关于一线工程师和技术经理的翻译文章,里面讲到一线工程师被提拔为主管后,很多东西会发生变化,细节的关注程度,技术方向的把握,工作规划的制定,团队之间的协作等等。个人感觉,有好有坏,确实带团队之后个人在细节的把握上比以前弱了不少,但是也因为带过团队思路和视野开阔不少。

最近谈得比较多的是 DevOps,国内基本上就是说研发具备运维能力,或者激进点就是干掉运维团队。运维团队是否没有存在的价值?未必,只能说传统的 Ops 运维不再有存在的价值,运维需要往更深领域去转型。运维工程师的关注点可能不再是一个变更或者一个具体的操作。

比较能想到的一个方向,是自动化运维,这也是近几年非常火的关键词。DevOps 的理念并非让研发来兼职完成运维的操作,而是需要将运维的经验通过代码的方式沉淀到自动化的平台,通过平台赋能帮助研发高效地完成运维工作。研发鼠标点点,填写几个表单选项就可以快速部署应用到各个环境,不再需要找运维同学去申请机器、申请域名、部署发布,容量不足了可以快速扩容,甚至设定规则弹性伸缩。但是我一般不看好(没有运维经验的)研发去做自动化平台,所以这也是为什么非常多研发组成的工具团队最终造出来的是一个难用的玩具的原因。

继续阅读