RemGRE Version 1.1 (Build 2 for Windows XP compatibility)

首先,我要在这里感谢shawn童鞋,他热情的参与使用了这个软件并提供了bug的详细信息。同时也感谢所有使用这个程序的童鞋。

本着让Windows XP下的机油快速使用上这个背单词软件的目的,我先详细叙述如何在XP平台上使用这个软件,然后我会分享一下这个bug的产生的原因,希望也能对在.NET平台上孜孜不倦开发的童鞋一点“跨平台”的启示(当然,跨的是M$的各家平台)。

如何在XP下运行?

  • 第一步,安装.net framework 2.0及其以上版本(Vista或以上版本不需要,因为微软已经自动集成了)。点这里可以下载(安全性大可放心,因为这是微软官方网站上复制下来的链接)。
  • 第二步,点这里下载这个软件,然后请参照之前的几篇博客(这篇这篇)可以看到其基本使用方法。

到这里已经把如何运行说明清楚了,相信参加GRE考试的聪明的童鞋们已经能够顺利的使用上这个软件来帮助记忆万恶的GRE单词。好了,下面就说说BUG产生的原因了。

Where is the bug from?

长话短说吧,这个bug来自于Windows XP和Windows Vista/Windows 7的颜色差异上。为什么呢?

举个例子,同样的一个Backcolor叫ActiveCaptionText,在Windows Vista/Windows 7上是黑色,但是在Windows XP上呈现出来的是白色,这样,由于我设置的字是白色的,所以,主界面就显得什么都没有了。从这个问题中,我们在GUI布局上不应该用系统颜色,而应用绝对颜色,譬如Black,White等。这样,平台之间的差异就会被抹平。其实不光在颜色这里,其他所有的方面都不要用系统相关的东西,这会使得不同平台的用户体验不相同。好在Windows XP,Windows Vista等产品都是M$的,所以系统的差异性要远远小于Windows和Linux的差异性,因此很多的windows特性依旧能够利用,譬如底层的Win32 API调用。好了,说了那么多废话,归根结底就是一句话,尽量用通用的东西。

Open Source

秉着开源精神,现提供最新版本的源代码(GPL第三版授权)。点击这里下载。


RemGRE Version 1.1

花了两天时间改版了一下,主要是在交互上进行了一些友好性的探索,不知道大家感觉如何。在内核上基本没有进行改动,所以如果你觉得不喜欢新版的交互方式,当然可以继续用1.0版本的。

