给google reader增加分享到人人网功能
现在每天几乎都要看一下人人网和google reader,SNS用来娱乐,和朋友沟通,GReader用来阅读,获取信息和知识,于是想把GR上看到的好文章分享到人人网上去和大家一直共享。
要实现这样的功能其实有现成的东西,人人网早提供了站外分享的工具,给自己网站加此功能的话可以修改代码(看这里),加上人人的分享代码的链接,给浏览器添加的话人人也做好了相关的分享书签,firefox的话还有小扩展可以用(看这里)。
这样的方法的话还是有个问题,在GR中阅读的时候看到的是google抓RSS得来的东西,我们真正要的东西是在frame里面的,直接用当前网址只是GR的阅读页面,要分享的话我们还是转去原始页面一次,才能使用上面说到的方法,不过我们既然都已经看到内容了还转过去一次再分享略显麻烦,所以我们要在GR的设置里面想办法,因为google一般都提供了很多的自定义功能,而且设置好的话是保存在自己的账号设置里面的,哪里都可以用,不像上面的方法是保存在浏览器上的。
打开google的setting,选择位于最右边的Send To标签,点下面的create a custom link

URL:http://share.renren.com/share/buttonshare.do?link=${short-url}
Icon URL:http://a.xnimg.cn/imgpro/share/share-tinybtn.png
这样填写,save就OK了,以后看到想要分享的文章时,直接点Send To->分享到人人网就行了。
其实这个方法原理很简单,看人人提供的站外分享的代码(这里):
<a href="javascript:void((function(s,d,e){if(/renren\.com/.test(d.location))return;var f='http://share.renren.com/share/buttonshare?link=',u=d.location,l=d.title,p=[e(u),'&title=',e(l)].join('');function%20a(){if(!window.open([f,p].join(''),'xnshare',['toolbar=0,status=0,resizable=1,width=626,height=436,left=',(s.width-626)/2,',top=',(s.height-436)/2].join('')))u.href=[f,p].join('');};if(/Firefox/.test(navigator.userAgent))setTimeout(a,0);else%20a();})(screen,document,encodeURIComponent));" title="分享到人人"><img src="http://a.xnimg.cn/imgpro/share/share-tinybtn.png" title="分享到人人"/></a>
稍微看一下这里的代码就知道人人的分享链接格式是这样的:http://share.renren.com/share/buttonshare?link=后面接上要分享的页面的地址,于是上面的就很好理解了,上面的URL刚好就是这样的格式组合出来的,下面的那个icon是图标,从上面这个人人网的分享代码里拉出来的。
可以举一反三,什么分享到开心,豆瓣之类的,还有微博等等,都是一样的原理,只需要看一下他们的分享代码,把上面的前缀部分改掉就可以了,详细参见这里:http://www.douban.com/note/41808100/
数学之美
1 x 8 + 1 = 9
12 x 8 + 2 = 98
123 x 8 + 3 = 987
1234 x 8 + 4 = 9876
12345 x 8 + 5 = 98765
123456 x 8 + 6 = 987654
1234567 x 8 + 7 = 9876543
12345678 x 8 + 8 = 98765432
123456789 x 8 + 9 = 987654321
1 x 9 + 2 = 11
12 x 9 + 3 = 111
123 x 9 + 4 = 1111
1234 x 9 + 5 = 11111
12345 x 9 + 6 = 111111
123456 x 9 + 7 = 1111111
1234567 x 9 + 8 = 11111111
12345678 x 9 + 9 = 111111111
123456789 x 9 +10= 1111111111
9 x 9 + 7 = 88
98 x 9 + 6 = 888
987 x 9 + 5 = 8888
9876 x 9 + 4 = 88888
98765 x 9 + 3 = 888888
987654 x 9 + 2 = 8888888
9876543 x 9 + 1 = 88888888
98765432 x 9 + 0 = 888888888
很漂亮,不是吗?下面这个更爽
1 x 1 = 1
11 x 11 = 121
111 x 111 = 12321
1111 x 1111 = 1234321
11111 x 11111 = 123454321
111111 x 111111 = 12345654321
1111111 x 1111111 = 1234567654321
11111111 x 11111111 = 123456787654321
111111111 x 111111111 = 12345678987654321
统计整数二进制表示中1的个数
这是一个很有意思的问题,也是在面试中最容易被问到的问题之一。这个问题有个正式的名字叫Hamming_weight,而且wikipedia上也提供了很好的位运算解决的方法,这个下面也会提到。
解决这个问题的第一想法是一位一位的观察,判断是否为1,是则计数器加一,否则跳到下一位,于是很容易有这样的程序。
int test(int n)
{
int count=0;
while(n != 0){
if(n%2 ==1)
count++;
n /= 2;
}
return count;
}
或者和其等价的位运算版本:
int test(int n)
{
int count=0;
while(n != 0){
count += n&1;
n >>= 1;
}
return count;
}
这样的方法复杂度为二进制的位数,即[tex]\log_2n[/tex],于是可是想一下,有没有只与二进制中1的位数相关的算法呢。
可以考虑每次找到从最低位开始遇到的第一个1,计数,再把它清零,清零的位运算操作是与一个零,但是在有1的这一位与零的操作要同时不影响未统计过的位数和已经统计过的位数,于是可以有这样一个操作 n&(n-1) ,这个操作对比当前操作位高的位没有影响,对低位则完全清零。拿6(110)来做例子,第一次 110&101=100,这次操作成功的把从低位起第一个1消掉了,同时计数器加1,第二次100&011=000,同理又统计了高位的一个1,此时n已变为0,不需要再继续了,于是110中有2个1。
代码如下:
int test(int n)
{
int count=0;
while(n != 0){
n &= n-1;
count ++;
}
return count;
}
这几个方法虽然也用到了位运算,但是并没有体现其神奇之处,下面这个版本则彰显位运算的强大能力,若不告诉这个函数的功能,一般一眼看上去是想不到这是做什么的,这也是wikipedia上给出的计算hamming_weight方法。
int test(int n)
{
n = (n&0x55555555) + ((n>>1)&0x55555555);
n = (n&0x33333333) + ((n>>2)&0x33333333);
n = (n&0x0f0f0f0f) + ((n>>4)&0x0f0f0f0f);
n = (n&0x00ff00ff) + ((n>>8)&0x00ff00ff);
n = (n&0x0000ffff) + ((n>>16)&0x0000ffff);
return n;
}
没有循环,5个位运算语句,一次搞定。
比如这个例子,143的二进制表示是10001111,这里只有8位,高位的0怎么进行与的位运算也是0,所以只考虑低位的运算,按照这个算法走一次
+---+---+---+---+---+---+---+---+
| 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | <---143
+---+---+---+---+---+---+---+---+
| 0 1 | 0 0 | 1 0 | 1 0 | <---第一次运算后
+-------+-------+-------+-------+
| 0 0 0 1 | 0 1 0 0 | <---第二次运算后
+---------------+---------------+
| 0 0 0 0 0 1 0 1 | <---第三次运算后,得数为5
+-------------------------------+
这里运用了分治的思想,先计算每对相邻的2位中有几个1,再计算每相邻的4位中有几个1,下来8位,16位,32位,因为2^5=32,所以对于32位的机器,5条位运算语句就够了。
像这里第二行第一个格子中,01就表示前两位有1个1,00表示下来的两位中没有1,其实同理。再下来01+00=0001表示前四位中有1个1,同样的10+10=0100表示低四位中有4个1,最后一步0001+0100=00000101表示整个8位中有5个1。