记下最近二三事
从后往前说吧。
刚刚发现.subversion/config中~是不能被解析成/home/xxx/的,原来配置svn好使总是有警告说xxx文件找不到,没在意;现在才知道确实是找不到啊,原来能连接是因为我的private key都放在.ssh/下,ssh自己会搜索这个路径下的key,所以说呢,我又犯了一次2。
也是刚才,发现我的adsense中Page impressions总共才4000多,收入$2.5…曾几何时我还梦想着收回成本呢。
再之前的这两天,断断续续的改程序,跑程序,体会就是无论多么小的系统,设计都是很重要的;
我的程序功能很简单,弄一堆候选词,抓网页,看这些词是不是在网络词典里出现;
最开始设计成了碎文件的存储,总是担心要是文件系统的node用光了怎么办,没实际算过。。。所以又改成数据库方式存储,这么干缺点是太慢了,数据规模变大了,数据库存取很慢;最后又改成了碎文件存储。。。而且我还要寄希望于这些个“词典”不要“屏蔽”我,毕竟慢慢的用代理偷偷摸摸抓也是抓,明目张胆赤裸裸的疯狂抓也是抓。
另外一点,我的感悟就是代码与数据的分离也是很重要的;
版本控制也是重要的,一个好的习惯是:checkout -> commit…checkout -> commit. 而我的做法是copy -> edit…copy -> edit。
最往前几天,帮助锋哥写了些hash函数,测试这些函数的优劣。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | u_int elfHash(const char *str) { u_int code = 0; u_int ans = 0; while(*str) { code = (code<<4) + (*str++); if((ans = (code & 0xf0000000)) != 0) { code ^= (ans >> 24); code ^= ans; } } return code & 0x7fffffff; } u_int nrHash(const char *str) { u_int code = 0; while(*str) { code *= 16777619; code ^= (u_int) *(unsigned char*)str; ++str; } return code; } u_int stlHash(const char *str) { /* inline size_t __stl_hash_string(const char* __s) { unsigned long __h = 0; for ( ; *__s; ++__s) __h = 5*__h + *__s; return size_t(__h); } */ return __stl_hash_string(str); } |
实际上这些hash函数都差不多,其思想也是相似的;我的实践经验发现:模数底M对结果影响很大,M取得很大与很小hash效果都不好;最后比较好的结果是M取8-10w之间的素数。我猜测sgi的hash_set有可能也是这么干的。
再往前几天,hbx同学某天晚上说我怎么变高了,我倒是希望变高,不过这是不可能的,我都什么岁数的人了,要是还能长,那么500w也离我不远了。
再之前几天,我实在想不起来具体都干什么了,就记着写程序了。有一天随便看了看一本什么数据存储查询的书,书上介绍了huffman编码压缩,算术编码压缩方法;就想起来曾经在acmClub时候,最开始就是学的这个,呵呵,真怀念啊。然后,花了点时间写了个压缩解压缩的程序,虽然压缩比很差,但是思路还是很清晰的;btw: wordpress添加downloads真麻烦,而且中文编码也有问题。
回想这些天,除了写写代码,配置这个那个,还真没干什么了。也许,所谓的什么个性化推荐才是我们应该走的道路,毕竟我们还是所谓的研究生。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | #include <iostream> #include <cstdio> #include <cstdlib> #include <map> #include <queue> #include <cassert> #include <cstring> using namespace std; typedef unsigned int u_int; struct Node { char key; u_int freq; Node *self; Node *left, *right; Node() { left = right = 0; key = 0; self = this;} bool operator<(const Node & _n) const { return freq > _n.freq ? true : freq < _n.freq ? false : key < _n.key ? true : false; } }; const u_int BLOCK_SIZE = 1024; class Huffman { public: Node *buildTree() { priority_queue<Node> Q; u_int num = 0; for(u_int i = 0; i < 256; ++i) { if(counter[i] == 0) continue; Node *ans = new Node(); ans->key = i, ans->freq = counter[i], ans->self = ans; //fprintf(stderr, "%d - %d\n", ans->key, ans->freq); Q.push(*ans); ++num; } for(int i = 1; i < num; ++i) { assert(!Q.empty()); Node first = Q.top(); Q.pop(); assert(!Q.empty()); Node second = Q.top(); Q.pop(); //fprintf(stderr, "(%d - %d)\n", first.freq, second.freq); Node *ans = new Node(); ans->left = first.self, ans->right = second.self; ans->freq = first.freq + second.freq; Q.push(*ans); } assert(!Q.empty()); return Q.top().self; } void trace(char *_code, u_int depth, const Node * _node) { if(_node->left == NULL && _node->right == NULL) { fprintf(stderr, "key: %d\tdepth: %d\tcode: ", _node->key, depth); for(int i = 0; i < depth; i++) fprintf(stderr, "%d", *(_code - depth + i)); fprintf(stderr, "\n"); return; } if(_node->left) { //fprintf(stderr, "("); *_code = 0; trace(_code+1, depth + 1, _node->left); *_code = 2; } if(_node->right) { *_code = 1; trace(_code+1, depth+1, _node->right); *_code = 2; //fprintf(stderr, ")"); } } void readFile(const char *file) { FILE *fin = fopen(file, "rb"); if(fin== NULL) { fprintf(stderr, "fopen fail.\n"); exit(-1); } char str[BLOCK_SIZE]; u_int n; memset(counter, 0, sizeof(counter)); while((n = fread(str, sizeof(char), BLOCK_SIZE, fin)) > 0) for(u_int i = 0; i < n; ++i) counter[(int)str[i]]++; //for(int i = 0; i < 256; ++i) fprintf(stderr, "counter[%d]: %d\n", i, counter[i]); fclose(fin); } void compress(const char *file, const char *outFile) { readFile(file); Node *root = buildTree(); char _code[256]; //trace(_code, 0, root); encode(_code, 0, root); writeFile(file, outFile); } void i2ch(u_int n, char *str) { for(int i = 0; i < 4; ++i) { *(str+i) = 0xff & (n >> ((3-i)*8)); } } void writeFile(const char *file, const char *com) { FILE *fin = fopen(file, "rb"); FILE *fout = fopen(com, "wb"); if(fin== NULL || fout == NULL) { fprintf(stderr, "fopen fail.\n"); exit(-1); } u_int num = 0; for(int i = 0; i < 256; ++i) if(counter[i] > 0) num++; char ntr[8] = {0}; i2ch(num, ntr); //fprintf(stderr, "num : %d-%d-%d-%d - %u \n", ntr[0], ntr[1], ntr[2], ntr[3], num); if(fwrite(ntr, sizeof(char), 4, fout) < 4) { fprintf(stderr, "fwrite 4 error.\n"); exit(-1); } for(int i = 0; i < 256; ++i) { if(counter[i] == 0) continue; char ttr[8] = {0}; ttr[0] = i; i2ch(counter[i], ttr+1); if(fwrite(ttr, sizeof(char), 5, fout) < 5) { fprintf(stderr, "fwrite 5 error.\n"); exit(-1); } } char str[BLOCK_SIZE]; char ctr[BLOCK_SIZE]; memset(ctr, 0, sizeof(ctr)); u_int n, ex = 0; int ix = 7; while((n = fread(str, sizeof(char), BLOCK_SIZE, fin)) > 0) { for(u_int i = 0; i < n; ++i) { for(int j = 0; j < mask[str[i]]; ++j) { if(code[str[i]][j] == 1) ctr[ex] = ctr[ex] | (1<<ix); ix--; if(ix < 0) ex++, ix = 7; if(ex == BLOCK_SIZE) { //写入文件 if(fwrite(ctr, sizeof(char), ex, fout) < ex) { fprintf(stderr, "fwrite error.\n"); exit(-1); } memset(ctr, 0, sizeof(ctr)); ex = 0, ix = 7; } } } } //fprintf(stderr, "write in to compress ex %d\n", ex); if(fwrite(ctr, sizeof(char), ex, fout) < ex) { fprintf(stderr, "fwrite error.\n"); exit(-1); } fclose(fin); fclose(fout); } void binaryPrint(char n) { for(int i = 7; i >= 0; --i) fprintf(stderr, "%d", ((1<<i) & (0x000000ff & n)) ? 1 : 0); } //_code : 0, _mask : 0 void encode(char *_code, char _mask, const Node *node) { if(node->left == NULL && node->right == NULL) { for(int i = 0; i < _mask; ++i) { code[node->key][i] = *(_code-_mask+i); } mask[node->key] = _mask; return ; } if(node->left) { *_code = 0; encode(_code+1, _mask+1, node->left); } if(node->right) { *_code = 1; encode(_code+1, _mask+1, node->right); } } void decompress(const char *file, const char *outFile) { FILE *fin = fopen(file, "rb"); FILE *fout = fopen(outFile, "wb"); if(fin == NULL || fout == NULL) { fprintf(stderr, "fopen fail.\n"); exit(-1); } char str[BLOCK_SIZE] = {0}; memset(counter, 0, sizeof(counter)); if(fread(str, sizeof(char), 4, fin) < 4) { fprintf(stderr, "fread first 4 char fail.\n"); exit(-1); } u_int n = ch2i(str); //fprintf(stderr, "n : %d-%d-%d-%d - %u \n", str[0], str[1], str[2], str[3], n); for(u_int i = 0; i < n; ++i) { if(fread(str, sizeof(char), 5, fin) < 5) { fprintf(stderr, "fread 5-group fail.\n"); exit(-1); } counter[(int)str[0]] = ch2i(str+1); } Node *root = buildTree(); Node *ans = root; char _code[256]; //trace(_code, 0, ans); u_int ix = 0; char ctr[BLOCK_SIZE]; while((n = fread(str, sizeof(char), BLOCK_SIZE, fin)) > 0) { for(u_int i = 0; i < n; ++i) { for(int j = 7; j >= 0; --j) { //fprintf(stderr, "%d",((1<<j) & (0x000000ff & str[i])) ? 1 : 0); if(((1<<j) & (0x000000ff & str[i]))) { assert(ans->right != NULL); ans = ans->right; } else { assert(ans->left != NULL); ans = ans->left; } if(ans->left == NULL && ans->right == NULL) { //fprintf(stderr, "\n"); ctr[ix++] = ans->key; if(ix == BLOCK_SIZE) { //写入文件 fwrite(ctr, sizeof(char), ix, fout); ix = 0; } ans = root; } } } } fwrite(ctr, sizeof(char), ix, fout); fclose(fin); fclose(fout); } u_int ch2i(const char *str) { u_int res = 0; for(int i = 0; i < 4; ++i) res = (res<<8) | (0x000000ff & str[i]); return res; } private: char mask[256]; char code[256][256]; u_int counter[256]; }; int main(int argc, char **argv) { Huffman huff; // huffman -c compress compressed // huffman -d decompress decompressed if(argc < 4) { fprintf(stderr, "usage: huffman -cd file.in file.out\n"); exit(-1); } if(strcmp(argv[1], "-c") == 0) { huff.compress(argv[2], argv[3]); } else if(strcmp(argv[1], "-d") == 0) { huff.decompress(argv[2], argv[3]); } else { fprintf(stderr, "usage: option -c or -d.\n"); exit(-1); } return 0; } |