What’s new

  • 改用VIM式的命令方法(用’:'启动命令输入)替代原本的控制台,使得界面更加紧凑简洁。

  • 增加了如下快捷键(不多,主要是因为很多命令需要参数):
        H:打开帮助文档。
        S:显示遗忘列表。
        Q:退出程序。
        L:加载保存的列表。
  • 增加了命令提示功能。

  • 整合了“红宝”词库,不再担心丢失vocabulary.rem。
  • 增加了对图形用户界面的支持,详情请右击程序主界面。

点击此处下载该程序


RemGRE

最近忙里偷闲,我就翻开以前写过的程序回味一番,找到了这个——RemGRE,一个用来帮助记忆GRE单词的程序。

平台要求

编写这个程序的时候,我非常热衷于C#(虽然我已经离开windows平台有一年了,用了大半年的linux,现在用mac),现在看来,开发简单的windows窗体程序,C#还是我的首选,因为简单。当然,如果需要写病毒,写外挂我还是会用C#,因为微软替dot net程序员考虑了很多操作系统native接口的集成,让C#变得更加强大。貌似在Java上就难以调用Windows底层接口,这样制作平台相关的应用就变得十分困难。闲扯了这么多,有点离题了,总而言之,这个程序是用C#编写的,要运行它你就需要.net framework 2.0+,这个在windows vista及其以上版本是自动集成的,在windows xp上你需要下载这个并安装。

如何使用?

其实,当时写这个程序只是考虑给自己用的,所以,UI的设计遵循效率优先的原则。简单的说,我希望这个程序能够真正帮我记忆GRE单词,而不是花架子。在设计UI的时候有一个小小的故事。

我看过很多其他背单词的软件,在这类软件中有一个基本的问题——判断用户是否认识这个单词。由于泱泱天朝地大物博,语言文化极其丰富,一个意思可以对应N个词语,而且N往往还很大。所以,很多同类软件都采用选择题的方式,只要判断用户的选择结果是否与“数据库”中的结果一样。这其实是一个很糟糕的做法。因为选项往往会对本来模糊的意识产生一个暗示作用,这对记忆单词是不利的。所以,我把判断对错的任务交给用户,让用户告诉我他是否想到了正确答案,然后我再记下那些他没有回忆起来的单词强化记忆。说了半天又有点跑题了,下面我说说如何使用这个程序。

这是初始界面,很简洁,是吗?大部分操作都需要通过ESC(左上角那个键)呼出命令控制台来完成的,这是出于我对键盘的喜爱。根据以往的经验,纯键盘的效率往往会高于鼠标的效率。背单词嘛,讲究的就是效率,不要在任何不相关的地方浪费时间,包括用鼠标点菜单的时间。而且,我相信大多数考GRE的同学电脑水平都应该很不错,命令行虽然提高了使用的门槛,但是不会挡住太多的同学。

通过test命令,你就可以开始单词测试之旅啦。看上图右边Console窗口中的test命令,它后面跟的参数是你需要测试的list号(忘记说了,这里面囊括的单词都是红宝书2008版的,list号也是根据该书来的)。其中1-10表示第一道第十个list,13表示第13个list,中间用分号隔开,这应该都看得懂吧。为了让测试更加有效,单词的顺序并非是红宝书上的顺序,这样可以防止因为顺序记住单词意思的bug。

当一个单词出现时:

  • 回想单词的意思。
  • 按J显示单词的意思。
  • 如果你回想正确,按I;否则,按O。

如果你想了解这个单词更详细的信息,你可以用鼠标双击这个单词。当然,秉着所有操作都可以在命令行里执行的原则,你也可以通过ESC呼出控制台,然后输入命令:look denizen。look后面就是你需要查的单词。当然,需要使用这个功能你必须处于联网状态。

show是一个比较常用的命令,你可以通过它显示未记住的单词。它怎么知道我哪些单词没有记住?还记得之前的背单词过程吗,按J显示单词的意思,紧接着I表示记住了,O表示没有记住。为什么我设计使用这几个键?因为这几个键正好是右手比较舒适的“抚摸”键盘的姿势,左撇子对不住了……看到主窗口(RemGRE)上的20/1820了吗,这表示这么多list一共有1820个单词,你现在已经测试到第20个了,当你测试完以后,RemGRE会把你missing的单词打乱顺序接着考你!这个过程直到你所有的单词都能正确回想出。

save/load也是非常常用的命令。save是用来保存的,保存什么呢?看到save后面的c没有,c表示当前正在背的单词,后面紧跟文件名。这样,关掉程序以后你也可以再次加载你保存的这些单词。如果save后面跟的是m,那么当前遗忘列表里的单词会被保存到指定文件中。那么为什么要有这样的区分呢?我的实践告诉我,我背啊背的就把一轮背完了,这时新的一轮包含所有我上一轮没有记住的单词,但是遗忘列表已经清空,那我想要保存上次遗忘列表里的单词怎么办呢?就把当前背的单词保存下来不就行了,所以save后面会有一个参数指明当前列表or遗忘列表。这样以后,你可以今天背完之后把遗忘列表中的顽固单词保存下来,第二天背之前加载进来再过一遍,把这些顽石单词强化攻克!

后记

还有一些其他的命令我就不一一列出了,想要全面了解的话就下载下来看看里面的readme.html吧。我还有一些新的想法,我觉得单独做一个Console窗口有点冗余,为什么不把主窗口和Console窗口合并呢,采用Vi的命令输入样式去整合,这样使得界面更加简洁。如果你觉得这个程序很好用,就请告诉别人,让更多人享受到高效的单词记忆带来的快感;如果你觉得这个程序不好用,请告诉我,让我能不断的改版原有的程序。

点击此处下载该程序


数学建模预赛

这几天都纠结于数学建模的预赛,一道很复杂的题目!题目大概是这样的,一个送货员(有负重限制),要在一个地区送100件快递,如何才能最快的送完?

第一天

用floyd算法简单的计算了下任意两点间的最短路径,死盯着那张恐怖对地图,把自己假想成那个倒霉的送快递的,算好一次出发能够带的东西,尽量把背包塞的满满的,然后像个孤魂野鬼穿梭于各个节点之间。用了N多程序去模拟,分块,搜索,试图找出最优解,但是,实际上在这么巨大的解空间找一个最优解无疑是大海捞针。一天下来,没有模型,没有最优解,没有方向,只有疲惫和交瘁。

第二天

瞎忙活了一天,没有什么结果,第二天基本照旧,还是像第一天那样没头苍蝇乱碰墙。但是,晚上出现了转折点,大杨给我们带来了希望。模拟退火算法,不得不感叹世界的奇妙。

模拟退火算法

所谓模拟退火算法,其名字是来源于冶金学中的退火过程。当晶体处于高能量状态时,其粒子的排列是混乱无序的,按照物理术语说是熵很高。但是,当温度降低的时候,在总的趋势上晶体由高能态转变为低能态,粒子的排列趋于整齐有序,熵降低。想象一下,烧红的铁块扔到冰水里去是什么场景?一团水蒸气化成的小液滴冉冉升起…

那么这个算法具体是什么样的呢?这里面要先说明一下几个重点。

  • 温度参数T,且T会随着时间的推移而不断降低
  • 状态S
  • 能量函数E(S),对于每个状态,都有一个能量值与之对应
  • 状态转移概率函数P(eo, en, T),eo表示当前状态的能量值,en表示新状态的能量值,T表示当前温度。这个函数最终返回状态转移的概率。其中还有一个小细节。当新状态的能量值小于当前状态的能量值时,P返回1,表示一定转移。当新状态能量高于当前状态时,这个概率遵守一个热力学公式:e^((eo-en)/t) 。其实,如果你很固执的觉得只有新状态的能量更低时才转换的话,冷却效果会远远不如这个,造物主真的很神奇!
  • 寻找近邻函数neighbour(S)

模拟退火算法的主要用途就是在一个巨大(有限)的解空间中找出逼近最优解的解,且这个方法往往要比穷举效果好(废话嘛,时间上肯定是不允许的,尤其是NPC问题)。下面我把我的代码贴出来,主旨在于展示模拟退火算法的结构和实做。

#include 
#include 
#include 
#include "sa.h"
 
#define PRINT(S) for(i = 0; i < N_OBJ; i++) \
                         printf("%d ", S[i]); \
                         printf("\n");
#define RANDOM() ((double)rand() / (double)RAND_MAX)
 
int nb[N_OBJ];
double T = 2000;
double rad = 0.9;
 
char _test(int * bag, int n) {
    int i;
    double w = 0;
    double v = 0;
    for (i = 0; i < n; i++) {
        w += objects[bag[i] - 1].weight;
        v += objects[bag[i] - 1].volume;
    }
    return w <= WEIGHT && v <= WEIGHT;
}
 
double _dispatch(int * bag, int n) {
    int i, loc = 0;
    double distance = 0;
    for (i = 0; i < n; i++) {
        int next = objects[bag[i] - 1].loc;
        distance += dismat[loc][next];
        loc = next;
    }
    distance += dismat[loc][0];
    return distance;
}
 
/* l should go back one step if
 * it doesn't pass the test.
 */
double E(int * S) {
    int p = 0;
    double distance = 0;
    do {
        int l = p;
        while (l < N_OBJ && _test(S + p, l - p))
            l++;
        if (l < N_OBJ || !_test(S + p, l - p))
            l--;
        distance += _dispatch(S + p, l - p);
        p = l;
    } while (p < N_OBJ);
    return distance;
}
 
char accept(double eo, double en, double t) {
    if (en < eo)
        return 1;
    else
        return exp(-(en - eo) / t) > RANDOM();
}
 
void neighbour(int * S) {
    int i, j, h;
    i = rand() % N_OBJ;
    j = rand() % N_OBJ;
    if (i > j) {
        h = i;
        i = j;
        j = h;
    }
    for (h = 0; h < i; h++)
        nb[h] = S[h];
    for (h = j + 1; h < N_OBJ; h++)
        nb[h] = S[h];
    while (i <= j) {
        nb[i] = S[j], nb[j] = S[i];
        i++; j--;
    }
}
 
void copy(int * new_state, int * state) {
    int i;
    for (i = 0; i < N_OBJ; i++)
        state[i] = new_state[i];
}
 
int main(int argc, char * argv[]) {
    int i;
    int state[N_OBJ];
    int best_state[N_OBJ];
    double eo, en, ebest = 1e10;
    for (i = 0; i < N_OBJ; i++) 
        state[i] = i + 1;
    eo = E(state);
    srand((unsigned)time(0));
    while (T > 0.1) {
        for (i = 0; i < 50000; i++) {
            neighbour(state);
            en = E(nb);
            if (accept(eo, en, T)) {
                eo = en;
                copy(nb, state);
                if (eo < ebest) {
                    copy(state, best_state);
                    ebest = eo;
                }
            }
        }
        T *= rad;
        printf("%lf\t%lf\n", T, eo);
    }
    printf("%lf\n", ebest / 24000 + 5);
    PRINT(best_state);
    return 0;
}

域名转移

我的域名管理正在从yahoo转向godaddy,如果中途有段时间上不了是正常现象。感谢关注我的博客。


突然很有感觉

不知道为什么,一下子充满了对过去的留恋。

有人说,当一个人习惯去回忆的时候说明他老了,我老了?感觉本来如此熟悉的土地,变得越来越陌生,看着旁边的小学依稀看到了我每天早早起床背着书包上学去的场景,看到了放学后和小伙伴们挤在校门口的小店里玩很幼稚的东西。现在,这所小学在扩大,新的楼房拔地而起,原来的操场已经消失的无影无踪,只有圆形的体育馆和老式的教学楼承载着我数不清的回忆,只是不知道原来熟识的面孔是否还在里面。

一下子感觉寂寞了许多。或许记忆中无比喧闹的场景和现在形成了鲜明的对比,我还记得在小学毕业的那一天,老师对我们说,大家以后还是会见到的,又不是一下就天南地北了。可是,这个“以后”意味着一段很短的时间吧,现在真的是天南地北,或许在不久的将来,就是在地球的两端了。写到这里,想了一下,似乎已经没有小学同学还保持着热切的联系了,每个人都是生命的过客,曾经灿烂的像流星,但现在早已陌路。

我尝试着留住记忆中的一些东西,通过那和我一样穿越着时间过来的“旧”东西。旧的东西往往会让旧的事情和旧的人产生联系,给人一个寄托的载体。记得曾经到二中去的时候,很多曾经很熟悉的老师也已经不在了,虽然人来人往,但是给我的感觉总是那么不熟悉,操场虽然还是那片操场,但是在上面迸发着活力的早已换了一届又一届,篮网也肯定换过很多次了,虽然我不知道。

Life should move on, and so do I.


侄女画画展

昨天我去大姑姑家吃饭,偶遇小侄女,遂有此篇。


在家的几日

首先,回来两天竟然感冒了,鼻涕不断,我都怀疑身体要脱水了…

今天约了汪猪去打球,汪猪虽然工作了,累了,瘦了,但还是精力十足,只不过我还没有脱离感冒阴影的笼罩,浑身没有力气,随便投了几个,顿然发现以下几点:

  • 身子骨硬了,感觉蹦蹦跳跳都不灵活了。
  • 投篮不准了,手腕也不柔和了。
  • 运球不娴熟了。

先总结到这里,以后有想法再写。


侄女

今天去看望爷爷奶奶,遇到侄女,发现她已经开始掉牙齿了。时间穿梭之快,就在不经意间。纪念侄女的慢慢长大和逝去的如梭光阴。


bottle

这两天看了看bottle,一个很小巧的玩意。虽然是个小东西,可是能够进行完美的web开发。所谓完美,只是顺利的意思,当然,如果你需要ORM,需要其他模板引擎当然可以自己获取,bottle只是关注web。

an example

from bottle import *
 
@route('/')
def index():
    return 'Hello, world!'
 
run()

如此简单的几行就组成了一个web应用!访问http://127.0.0.1:8080/看看结果吧!代码就不解释了,写过web应用的都应该可以看得懂!

最后在列出几个模板引擎吧。

  • Mako
    声称渲染的速度很快。可以尝试一下,不过我对其中带那么多python语法不以为然。渲染只需要包含最简单的if, else, for等基本逻辑就可以了,我们不应该在View(MVC应该知道吧)层进行大幅度的业务逻辑。
  • Cheetah
    这引擎的官网做的真不怎么样,这对推销自家的模板引擎不是一个好方法噢(^_^)。没有用过,据说效率也很高,跟Mako有一拼。

  • Archive

    September 2010
    S M T W T F S
    « Aug    
     1234
    567891011
    12131415161718
    19202122232425
    2627282930  
  • Tags

  • Copyright © 1996-2010 阳阳的漂泊. All rights reserved.
    iDream theme by Templates Next | Powered by WordPress