退步集

读陈丹青的退步集,你会发现他像是一个有些愤青的老头子,我看到过他与韩寒的一期节目的时候,这位愤青老头子居然是年轻的。光头、西装和眼镜。郑渊洁也是光头,一个写童话的愤青,有社会责任感,能够出名,善于推销自己的产品,能够赚钱。其实,在某种程度上,光头陈丹青也是。

陈丹青出名于西东篱把酒黄昏后藏组画,之后以画家身份移居纽约18年,归国后为清华大学特聘教授,任教5年递交辞呈。退步集里收录了他的辞呈,除了辞职报告之外,还有几篇坦陈对教育体制和清华大学艺术学院教学的质疑,言辞温和而恳切。他辞职的原因,从他的辞呈可以看出来--一位老师,选择弟莫道不消魂子的权利被种种规矩制度所限制缩小到一定限度而不得的时候,一位先生,当他想教导学生”独立之人格,自由之思想“时,却发现和大环境和体制格格不入的时候,一位教师,在三番进谏而不纳的情况下,再大的大师和再光的光头,也会生气走人的。

此人睿智,有时候很有见地,比如在评论房地产的时候,他说到:”开发房地产,是一回事;盖更多的房子给人住,又是一回事儿。“;在谈到贫富差距的时候他说到:”美国的贫富差距比中国大多了,但他有一套机制,维持社会最后一丁点儿公正与平衡;... ... 中国现在的问题不是贫富悬殊,是不公正,不平衡。“;
此人愤青,锋利而且一针见血,比如在谈到作秀他说到:”我不骂明星,明星挺好。有个别人猖狂,欺负人,但绝不会比贪官更猖狂,更欺负人。贪官欺人太甚,谁敢言语?言语了又怎样?好,哪位明星使一回性子,众人就吐口水,要他道歉。中国人到了欺负弱者,欺负站在名里的人,立马个个义正言辞。“

此人有自知之明,却不失本心。”我现在有两个态度,一是说话没用的,所以第二,保持说话,这是最后一点权利,如此而已。“

本来还要写些的,但是我瞌睡了,所以我开始写结尾。

退步集是可看的一本书,有文采,有思想,有文人的忧患意识,适合关掉电脑,闲来无事的读。

Posted in 读书 | Leave a comment

Play with bits

Have fun with bits...

1. Big bits table.

#define BITSPERWORD 32
#define SHIFT 5
#define MASK  0x1F
#define N     10000
unsigned int a[1+N/BITSPERWORD];
void set (unsigned int i) { a[i>>SHIFT] |= 1 << (i&MASK); }

2. Bit operations.

  • Splitting a set into it's elements:x & ~(x-1)
  • For a << b, b must >=0 && < sizeof(b)*8.
  • The & and | have lower precedence than comparison operators. So we should write if ((a & MASK) != 0x1F).
  • Be sure to use unsigned types.

3. TC problem, TCO2006, Round1 Easy. problem

The small number of nodes strongly suggests that this is done by considering all possible subsets. For every possible subset we consider two possibilities: either the smallest-numbered node does not communicate at all, in which case we refer back to the subset that excludes it, or it communicates with some node, in which case we refer back to the subset that excludes both of these nodes. static int dp[1 << 18];

int SeparateConnections::howMany(vector <string> mat)
{
    int N = mat.size();
    int N2 = 1 << N;
    dp[0] = 0;
    for (int i = 1; i < N2; i++)
    {
        int bot = i & ~(i - 1);
        int use = __builtin_ctz(bot);
        dp[i] = dp[i ^ bot];
        for (int j = use + 1; j < N; j++)
            if ((i & (1 << j)) && mat[use][j] == 'Y')
                dp[i] = max(dp[i], dp[i ^ bot ^ (1 << j)] + 2);
    }
    return dp[N2 - 1];
}

Posted in 算法之美 | Leave a comment

tang paradise

google summer of code 的500刀还没来,便给我败了一Ricoh gx200。 周末刷了一遍大唐芙蓉园,绝对新手,有较强心理承受能力的可以参见我的flickr

