2012年4月23日星期一

非越狱ios的twitter方案

其他人我不清楚,对于我自己而言,发tweet的理由是基于以下几点考虑的:

  1. 可以有个地方随时记录自己的牢骚(都不好意思说思想两字)
  2. 厌恶国内微博浓烈的商业气息和娱乐味道,还有恶心至极的实名
  3. 对于社交性并不是那么在乎(刚开始会follow些名人,但已然厌倦),当然如果能有一两枚粉丝还是会暗爽的

一个很理想的场景是有个ios客户端,闷骚时就随手一tweet。虽然Twitter已有优秀的官方客户端,但在国内糟糕的网络环境下,就只能变成摆设。VPN我是考虑过的,但是懒得也舍不得购买。至于免费VPN,就没有找到好用的,tenacy VPN 得每次查询密码,刚开始想能克服,最终还是怕了这个麻烦。网上有教程说怎么在ios中装goagent,过程极为繁琐,看起来挺美,但我的itouch没有越狱,也不想越狱(好像已经说了好多次懒了,羞愧)。总之,就这么简单的需求也难有很好的解决方法。

忽然哪天灵光一闪,为什么不用email来发tweet呢?这篇博文介绍了使用twitterfeed.com + blogger 的方法来通过email发tweet。这是我现在采纳的方法,这个方法的优点就是可以方便的发tweet,不用担心vpn又登陆不上或是私有twitter api又被封的问题,而且相应的推文是发送的blogger的,这等于做了一个备份。缺点也很明显,就是完全没有了社交性,这对于我来说真不是问题,如果有强烈的社交互动需求的,那就要重新考虑考虑拉。

如果在google中搜“twitter email”,第一个链接是tweetymail这个服务。tweetymail看起来满不错的,可以通过邮件来回复等一定的社交性,更新twitter的速度比twitterfeed快,因为它是接收到邮件就更新,而twitterfeed是查看blogger rss的输出来相应地更新twitter。tweetymail让我不能忍受(主要是我的心里作祟)的地方有两点,让我放弃了使用这个服务:1. 免费用户每月发tweet有限额,不在于说限额是否满足自己需求(实际上100条是完全够的),而在于这样的限制让我挺不舒服的。 2. 免费用户的tweet都会在tweetymail上公开,应该是在它的服务器上有存档,这尤其令我难以接受。

twitterfeed + blogger 的方案也不是很完美,因为twitterfeed好像并不能作用在有图片的邮件,只能输出邮件中的文字而会忽略图片。还好这世上还有twitpic这个服务,它支持通过邮件来发送tweet,这时邮件必须有图片附件才会被twitpic转到twitter。所以这刚好与twitterfeed珠联璧合,相得益彰。

2012年2月15日星期三

emacs输入中文

症状:无法在emacs中调出ibus,输入中文
环境: Linux 2.6.32-5-amd64 + GNU Emacs 23.4.1
Locale:
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
解决:
(1)先用locale -a 查看是否安装 zh_CN.UTF-8,如果有,跳过步骤(2)
(2)运行sudo dpkg-reconfigure locales,安装zh_CN.UTF-8
(3)编辑/etc/environment文件,添加
LC_CTYPE="zh_CN.UTF-8"
重启即可

2012年2月10日星期五

euler 48: 大整数乘法

euler project 48:

The series, 11 + 22 + 33 + ... + 1010 = 10405071317.
Find the last ten digits of the series, 11 + 22 + 33 + ... + 10001000.

我是用python解的,python 的数没有大小的限制,这样就很方便,brute force.

在问题的讨论帖中,有人(grimbal)贴了他用C解决的算法。我觉得很优美,记录如下:

#define mod 10000
void ex48(){
    int n, k;
    unsigned int p2, p1, p0;
    unsigned int s2, s1, s0;
    unsigned int t2, t1, t0;

    // s = 0
    s2 = s1 = s0 = 0;
    for( n=1 ; n<=1000 ; n++ ){
        // p = 1
        p2 = p1 = 0; p0 = 1;
        for( k=1 ; k<=n ; k<<=1 );
        while( k>>=1 ){
            // p *= p
            t0 = p0*p0;
            t1 = 2*p0*p1 + t0/mod;
            t2 = 2*p0*p2 + p1*p1 + t1/mod;
            p0 = t0%mod;
            p1 = t1%mod;
            p2 = t2%mod;
            if( n&k ){
                // p *= n
                t0 = p0*n;
                t1 = p1*n + t0/mod;
                t2 = p2*n + t1/mod;
                p0 = t0%mod;
                p1 = t1%mod;
                p2 = t2%mod;
            }
       }
       // s += p
       t0 = p0+s0;
       t1 = p1+s1 + t0/mod;
       t2 = p2+s2 + t1/mod;
       s0 = t0%mod;
       s1 = t1%mod;
       s2 = t2%mod;
    }

    printf("ex48: %02d%04d%04d\n", s2%100, s1, s0);
}

2012年1月22日星期日

emacs利用g-client发blog

首先介绍和感谢下emacspeak的作者T. V. Raman。Wikipedia中是这 么写的:
T. V. Raman is a computer scientist who is blind.His accessibility research interests are primarily auditory user interfaces and structured electronic documents. He has worked on speech interaction and markup technologies in the context of the World Wide Web at Digital's Cambridge Research Lab (CRL), Adobe Systems and IBM Research.[2] He currently works at Google Research.
这样的牛人,着实让人敬仰。

要在emacs中向托管在blogger的博客发blog,emacswiki上介绍了好几种方案,比较流行的方 法是使用weblogger,我试验了一下,并不管用。最后我选择使用 g-client + emacs-w3m 的 方案。g-client是emacspeak中的一个组 件,利用Google DATA API 来访问google的服务,emacs-w3m是w3m的emacs前端。当然,还需 要emacs。

得到这个方案并不是轻松的。原因是网上仅有的一些关于g-client的介绍也都 已经过时,还起了误导作用;为了贪图方便,g-client 和 emacs-w3m 都是在其主页下载的 压缩包,但其实打包的版本过于陈旧,这也增加了我按图索骥的困难。最后摸索出来的教训 是:

  • g-client
    下载emacspeak的最新版,编译后,从/lisp/g-client提取到emacs load-path。
  • emacs-w3m
    emacs-w3m的主页上的稳定版居然是2005年 的,我还以为这项目没有更新了而已。这个版本中甚至g-client所需要的一些函数。应该下载cvs版。

配置文件如下:

;;=========== emacs-w3m ====================
(require 'w3m)
;;=========== emacs-w3m END ================

;; =============== g-client =================
(add-to-list 'load-path "~/.emacs.d/g-client/")
(load-library "g")
(setq g-user-email "yournamee@gmail.com")
;;设置访问时的代理, 后面的参数是默认的
(setq g-curl-common-options "--proxy 127.0.0.1:8087 --compressed --silent --location --location-trusted")
;;使用emacs-w3m访问
(setq browse-url-browser-function 'w3m-browse-url)
;; ================ g-client END ========================

2012年1月18日星期三

euler 3: Largest prime factor

题出自 Project Euler Problem 3:
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?

我自己的解法思路是先判断该数(记为A)是否为prime,如果是,则直接返回它本身。否则从该数的一半开始(记为index),判断index是否能被A整数以及index是否是prime,当两者同时满足时,返回index,否则index自减1。 判断某数是否为prime的算法,是从该数的平方根数开始一个一个检查。代码如下:

#include <stdio.h>
#include <math.h>

//#include <limits.h>

int is_prime(long l);
long largest_prime_factor(long l);

int main(int argc, char *argv[])
{
  long result = largest_prime_factor(600851475143L);
  printf("%ld\n",result);
  return 0;
}

int is_prime(long l){
  long l_sqrt = (long)sqrt(l);
  long i = 2L;
  for(; i <= l_sqrt; i++){
    if(l % i == 0)
      return 0;                 /* is not prime */
  }

  /* is prime */
  return 1;
}


long largest_prime_factor(long l){
  if(is_prime(l))
    return l;
 
  long l_mid = l/2;
  long l_ind;
  for(l_ind = l_mid; l_ind >=2; l_ind--){
    if((l%l_ind == 0) && is_prime(l_ind))
      return l_ind;
  }

  return 1; // never come here
}



上面的算法很惨,算了几十分钟都没有算出结果。所以最后我放弃了,google到了下面这个算法:

#include <stdio.h>

long largest_prime_factor(long l);

int main(int argc, char *argv[])
{
  long result = largest_prime_factor(600851475143L);
  printf("%ld\n",result);
  return 0;
}

long largest_prime_factor(long l){
  long factor = 2L;
  while(l > 1L){
    while(l % factor == 0 ){
      l = l / factor;
    }
    factor++;
  }

  return (factor-1);
}

细想一下,这个算法与筛选法类似。但是,我怎么就没想到呢?FAIL!!!

2012年1月6日星期五

cURL “虾米” 签到的小脚本

这个脚本用于登陆虾米网站,并进行签到。虽然只是个二三十行的脚本,但由于对cURL不甚
了解,还是搞了几天。主要的经验有:

  1.  curl 用 -d 发送表单时,要把按钮的值也加进去("submit=登录")
  2.  curl 处理 ajax,应该通过分析javascript脚本,找到真正接收请求的url
  3.  curl 模拟 ajax时,添加 HTTP头 "X-Requested-With: XMLHttpRequest",更好的方法是观察实际的HTTP头,并构造出个一样的
  4.  总之,分析浏览器的HTTP请求,再用 cURL构造即可。


#! /bin/bash

declare -r SCRIPT="${0##*/}"

SITE="http://www.xiami.com"
USERAGENT="Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.0)"
COOKIEFILE="cookie.txt"

USER="********@gmail.com"
PASSWORD="******"

# 检测cookie
if [[ ! -e $COOKIEFILE ]];then
    # 登录xiami
    curl -c $COOKIEFILE -d "email=$USER&password=$PASSWORD&submit=登录"  "$SITE/member/login"
fi

# 单击"签到"
curl -s  -b $COOKIEFILE -A "$USERAGENT" -e "$SITE" -H "X-Requested-With: XMLHttpRequest" -X POST -d "" "$SITE/task/signin" --retry 5 -H "Connection: keep-alive" 1>/dev/null

# 删除cookie
#rm $COOKIEFILE

2012年1月1日星期日

判断无符号整数二进制中1的个数(外一则)


三种算法。

算法1:
比较容易想到的算法,逐位比较,最多需要32次。
int count_ones_01(unsigned int n)
{
    int i;
    for(i = 0;n > 0;n >>= 1)
         i += (n&1);
    return i;
}

算法二:
Monster级算法。比较次数比算法1少,最多需要32次(如果int长度为32位的话)。
int count_ones_02(unsigned int n){
  int count=0;
  while(n>0){
    n &= (n-1);
    count++;
  }
  return count;
}

算法三:
二分法。遗憾的是不具有跨平台性。运算次数为5次(\(\log_{2}{32}\))
int count_ones(unsigned 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;
}

算法的思路是这样的:2位为一组,相加,看看有几个1。再4位为一组,相加,看看有几个1,
以此类推。
为了简单说明,先看看8位的情形。
x = (x & 0x55) + ((x >> 1) & 0x55);    (1)
x = (x & 0x33) + ((x >> 2) & 0x33);    (2)
x = (x & 0x0f) + ((x >> 4) & 0x0f);    (3)
return x;

对于语句(1)

当x=11111111
x= (x & 0x55) + ((x >> 1) & 0x55);
之后x=10101010。你2位2位地看,10=2, 就是2 2 2
2, 就是说各组都是2个1。

当x=00101001
x= (x & 0x55) + ((x >> 1) & 0x55);
之后x=00010101。你2位2位地看,就是0 1 1 1, 前
1组只有0个1,后面的组都是1个1。

接着看语句(2)

当x=abcdefgh
x=(x & 0x33)+((x >> 2)&0x33);
相当于 00cd00gh + 00ab00ef。

因为语句(1)之后,每两位表示该两位有几个1,相加就指示每4位有多少个1。这样就是4位
4位为一组。注意这样的分组,组与组之间永远都不会产生进位的。正因为不会产生进位,才
可以分开来看。

8位,16位,32位依上类推。

外一则:
利用算法三类似的思想,进行反转一个字节的二进制次序。
unsigned char reverse8( unsigned char c )
{
     c = ( c & 0x55 ) << 1 | ( c & 0xAA ) >> 1;
     c = ( c & 0x33 ) << 2 | ( c & 0xCC ) >> 2;
     c = ( c & 0x0F ) << 4 | ( c & 0xF0 ) >> 4;
     return c;
}