Posted in 算法之美 | 1 Comment

校鸟评选的代码 (囧)...

2.
bmy上有人突发奇想,搞出了一校鸟评选 :)
我就很好奇的写一堆代码分析了一下结果。看来麻雀人缘不错。得到了53/138票。

一堆代码:

# -*-coding:utf-8 -*-
# date: 2009-4-16
# author: Li Feng (NemoK@bmy)
# ATTENTION: Do not read the some bit dirty code unless you
# want to MAKE IT CLEAR
from BeautifulSoup import BeautifulSoup import urllib2 import re import time
birds = [u'麻雀', u'灰喜鹊', u'白头鹎', u'斑鸠', u'戴胜', u'八哥', u'鹡鴒', u'啄木鸟'] dicts = dict([[bird, [0,[]]] for bird in birds]) URLBASE = 'http://bbs.xjtu.edu.cn/BMYKAUVLIJBGXOPZXWBZZFJGURPLXHAFRUFZ_B/' URLCC = 'bbstcon?board=Nature&start=2444&th=1239798398' cnt = 0 total = 0 valid = 0
while(True): print cnt cnt+=1 print URLCC URL = URLBASE + URLCC response = urllib2.urlopen(URL) html = response.read() soup = BeautifulSoup(html, fromEncoding='gb18030') comments = soup('tbody') for comment in comments: total+=1 cc = comment.contents[2].td
# AUTHOR is one line like: # 发信人: NemoK (春暖花开), 信区: Nature
author = unicode(cc.contents[0])
# here we just find if the user's comment SAY_BIRDS # match any bird in BIRDS # we simply exclude the quote start by '【'
contents = unicode(cc.renderContents(), 'utf-8') author = re.compile(r'\W+').split(author)[1] say_birds = contents.split(u'【')[0] for bird in birds: if say_birds.find(bird) != -1: valid+=1 dicts[bird][0]+=1 dicts[bird][1].append(author) break
# follow the NEXT_PAGE link to next page till # we meet the last
next_page = soup('a')[-2] print next_page if next_page.contents[0] == u'本讨论区': break URLCC = next_page['href']
print 'time: %s' % time.asctime() print '=====================================================' print "totla voters: %d, valid voters: %d" % (total, valid) for bird in dicts.keys(): print "bird: %s, num: %d " % (bird.encode('utf-8'), dicts[bird][0]) print "voters: %s" % ', '.join(dicts[bird][1]) print
Posted in programming | Leave a comment

秒杀git :~D (git tutorials)

最近由于项目需要,从svn该到了git。从网上搜了一堆教程,所以,我不打算重复,只推荐最佳阅读顺序: 1,2必读,3,4强烈推荐,秒杀git :~D

Maybe you want to read this first:

Why is git better than Subversion?

1. 入门级...快速上手,完美简洁

Git Tutorial : Starting with git using just 10 commands

2. 官方教程, 稍微上了一个小台阶

gittutorial(7) Manual Page

3. 如果你想了解更多: git object model

The Git Object Model

4. 实际操作,帮你理解git object model

gittutorial-2(7) Manual Page

enjoy :~)

Posted in programming | Tagged | Leave a comment

如何使用gdb调试代码(三、如何查看变量)

当你想了解或者参与一个较大项目的时候,往往调试是最佳的解决方案,通过调试能 够获得你需要部分代码的运行情况,以及通过代码中原有debug函数来得到一些中间 结果。

gdb能够很好的做这件事情,可以通过ptype获得结构体的结构信息,同时也可以获取 变量值。一个比较有用的功能便是你可以在调试过程中调用函数来获取你想要的输出。 这里通过一个例子来表述:

typedef struct vec
{
    int size;
    char name[1];
}vec;
int debug_cat(vec* v) { printf("vector size:%d\nvector content:%s\n", v->size, v->name); fflush(stdout); }
int main(int argc, char *argv[]) { char name[] = "hello world"; int len = strlen(name); vec *v = malloc(sizeof(vec)+len); strcpy(v->name, name); printf("%s\n",v->name); fflush(stdout); v->size = len; return 0; }

启动

>>gdb a.out
Starting program: /home/okidogi/Coding/blog/how_to_debug_with_gdb/src/a.out
>>b 26
Breakpoint 2, main (argc=1, argv=0xbf826ed4) at test.c:26
26          return 0;
>>r
Breakpoint 2, main (argc=1, argv=0xbfd54c04) at test.c:26
26          return 0;

获取结构体的信息

可以通过ptype获取结构体信息,或者变量类型信息。ptype后边可以直接跟变量,或者结构体 名称。

>>ptype v
type = struct vec {
    int size;
    char name[1];
} *
>>ptype vec
type = struct vec {
    int size;
    char name[1];
}
>>ptype name
type = char [12]

获取变量值

可以通过p加变量名称获得变量的值。

>>p *v
$1 = {size = 11, name ="h"}

对于指针可以取得指针地址

>>p v
$2 = (vec *) 0x804a008

在上边的表述中我们可以看到gdb对于结构体vec中name打印出来了name="h", 如果我们期望它能够打印出来我们想要的结果,比如我想要输出成这样的样子:

vector size:11
vector content:hello world

这一点的实现我们可以自己来写debug函数,通过在gdb中调用来达到我们期望的效果。 在本例中debug_cat(vec *v)便是一个这样的函数。我们可以在gdb中通过调用:

>>set debug_cat(v)
vector size:11
vector content:hello world

这是一个非常有用的技巧,如果你能在编写源代码的时候就写这样的debug_函数出来, 对于代码的可维护性无疑是很有帮助。

Posted in 算法之美 | Tagged | Leave a comment

easyshell 1.0 alpha released :D

在用windows底下串口调试用超级终端的时候实在不爽,数据经常被刷掉找不回来,刚好项目到了收尾阶段,不是太忙,袖子一挽,便磊了几天代码,现在终于磊成一个石头堆了 :) 。  一堆难看的代码。不过自己用着觉得还不错 :D

当初建立这个prj的时候我是在写单片机代码,通过计算机串口传输命令和调试的。实际上说白了就是封装封装printf函数,配置单片机的串口,一堆类似 的东西。当然,我们通过命令行来对单片机进行控制和调试,就再加上一堆命令行解析的东西,后来我觉的太体力了没意思,自己又加上了命令行自动补全。

同样的代码理论上来讲我是不大愿意写两遍的。同样的代码理论上来讲我是不大愿意写两遍的。而这一堆东西的需求很明朗,于是我便想着写一个容易保存的版本,就是easyserial这个小项目。我想我大约会陆陆续续的来做这件事情,权当作自娱自乐罢。

西安很干燥,5、6个月硬是没有憋出雨来,以至于前些日子的一场人工降雪让我误以为是神迹,现在回想起来仍是恍若梦中。

Posted in 算法之美 | Tagged | Leave a comment

如何使用gdb调试代码(二.如何设置断点)

如何设置断点

less is more...

编译需要调试的代码:

gcc -g test.c -o test

启动gdb:

gdb test

一般来讲,设置断点有四种方式:

  1. 通过函数名
  2. 通过行号
  3. 通过文件名+函数名/行号
  4. 通过地址

通过函数名:
对于c++来讲,由于有多态,因此,函数名不能唯一定义一个地址,
所以需要包含完整的参数类型。

(gdb) b main
Breakpoint 3 at 0x8048a97: file test1.cpp, line 5.
#(gdb) b TestClass::testFunc(char *)
#Breakpoint 3 at 0x8048a97: file test1.cpp, line 15.

通过行号:

(gdb) b 8
Breakpoint 4 at 0x8048aae: file test1.cpp, line 8.

通过文件名+行号

(gdb) b test1.cpp:9
Breakpoint 5 at 0x8048ae4: file test1.cpp, line 9.

通过地址:

(gdb) print main
$1 = {int (int, char **)} 0x8048a80 <main>
(gdb) b *0x8048a80
Breakpoint 6 at 0x8048a80: file test1.cpp, line 5.

有条件断点:
在调试过程中一个比较有用的设置便是有条件中断,比如以下指令:

(gdb) b 3 i>92

上边的这个命令告诉gdb如果运行到断点3的时候i大于92便发生中断停止,
否则继续运行。挺有用的一条指令。

查看设置断点情况可以通过info breakpoints,比如经过上边的设置,我们
得到了4个断点:

(gdb) info breakpoints
Num     Type           Disp Enb Address    What
3       breakpoint     keep y   0x08048a97 in main at test1.cpp:5
4       breakpoint     keep y   0x08048aae in main at test1.cpp:8
5       breakpoint     keep y   0x08048ae4 in main at test1.cpp:9
6       breakpoint     keep y   0x08048a80 in main at test1.cpp:5

清除断点一般可用clear和delete两条指令,clear后跟函数名,行号,或者地址,
跟break的参数是一致的,而delete后边则跟断点标号。

(gdb) clear main
Deleted breakpoint 3
(gdb) info breakpoints
Num     Type           Disp Enb Address    What
4       breakpoint     keep y   0x08048aae in main at test1.cpp:8
5       breakpoint     keep y   0x08048ae4 in main at test1.cpp:9
6       breakpoint     keep y   0x08048a80 in main at test1.cpp:5
(gdb) delete 5
(gdb) info breakpoints
Num     Type           Disp Enb Address    What
4       breakpoint     keep y   0x08048aae in main at test1.cpp:8
6       breakpoint     keep y   0x08048a80 in main at test1.

如果你想暂时屏蔽某个断点并不打算删除的话可以使用disable,恢复则用enable:

(gdb) disable 4
(gdb) info breakpoints
Num     Type           Disp Enb Address    What
4       breakpoint     keep n   0x08048aae in main at test1.cpp:8
6       breakpoint     keep y   0x08048a80 in main at test1.
(gdb) enable 4
(gdb) info breakpoints
Num     Type           Disp Enb Address    What
4       breakpoint     keep y   0x08048aae in main at test1.cpp:8
6       breakpoint     keep y   0x08048a80 in main at test1.
Posted in linux, programming | Tagged | 1 Comment

如何使用gdb调试代码(一、A Globla view of GDB)

在前面的文章如何使用emacs阅读源代码中提到了打算写一篇如何使用gdb调试源代码 这样的文章,近日又刚好闲了下来,便挽起袖子,关门沏茶,一把ssh过去,便开工了。

History of GDB

GDB被用来调试代码,如果你习惯了用IDE来做那么一连串的事情,你可以尝试着从IDE中 解脱出来,看看IDE之外的世界。 RMS爷爷于1986年写了gdb的第一个版本,之后以GPL发布。现在gdb仍被一堆自由软件热爱 者捣鼓着。2006年左右gdb开始着手于实现"eversible debugging",现在不知道进展 到了什么程度。什么是eversible debugging,说白了就是你执行下一步下一步正高兴着 呢突然发现执行过了现场跑了怎么办?那就靠神奇的eversible debugging来执行一条 称之为"上一步"的指令。于是,一切便重演了。

A Global View of GDB

before GDB start

在gdb启动之前,需要在编译源代码的时候加上-g选项。

gcc -g test.c -o test

对于我们而言,在代码中有函数名fancy_abort,变量名i等,但对于计算机来讲, 可能便是0x3993930a,0x3929ffce等。因此,我们需要提供给gdb一张符号表。 gcc的-g选项便提供了这个功能。事实上-g选项会告诉gdb两件事情: 1. 如何将一个 符号地址和源代码中的名称联系起来 2. 如何将一条机器码的地址和一行源代码联系起来。

启动gdb:
[code=bash]gdb test
(gdb) run
Starting program: /home/okidogi/blog/how_to_debug_with_gdb/src/testProgram exited normally.
(gdb)[/code]
其中run可带参数执行,即run arg0 arg1。便是程序的命令行参数。

GDB启动时候所做的事情

作为一个全局的大致性的了解,我会粗略解释gdb配置文件的格式及功能,详细的说明 会在合适的时候出现。一般来讲,gdb在初始化的时候大致做了以下几件事情。(注:这 个列表是不完整了,我略去了几条看起来不大重要的部分)。

  1. 执行~/.gdbinit文件。初始化一些命令,参数。
  2. 解析命令行参数。
  3. 执行当前工作目录下面的.gdbinit文件。 因为启动时先执行1再执行2,因此你不能在~/.gdbinit中设置断点等操作(还没有读取你要调试 的文件),当然你可以把一些使gdb用起来很舒服的设置放在这儿。当前工作目录下的.gdbinit文件 是一个良好的对各个工程可以分别对待的配置文件。这儿你可以做设置断点,写自己的函数等一系列 的事情。

    .gdbinit文件

.gdbinit文件在gdb初始化的时候对gdb进行配置。我不打算很详细的在这里将如何写这样的文件, 我抽取了gcc中gdb配置文件(gdbinit.in)的一部分来做为例子,做大致的说明:

define ptn
output $.type.name->decl_minimal.name->identifier.id.str
echo \n
enddocument ptn
Print the name of the type-node that is $.
end# Put breakpoints at exit and fancy_abort in case abort is mapped
# to either fprintf/exit or fancy_abort.
b fancy_abort
# Put a breakpoint on internal_error to help with debugging ICEs. b internal_error
set complaints 0

在这个配置文件中,define可以用来定义自己的命令,这些命令可以在gdb中调用。define 和end block标识了一个用户自定义函数的完整定义。document end block则表述了对于定义函数 ptn的说明文档。在gdb中调用help ptn便会打印字符串"Print the name of the type-node that is $."。b fancy_abort即在调试代码中的fancy_abort函数处设置断点。b internal_error亦是同理。set complaints 0则是设置gdb为no complaints。

在下一节,大约会写写关于如何设置断点方面的内容。敬请关注 :D

Posted in linux | Tagged | 1 Comment

Real Python ---- zip

What does this do?

L = [1,2,3,4,5,6,7,8,9]
zip(*(iter(L),)*3)

Firstly

python reference中的解释:

zip([iterable,...]) returns a list of tuple, where the i-th element from each argument sequences or iterables.The returned list is truncated in length to the length of the shortest argument sequence. 返回一个tuple的列表。比如:
>>> x = [1,2,3]
>>> y = [4,5,6]
>>> zipped = zip(x,y)
>>> zipped

[(1,4),(2,5),(3,6)] 实际上,zip做的事情便是依次调用可遍历对象的next()函数,遍历一次,组成一个tuple。 比如 zip(x,y) 实际上相当于调用x = iter(x), y = iter(y), 之后, [(x.next(),y.next()),(x.next(),y.next()),(x.next(),y.next()),...]。直到 x.next() or y.next() 抛出 StopIteration 的异常。

>>> x = [1,2,3]
>>> y = [4,5,6]
>>> x = iter(x)
>>> x.next()
1
>>> x.next()
2
>>> x.next()
3
>>> x.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

zip(*L)用来对一个zip后的数组做unzip操作。

>>> x2,y2 = zip(*unzipped)
>>> x2 == x, y2 == y
True

secondly

>>> L = [1,2,3]
>>> li = (L,)*3
>>> li
([1, 2, 3], [1, 2, 3], [1, 2, 3])
>>> li[0][1] = 9
>>> li
([1, 9, 3], [1, 9, 3], [1, 9, 3])

Thirdly

>>> L = [1,2,3,4,5,6,7,8,9]
>>> a = zip(*(iter(L),)*3)
>>>
>>> (iter(L),)*3
>>> (<listiterator object at 0xb7deae6c>, <listiterator object at 0xb7deae6c>, <listiterator object at 0xb7deae6c&gt ;)
>>> a
[(1, 2, 3), (4, 5, 6), (7, 8, 9)]
Posted in programming | Tagged , | 2 Comments