仰慕已久,发现网上有这本书的PDF,下载了一份,就当练习英语阅读了…
2012-5-10
刚刚看完第一章Intro.大概介绍了游戏团队的构成,游戏类型,游戏引擎的构成.
2012-5-11
第二章 Tools of Trade. Version Control推荐SVN.IDE简单介绍了VS的配置和调试工具.两种代码分析方式,统计分析,精确分析.内存泄露检测.
仰慕已久,发现网上有这本书的PDF,下载了一份,就当练习英语阅读了…
2012-5-10
刚刚看完第一章Intro.大概介绍了游戏团队的构成,游戏类型,游戏引擎的构成.
2012-5-11
第二章 Tools of Trade. Version Control推荐SVN.IDE简单介绍了VS的配置和调试工具.两种代码分析方式,统计分析,精确分析.内存泄露检测.
作为灰常有历史的两个函数式语言,LISP和ML分别有一本神教材: 计算机程序的构造和解释 和 ML程序设计教程.
嗯,基于个人的看法,应该先学LISP再学ML.确切的说,是这两本教材的顺序.
LISP是一个非常优美的编程语言. 这种优美源于,LISP在语法上彻底贯彻了”函数式”,但他并不是纯粹的函数式语言,同样ML也不是.
先说明一下什么是函数式语言.
在繁杂的程序语言中,我们可以大体分为两类:命令式,和函数式.但大多数函数语言都会支持一些命令式的特点.比如赋值语言,纯正的函数式语言是没有赋值语句的.
关于命令式语言,C就是一个典型的代表.命令式在本质上来说,更贴近机器运行原理.运行环境被认为是一个状态机,语言由一条条命令构成,命令的本质就是状态转移.
从命令式语言的本质出发,我们可以得到一种关于程序设计的理念.即一切程序皆有限状态机,一切操作皆状态转移.我们可以枚举合法的操作序列,来确定程序状态个数…详情参见IBM的净室工程,以及IBM编写的卫星程序就是这么干的…
下面说一下函数式语言,纯函数语言还是有的,叫Haskell,但偶没学过,从语法上来看,和ML有些相似.
函数式语言和命令式语言最表面的区别就是没有赋值语句.如果命令式语言没有赋值语句,就意味着无法改变状态.更抽象的讲,就是没有”变量”,只有”定义”.
其次就是”高阶函数”这个概念,按照字面的意思就是操作函数的函数,成为高阶函数.即以函数为参数,或者返回一个函数.当然,C语言可以传入函数指针,或者返回函数指针.但是函数式语言中的函数,确切的说是lambda函数,通常称为匿名函数(其实还不如叫lambda…)
lambda的取自于”lambda calculus”,lambda演算,这也是函数式语言的数学基础.如果介绍lambda演算的话,那会是一个很漫长的话题,所以详情参见wiki~.
简单来说,lambda演算的语法只有3条,exp = 标识符 or 函数定义 or 函数调用. 即 <exp> = <id> | (function <id> <exp>) | (<exp> <exp>) 这里面的函数永远只有一个参数,而且参数和返回值都是exp,要么是标识符,要么是函数.这一点会让人感觉匪夷所思,基本类型呢?
从纯数学的角度来讲的话,lambda演算中是没有类型的,我们可以通过某种构造方法,使用函数来表现出我们需要的类型,以及所需要的运算,比如自然数,加减乘除…同参见wiki~
再一点,lambda演算要求一个函数必须定义之后才能使用,也就是意味着并不直接支持递归,那么如何编写递归函数,这里有一个很有名的构造方法,叫Y combinator,这玩意居然是MIT CS系的系徽…
以上lambda内容全部跑题,哈哈~简单说完命令式和函数式之后…再从技术角度来说一下LISP~
1. 垃圾回收技术,LISP发明了GC技术,直到今日.NET和JAVA的GC也不过是改进而已,整体思想依然是递归扫描所有从root能到达的节点,复制到另一个区域.计数器法有可能造成内存泄漏,像弱引用之类的解决方法,只能是越看越蛋疼的技术…不过垃圾回收无疑造成运行中会忽然KB的现象,JAVA和C#中均可体现.现在的改善方法是将对象分代…依然抽搐的方法…
2. 函数是第一类值,以及闭包的概念.在命令式语言中,函数的调用环境简单的分为全局变量,和局部变量.但是LISP并非如此,他将函数的调用环境理解成一种传递闭包的关系,即环境2->环境1->root环境…
3. 无循环结构,用尾递归代替,这一点也是通用的,编译器可以很容易判断出尾递归,并在递归时保持栈不增长.
4. 表结构,LISP里面没有数组,只有链表.我们通过惰性表,可以实现无穷表.比如一张自然数的表…没有数组是个很蛋疼的事情,砖家们建议实现成树结构,来加快访问速度…
P.S.
很久以前的草稿,没写完,忘记后面要写什么了…发出来好了…
貌似后面还想写点按值传递,按需传递,惰性传递的比较,静态类型推断…
恩,实现了一个内存泄漏C++版本的LISP解释器,想要解决内存问题,只有完整的实现一个GC,或者使用有GC的语言,例如JAVA或C#.
不过对这个兴趣不大,目前对类型比较感兴趣.考虑类型的本质是什么,怎么动态加载自定义类型和内置类型.
嗯嗯,萌生了一个很简单的想法,PKU上你没有过的题目里,哪些题目过的人最多?可以依此来慢慢切水题…
本来是想架设在Google App Engine上面的,但是很不幸PKU是局域网网站…而GAE又在墙外…嗯…居然首先想到了牛郎织女…
用Python写了一段简单的扒网页程序,恩…正好用了两种扒数据的方法,一个是HTMLParser,这个类似JAVA里的SAX.另一个就是烂大街的正则式.
为了方便显示,只显示了前20个,可以自己随便调了,输出到文件里,解决一切~
嗯,代码很挫,第一次用Python做点实事,for循环还没熟练…恩,可以改成只读一次ProblemSet,然后可以反复查询.
import urllib
import HTMLParser
import re
import string
table = {}
class MyParser(HTMLParser.HTMLParser):
pid = None
ac = None
submit = None
def __init__(self):
HTMLParser.HTMLParser.__init__(self)
def handle_starttag(self, tag, attrs):
if tag == 'a':
for name,value in attrs:
if name == 'href':
if value.startswith('problemstatus?problem_id=') :
self.pid = value[len(value) - 4 :]
def handle_data(self, data):
if data == '/' : return
if self.pid == None : return
if self.ac == None :
self.ac = data
return
self.submit = data
table[int(self.pid)] = int(self.ac)
#print 'id ' + self.pid + ' ac ' + self.ac + ' submit ' + self.submit
self.pid = None
self.ac = None
self.submit = None
name = raw_input("Please input your id:\n")
for i in range(1, 32) :
print 'Loading ProblemSet', i
html = urllib.urlopen('http://poj.org/problemlist?volume=' + str(i)).read()
my = MyParser()
my.feed(html)
#print table
print 'Loading User\'s Infomation'
html = urllib.urlopen('http://poj.org/userstatus?user_id=' + name).read()
prbReg = re.compile(r'p\([0-9]*\)', re.I | re.M)
match = prbReg.search(html)
for m in prbReg.finditer(html):
s = m.group()[2:6]
s = int(s)
if s in table : del table[int(s)]
#print s[2:6]
print 'Sorting...'
ret = sorted(table.items(), key=lambda d: d[1])
n = len(ret) - 1
i = 0
while n > 0 :
if i > 20 : break
print ret[n]
n -= 1
i += 1
前一段时间跟朋友提到一个彩票的故事,顺手发到blog上来.
我们都知道信息具有价值,但信息如何表现出他自身的价值呢,说一个我很喜欢的统计学的小故事.
日本有种彩票叫Numbers3,规则是从0-999中选一个数字,每张彩票200日元,每期抽1个数字作为中奖号码,所有的彩票钱的45%平分给中奖者.
我们可以清楚的知道,每个号码中奖的概率是0.1%,顺道吐槽一下那些彩票预测…然后…如果我们得到了这一期彩票每个数字的下注人数…那么会出现什么奇妙的事情呢…
当 总人数 * 200 * 0.45 / 某数字下注人数 * 0.1% – 200 > 0 的时候,我们下注就是必胜的.简单计算一下可知,选择那些下注率小于0.045%的号码,从而使自己获利的期望高于本钱.
恩,很简单清晰的一个例子,只有你知道下注的统计信息,不需要作弊,即可发家致富~信息就是金钱~^_^
经常听闻这么一种故事,一个人被诊断得了不治之症,然后万念俱灰,豁然开朗,跑到深山野岭,或者全世界周游一圈,回来之后发现不治之症痊愈了.
嗯嗯,听着非常励志的故事,不过我们计算一下其中被误诊的概率…
假设诊断仪器有2%的错误率,而病症则是1%的患病率,就是平均100人有1人患病.
我们通常会认为如果被判断生病,则98%的可能是真的病了…但是我们换一个角度来看这个事情…
假设医院一个月有1W位人做诊断,其中9900名无病,100名有病.则出现以下4种情况
A 无病,被诊断无病 9900 * 0.98 = 9702
B 无病,被诊断有病 9900 * 0.02 = 198
C 有病,被诊断无病 100 * 0.02 = 2
D 有病,被诊断有病 100 * 0.98 = 98
那么一个月内将有|B+D|=296位被诊断为有病…以及|D|=98位真正有病…
所以真正的误诊率是66%,真正患病的概率仅为33%…
有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子.最后把石子全部取完者为胜者.现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者.
这是一道很经典的博弈题目,PKU1067,过这道题的人数很多,不过相信大多数都是直接搜到公式AC.我碰巧看到了此题的证明过程,就顺手来blog划拉两笔.
第一个是终极公式 An = [(1 + sqrt(5)) / 2 * n], Bn = [(3 + sqrt(5)) / 2 * n]; 代码是极其简短的…
#include <stdio.h>
#include <math.h>
int ak, bk;
double x;
int main() {
x = (1 + sqrt(5.0)) / 2;
while(scanf("%d %d", &ak, &bk) != EOF) {
if(ak > bk) {
ak ^= bk;
bk ^= ak;
ak ^= bk;
}
int k = bk - ak;
if(ak == (int)(k * x)) printf("0\n");
else printf("1\n");
}
}
对必输态的结论我就直接使用了,不再重复证明,不明白可以自己证明,或看discuss~
必输态的结论:我们知道所有的必输的数对(a,b),假定a < b,具有两个性质,1.任何一个自然数在数对中都仅出现一次,任意一个b-a的差值也只出现一次,同时知道第n个点对的差值是n.
(0,0) (1,2) (3,5) (4,7) (6,10) (8,13)... 差值是0,1,2,3,4,5...
首先我们需要证明这么一个辅助定理:
对于任意两个正无理数r,t
如果 1 / r + 1 / t = 1
那么 An = [rn], Bn = [tn],可以不重复的覆盖所有自然数.([]为下取正的意思,x-1 < [x] < x)
我们来考察任意一个正数N,假设存在[rx] = N,并且存在[ty] = N,那么x = [N/r], y = [N/t].
(N/r-1)+(N/t-1) < [N/r]+[N/t] < N/r+N/t,
因为1/r+1/t=1, 所以得到N-2 < x+y < N,所以可知x+y只可能等于N-1 (这也可以说明An,Bn覆盖了N-1个小于N的数).
又因为[rx] = N, [ty] = N 所以N < (rx && ty) < N+1.
可知 N/x < r < (N+1)/x 和 N/y < t < (N+1)/t
继续 x/(N+1) < 1/r < x/N 和 y/(N+1) < 1/t < y/N
x/(N+1) + y/(N+1) < 1/r + 1/t < x/N + y/N
因为x + y = N - 1所以 (N-1)/(N+1) < 1/r + 1/t < (N-1)/N 和已知条件矛盾.
所以不存在一个数可同时使[rx] = N并且[ty] = N.
以上过程证明An,Bn不重复覆盖了所有自然数.
现在我们假设点对为 An = [rn], Bn = [tn], 1/r + 1/t = 1 并且 Bn - An = n
n = n + [rn] - [rn] = [n + rn] - [rn] = [(1+r)n] - [rn]
很容易知道如果(1+r) != t,则肯定存在一个足够大的n使[(1+r)n] 和 [tn] 相差1 那么则与[(1+r)n] - [rn] = n, [tn] - [rn] = n 矛盾
所以 1/r + 1/(r+1) = 1 解得 r = (1 + sqrt(5)) / 2, t = (3 + sqrt(5)) / 2;
当然,如果不知道辅助定理,以上证明根本不可能YY出来...下面隆重介绍一个极度YY的找规律方法,和另一种解法的证明.
按照正常的YY找规律做题方式,我们先人肉几组数据
1 (1,2) 1+2=3
2 (3,5) 3+5=8
3 (4,7) 4+7=11
4 (6,10) 6+10=16
5 (8,13) 8+13=21
6 (9,15) 9+15=24
7 (11,18) 11+18=29
8 (12,20) 12+20=32
9 (14,23) 14+23=37
10 (16,26) 16+26=42
11 (17,28) 17+28=45
12 (19,31) 19+31=50
13 (21,34) 21+34=55
14 (22,36) 22+36=58
15 (24,39) 24+39=63
16 (25,41) 25+41=66
17 (27,44) 27+44=71
18 (29,47) 29+47=76
先来说一组最明显的线索(1,2)(3,5)(8,13)(21,34)...居然有一个fib数列!再仔细观察发现(4,7)(11,18)(29,47)... (6,10)(16,26)...
以此我们将数对化为一个数对矩阵
(1,2)(3,5)(8,13)(21,34)...
(4,7)(11,18)(29,47)...
(6,10)(16,26)...
(9,15)...
第一条规律,我们可以发现任何一组都满足fib的特征,如果存在(a,b)项那么在第b项必然是(a+b,a+2b).
这条规律还不能让我们把全部序列构造出来,因为每一组都需要第一个数对(1,2),(4,7),(6,10),(9,15),(12,20)...我们姑且称这一列为"头数对",对应与头数对中的a,即1,4,6,9,12...我们称之为"头数".
假设将头数拿出来构成一个数列Sn = 1,4,6,9,12,14,17,19,22,25,27,30,33,35,38...这组数有什么特征?
4 = 3 + 1
6 = 5 + 1
9 = 8 + 1, 12 = 8 + 4
14 = 13 + 1, 17 = 13 + 4, 19 = 13 + 6
22 = 21 + 1, 25 = 21 + 4, 27 = 21 + 6, 30 = 21 + 9, 33 = 21 + 12
35 = 34 + 1, 38 = 34 + 4...
呵呵,看出点什么规律没?Sn由fib(n) + 一个小于fib(n-1)的Sn项来构成的.
知道了头数对的a,那么我们还需要知道数对位置k从而算出a+k=b
那么k是具有什么规律呢?我们考察所有头数对的位置得到1,3,4,6,8,9,11,12...这个数列有什么规律呢...将人肉的数据竖着看一下...是不是发现了它的存在?原来头数对的位置隐藏在每一项数对(a,b)的a里面...
但是这两条坑爹的规律仅仅可以用于构造,但并不能得到O(1)的计算方法,所以我们需要从中发掘出更坑爹的东西来...
大家知道计算机是二进制...下面介绍一种坑爹进制,叫斐波纳妾进制~这个进制每一位是 1 2 3 5 8 13 21... 这个进制是很坑爹的,因为不可能存在相邻的两个1,以及加减法也很坑爹,想要深入了解的同学,可以自行研究其坑爹之处...
那么我们将以上规律化成斐波纳妾进制...神奇的事情出现了!
(1,2)(3,5)(8,13)...变为了(1,10)(100,1000)(10000,100000)...
(4,7)(11,18)(29,47)...变为了(101,1010)(10100,101000)(1010000,10100000)
(6,10)(16,26)...变为了(1001,10010)(100100,1001000)
每一行写成正则式,变成了^10*,^1010*,^10010*,...
这规律太赤裸裸了...用这一条规律就可以O(1)秒杀题目了...即对于每一对(a,b),a以偶数个0结尾,b为a左移一位.
对于任意一个数x,我们判断它最后0的个数,如果是偶数个,则y=x左移一位,构成(x,y)数对.如果是奇数个,则y=x右移一位,构成(y,x)数对.
对于找规律解题到这里可以说已经OK了,但怎么证明正确呢,还看下面更神奇的规律及简要证明...
我们考察头数的构成的Sn数列,刚才对于Sn的规律对应到斐波纳妾进制中意味着什么呢?
1,4,6,9,12,14,17... 变成了 1,101,1001,10001,10101,100001,100101... 这些数恰恰是斐波纳妾进制0位为1的数.
我们从而得知,矩阵第一列数字都是为以1结束的斐波纳妾进制数(=.= 好长的名字... ),此后都是无限左移.这一点可以保证,每个自然数都有且仅被包含一次.
那么还有第二点需要证明,即没有两个数对,他们a,b的差值d是相同的.我们通过推导以下结论,来证明这一点.
即对任意差值d,都有唯一一个数对和其对应.
首先对于每一个数对(a,b)我们可知每一个b都是其后续的差值.我们仅仅需要证明每一个a对应一个不同的数对即可.(每一项a, 即1,100,10000,...,101,10100....)
但每一个b都和其后续对应,那么只剩下头数对没有对应的d.所以我们要证明的是每一个a都可以对应到一个头数对的差值.
这时候我们需要先仔细研究一下(a,b)和差值d的关系...很容易知道对于任何非头数对,其中b是a的左移,d是a的右移.
而对于1,101,1001,10001是没法右移的,但很容易得知,这时候d的计算方法是(a - 1)右移 + 1 = d.则a = (d - 1)左移 + 1
再往下出几个数字来证明,可推广至全部情形.
对于1,101,1001,很容易知道推导得对应的a也是头数,例如(101-1)<<1 + 1 = 1001,...
对于每一行我们假设头数是u,其对应的数v,u->v,即1->1, 101->1001, 1001->10001.
先科普一下在斐波纳妾进制中的减法… 10 – 1 = 1, 100 – 1 = 10, 1000 – 1 = 101, 10000 – 1 = 1010… 坑爹…
即 (1偶数个0) – 1 = 1010…10, (1奇数个0) – 1 = 101…01
而我们剩下的a恰好全部是最后带偶数0的…假设a为一个u前缀,带着偶数个0, u00..00.
那么 (u00..00 – 1)<<1 + 1 = (v0...10)<<1 + 1 = (v0..100) + 1 = v0..101,同样为尾部为1的数,满足对应到头数对中.
好了,坑爹的证明完毕,最后我们还得知了其中的对应关系, ^1(00)*->^1(01)*, ^101(00)*->^(1001)(01)*, ^1001(00)*->^(10001)(01)*…
半文字半正则描述一下, 前缀1(00)* -> 前缀01(01)*~ 至此全部完毕,附带一份简易代码.
#include <stdio.h>
typedef __int64 ll;
ll fib[100] = {1, 1};
int i2f(int x, int s[]) {
int w = 1;
while(fib[w] <= x) ++w;
--w;
for(int i = w; i > 0; --i) {
if(x >= fib[i]) {
s[i - 1] = 1;
x -= fib[i];
} else {
s[i - 1] = 0;
}
}
return w;
}
int f2i(int w, int s[]) {
int ret = 0;
for(int i = 0; i < w; ++i) if(s[i]) ret += fib[i + 1];
return ret;
}
int solve(int x) {
int w, s[100];
w = i2f(x, s + 1);
s[0] = 0;
int n = 1;
while(!s[n]) ++n;
if(n & 1) {
return f2i(w + 1, s);
} else {
return f2i(w - 1, s + 2);
}
}
void print(int w, int s[]) {
for(int i = w - 1; i >=0; --i) printf("%d",s[i]);
}
int main() {
for(int i = 2; i < 100; ++i) {
fib[i] = fib[i - 1] + fib[i - 2];
}
int a, b;
while(scanf("%d %d", &a, &b) != EOF) {
if(solve(a) == b) puts("0");
else puts("1");
}
return 0;
}
http://livearchive.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3738
这里有道多个威佐夫博奕合在一起的题目,直接暴力打表SG找规律即可,刷了个第一名,0.024s~
VIM和EMACS选一个,后者有LISP,刚开始看自带的Tutorial。嗯。。。其实对于小红点用户。。。手是不用离开键盘的。。。
C-v 移动到下一屏 M-v 移动到上一屏 C-l 将指针设为屏幕最上or中间or最下 C-f 向前移动一个字符 C-b 向后移动一个字符 M-f 向前移动一个单词 M-b 向后移动一个单词 C-n 移动到下一行 C-p 移动到上一行 C-a 移动到这一行的开始 C-e 移动到这一行的结束 M-a 移动到这一段的开始 M-e 移动到这一段的结束 M-< 移动到文章开始 M-> 移动到文字结束 C-u 数字N 命令 将命令重复N次 C-g 中断命令 C-x 1当前窗口全屏 2上下切屏 3左右切屏 C-x u 撤销 C-d 删除光标之后的一个字符 M-d 删除光标之后的一个单词 C-k 删除光标到这一行结束 M-k 删除光标到这一段结束 C-标记 C-w 删除标记的内容
其实想写一篇流与装饰模式的文章,不过没时间写,学弟说起JAVA IO和装饰模式.JAVA的流其实就是按照装饰模式来做的,不过C++并不是,我想大概因为两点原因吧,1.<< >>必须是类的友元函数,2.标准库里的IO流是基于模板技术开发的.
顺便又翻出了当年用JAVA写的一个JAVA IDE… 一个20KB的文件.其实就是一个记事本,支持新建,保持,以及编译和运行.
应该是看完JAVA核心技术第一卷时写的,第二卷没坚持看完,因为觉得未来不太可能用JAVA开发程序.
关于专业方面的书籍,我建议多看一些理论基础,编程思想方面的书,像核心技术这样注重语言细节的书籍大可不必深究.
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;
import javax.swing.filechooser.FileFilter;
public class JavaEditor {
public static void main(String[] args) {
MainFrame f = new MainFrame();
f.setVisible(true);
}
}
class MainFrame extends JFrame implements InternalFrameListener{
public MainFrame() {
Toolkit tk = this.getToolkit();
JFrame.setDefaultLookAndFeelDecorated(false);
this.setTitle("My JAVA Editor");
this.setLocation(tk.getScreenSize().width / 4, tk.getScreenSize().height / 4);
this.setSize(tk.getScreenSize().width / 2, tk.getScreenSize().height / 2);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane = getContentPane();
contentPane.setLayout(new BorderLayout());
actionNew = new NewAction(this);
actionSave = new SaveAction(this);
actionOpen = new OpenAction(this);
actionSaveAs = new SaveasAction(this);
mainMenuBar = new JMenuBar();
JMenu fileMenu = new JMenu("文件");
fileMenu.add(actionNew);
fileMenu.add(actionOpen);
fileMenu.add(actionSave);
fileMenu.add(actionSaveAs);
mainMenuBar.add(fileMenu);
actionCompiler = new CompilerAction(this);
actionRun = new RunAction(this);
JMenu debugMenu = new JMenu("调试");
debugMenu.add(actionCompiler);
debugMenu.add(actionRun);
mainMenuBar.add(debugMenu);
JMenu helpMenu = new JMenu("帮助");
JMenuItem questionItem = new JMenuItem("问题");
questionItem.addActionListener(new
ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "这个程序还有些小问题,其中就是控制台输出不能全部被截获,就是System.out不能用\n若哪位大侠指点小弟一二,不胜感激", "问题", -1);
}
}
);
helpMenu.add(questionItem);
JMenuItem aboutItem = new JMenuItem("About");
aboutItem.addActionListener(new
ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "JAVA Editor Version 0.001\nMade In China\n By 追忆似风", "About", -1);
}
}
);
helpMenu.add(aboutItem);
JMenuItem aboutMeItem = new JMenuItem("About我");
aboutMeItem.addActionListener(new
ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "我是这比较恶的程序的作者\n感谢大家给这个程序一次编译的机会\n欢迎加我Q,81642410", "About我", -1);
}
}
);
helpMenu.add(aboutMeItem);
mainMenuBar.add(helpMenu);
this.setJMenuBar(mainMenuBar);
compilerText = new JTextArea(10,20);
runText = new JTextArea(10,20);
JPanel jp = new JPanel(new GridLayout(1, 2));
JSplitPane split1 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(compilerText), new JScrollPane(runText));
jp.add(split1);
contentPane.add(jp, BorderLayout.SOUTH);
desktop = new JDesktopPane();
contentPane.add(desktop, BorderLayout.CENTER);
/*
btn = new JButton("HAHA");
contentPane.add(btn, BorderLayout.SOUTH);
btn.addActionListener(new
ActionListener() {
public void actionPerformed(ActionEvent e) {
MyInternalFrame intf = new MyInternalFrame("内部" + (xx++));
intf.setSize(150, 150);
intf.setVisible(true);
intf.setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);
intf.setAutoscrolls(true);
jifs.add(intf);
desktop.add(intf);
Iterator iterator = jifs.iterator();
while(iterator.hasNext()) {
JInternalFrame ii = iterator.next();
if( ii.isSelected() ) {
JOptionPane.showMessageDialog(null, "" + ii.getTitle() + " ALL : " + jifs.size());
}
}
}
}
);
*/
}
public void addMyInternalFrame(MyInternalFrame e) {
e.setSize(desktop.getWidth(), desktop.getHeight());
//e.setAutoscrolls(true);
e.addInternalFrameListener(this);
e.setVisible(true);
desktop.add(e);
/*
jifs.add(e);
Iterator iterator = jifs.iterator();
while(iterator.hasNext()) {
JInternalFrame ii = iterator.next();
if( ii.isSelected() ) {
try {
ii.setSelected(false);
} catch (PropertyVetoException e1) {
e1.printStackTrace();
}
}
}
try {
e.setSelected(true);
} catch (PropertyVetoException e1) {
e1.printStackTrace();
}
*/
if(focusAt != null) {
try {
focusAt.setSelected(false);
} catch (PropertyVetoException e1) {
// TODO 自动生成 catch 块
e1.printStackTrace();
}
}
try {
e.setSelected(true);
} catch (PropertyVetoException e1) {
// TODO 自动生成 catch 块
e1.printStackTrace();
}
}
public MyInternalFrame getFocusAt() {
return focusAt;
}
public JTextArea getCompilerText() {
return compilerText;
}
public JTextArea getRunText() {
return runText;
}
public void saveFile() {
actionSave.save();
}
public void internalFrameActivated(InternalFrameEvent e) {
focusAt = (MyInternalFrame)e.getSource();
}
public void internalFrameClosed(InternalFrameEvent e) {
}
public void internalFrameClosing(InternalFrameEvent e) {
int ms = JOptionPane.showOptionDialog(null, "文件是否保存", "正在关闭窗口", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, null, null);
switch(ms) {
case JOptionPane.YES_OPTION :
saveFile();
break;
case JOptionPane.NO_OPTION :
break;
/*
case JOptionPane.CANCEL_OPTION :
e.setSource(null);
*/
}
}
public void internalFrameDeactivated(InternalFrameEvent e) {
}
public void internalFrameDeiconified(InternalFrameEvent e) {
}
public void internalFrameIconified(InternalFrameEvent e) {
}
public void internalFrameOpened(InternalFrameEvent e) {
}
private MyInternalFrame focusAt;
private JMenuBar mainMenuBar;
private JTextArea compilerText;
private JTextArea runText;
private NewAction actionNew;
private SaveAction actionSave;
private OpenAction actionOpen;
private SaveasAction actionSaveAs;
private CompilerAction actionCompiler;
private RunAction actionRun;
private Container contentPane;
//private JButton btn;
private JDesktopPane desktop;
//private LinkedList jifs = new LinkedList();
}
class MyInternalFrame extends JInternalFrame{
public MyInternalFrame(String s) {
super(s, true, true, true, true);
jta = new JTextArea(10, 20);
file = null;
scroll = new JScrollPane(jta);
this.getContentPane().add(scroll);
}
public MyInternalFrame(String s, JTextArea e, File f) {
super(s, true, true, true, true);
jta = e;
file = f;
scroll = new JScrollPane(jta);
this.getContentPane().add(scroll);
/*
JScrollBar scrollBar = scroll.getHorizontalScrollBar();;
scrollBar.setValue(scrollBar.getMaximum());
scrollBar = scroll.getVerticalScrollBar();
System.out.println("" + scrollBar.getValue() + " " + scrollBar.getMaximum());
scrollBar.setValue(scrollBar.getMaximum());
System.out.println("" + scrollBar.getValue() + " " + scrollBar.getMaximum());
scroll.setVerticalScrollBar(scrollBar);
scroll.repaint();
*/
}
public JTextArea getTextArea() {
return jta;
}
public File getFile() {
return file;
}
public void setFile(File f) {
file = f;
this.setTitle(file.getName());
try {
jta.setText(null);
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
byte[] b = new byte[in.available()];
in.read(b, 0, b.length);
jta.append(new String(b, 0, b.length));
in.close();
} catch(IOException ex) {
}
}
private File file;
private JTextArea jta;
private JScrollPane scroll;
}
class NewAction implements Action {
public NewAction(MainFrame p) {
parent = p;
enabled = true;
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
// TODO 自动生成方法存根
}
public Object getValue(String key) {
if(key == Action.NAME) return "New";
return null;
}
public boolean isEnabled() {
// TODO 自动生成方法存根
return enabled;
}
public void putValue(String key, Object value) {
// TODO 自动生成方法存根
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
// TODO 自动生成方法存根
}
public void setEnabled(boolean b) {
enabled = b;
}
public void actionPerformed(ActionEvent e) {
MyInternalFrame intf = new MyInternalFrame("未命名" + (NUMB++));
parent.addMyInternalFrame(intf);
}
private MainFrame parent;
private boolean enabled;
private static int NUMB = 1;
}
class MyFileFilter extends FileFilter {
public boolean accept(File pathname) {
if(pathname.isDirectory()) return true;
return pathname.getName().endsWith(".java");
}
public String getDescription() {
return "*.java";
}
}
class OpenAction implements Action {
public OpenAction(MainFrame p) {
parent = p;
enabled = true;
jfc = new JFileChooser(new File("."));
MyFileFilter myFileViewr = new MyFileFilter ();
jfc.setFileFilter(myFileViewr);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
// TODO 自动生成方法存根
}
public Object getValue(String key) {
if(key == Action.NAME) return "Open";
return null;
}
public boolean isEnabled() {
// TODO 自动生成方法存根
return enabled;
}
public void putValue(String key, Object value) {
// TODO 自动生成方法存根
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
// TODO 自动生成方法存根
}
public void setEnabled(boolean b) {
enabled = b;
}
public void actionPerformed(ActionEvent e) {
open();
}
private void open() {
if(jfc.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) open(jfc.getSelectedFile());
}
private void open(File file) {
try {
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
byte[] b = new byte[in.available()];
in.read(b, 0, b.length);
JTextArea jta = new JTextArea(10,20);
jta.append(new String(b, 0, b.length));
in.close();
MyInternalFrame intf = new MyInternalFrame(file.getName(), jta, file);
parent.addMyInternalFrame(intf);
} catch(IOException ex) {
}
}
private MainFrame parent;
private JFileChooser jfc;
private boolean enabled;
}
class SaveAction implements Action {
public SaveAction(MainFrame p) {
parent = p;
jfc = new JFileChooser(new File("."));
MyFileFilter myFileViewr = new MyFileFilter ();
jfc.setFileFilter(myFileViewr);
enabled = true;
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
}
public Object getValue(String key) {
if(key == Action.NAME) return "Save";
return null;
}
public boolean isEnabled() {
return enabled;
}
public void putValue(String key, Object value) {
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
}
public void setEnabled(boolean b) {
enabled = b;
}
public void actionPerformed(ActionEvent e) {
save();
//JOptionPane.showMessageDialog(null, "保存成功");
}
public void save() {
MyInternalFrame intf = parent.getFocusAt();
if(intf == null) JOptionPane.showMessageDialog(null, "错误");
else {
File file = intf.getFile();
if(file == null) saveAs(intf.getTextArea());
else save(intf.getTextArea(), file);
}
}
private void saveAs(JTextArea jta) {
if(jfc.showSaveDialog(parent) == JFileChooser.APPROVE_OPTION) {
File file = jfc.getSelectedFile();
save(jta, file);
parent.getFocusAt().setFile(file);
}
}
private void save(JTextArea jta,File file) {
try {
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
byte[] b = (jta.getText()).getBytes();
out.write(b);
out.close();
} catch(IOException ex) {
}
}
private MainFrame parent;
private JFileChooser jfc;
private boolean enabled;
}
class SaveasAction implements Action {
public SaveasAction(MainFrame p) {
parent = p;
jfc = new JFileChooser(new File("."));
MyFileFilter myFileViewr = new MyFileFilter ();
jfc.setFileFilter(myFileViewr);
enabled = true;
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
// TODO 自动生成方法存根
}
public Object getValue(String key) {
if(key == Action.NAME) return "SavaAs";
return null;
}
public boolean isEnabled() {
// TODO 自动生成方法存根
return enabled;
}
public void putValue(String key, Object value) {
// TODO 自动生成方法存根
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
// TODO 自动生成方法存根
}
public void setEnabled(boolean b) {
enabled = b;
}
public void actionPerformed(ActionEvent e) {
saveAs();
//JOptionPane.showMessageDialog(null, "保存成功");
}
private void saveAs() {
MyInternalFrame intf = parent.getFocusAt();
if(intf == null) JOptionPane.showMessageDialog(null, "错误");
else if(jfc.showSaveDialog(parent) == JFileChooser.APPROVE_OPTION) {
save(intf.getTextArea(), jfc.getSelectedFile());
}
}
private void save(JTextArea jta,File file) {
try {
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
byte[] b = (jta.getText()).getBytes();
out.write(b);
out.close();
} catch(IOException ex) {
}
}
private MainFrame parent;
private JFileChooser jfc;
private boolean enabled;
}
class CompilerAction implements Action, Runnable {
public CompilerAction(MainFrame p) {
parent = p;
compiler = null;
enabled = true;
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
// TODO 自动生成方法存根
}
public Object getValue(String key) {
if(key == Action.NAME) return "Compiler";
return null;
}
public boolean isEnabled() {
return enabled;
}
public void putValue(String key, Object value) {
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
}
public void setEnabled(boolean b) {
enabled = b;
}
public void actionPerformed(ActionEvent e) {
parent.saveFile();
if( (compiler == null) || (!(compiler.isAlive())) ) {
compiler = new Thread(this);
} else if( (!(compiler.isAlive())) ) {
compiler.interrupt();
compiler = new Thread(this);
}
try {
compiler.start();
} catch(Exception eee) {
System.out.println(eee);
}
}
public void run() {
JTextArea compilerText = parent.getCompilerText();
compilerText.setText(null);
try {
MyInternalFrame intf = parent.getFocusAt();
if(intf == null) {
return;
}
File file = intf.getFile();
String path = file.getPath().trim();
Runtime rt = Runtime.getRuntime();
//InputStream in = rt.exec("javac " + path).getErrorStream();
InputStream in = rt.exec("javac " + file.getName(), null, file.getParentFile()).getErrorStream();
BufferedInputStream bin = new BufferedInputStream(in);
byte[] b = new byte[100];
int n; boolean bn = true;
while((n = bin.read(b, 0, 100)) != -1) {
String s = null;
s = new String(b, 0, n);
parent.getCompilerText().append(s);
if(s != null) bn = false;
}
if(bn) parent.getCompilerText().append("这是个意外,程序居然编译通过了\n");
else parent.getCompilerText().append("我就说吧,这程序能不出错,那真神了\n");
in.close();
}catch(IOException ex) {
System.out.println(ex);
}
}
private Thread compiler;
private MainFrame parent;
private boolean enabled;
}
class RunAction implements Action, Runnable {
public RunAction(MainFrame p) {
parent = p;
running = null;
enabled = true;
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
// TODO 自动生成方法存根
}
public Object getValue(String key) {
if(key == Action.NAME) return "Run";
return null;
}
public boolean isEnabled() {
return enabled;
}
public void putValue(String key, Object value) {
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
}
public void setEnabled(boolean b) {
enabled = b;
}
public void actionPerformed(ActionEvent e) {
if( (running == null) ) {
running = new Thread(this);
} else if( (!(running.isAlive())) ) {
running.interrupt();
running = new Thread(this);
}
try {
running.start();
} catch(Exception eee) {
System.out.println(eee);
}
}
public void run() {
JTextArea runText = parent.getRunText();
runText.setText(null);
try {
MyInternalFrame intf = parent.getFocusAt();
if(intf == null) {
JOptionPane.showMessageDialog(null, "错误");
return;
};
String name = intf.getFile().getName();
int index = name.indexOf('.');
name = name.substring(0, index);
File file = intf.getFile();
//String classpath = (file.getParentFile()).getPath().trim();
Runtime rt = Runtime.getRuntime();
//InputStream in = rt.exec("java -classpath " + classpath + " " + name).getInputStream();
Process pcs = rt.exec("java " + name, null, file.getParentFile());
InputStream in = pcs.getInputStream();
BufferedInputStream bin = new BufferedInputStream(in);
byte[] b = new byte[200]; int n;
InputStream ein = pcs.getErrorStream();
BufferedInputStream ebin = new BufferedInputStream(ein);
byte[] eb = new byte[200]; int en;
runText.append("正在运行...\n");
boolean key1 = ((n = bin.read(b, 0, 200)) == -1);
boolean key2 = ((en = ebin.read(eb, 0, 200)) == -1);
while( !(key1 && key2) ) {
String s = null;
if(!key1) {
s = new String(b, 0, n);
runText.append(s);
}
if(!key2) {
s = new String(eb, 0, en);
runText.append(s);
}
key1 = ((n = bin.read(b, 0, 200)) == -1);
key2 = ((en = ebin.read(eb, 0, 200)) == -1);
}
in.close();
//Thread t = new Thread(new ReadInput(runText, in));
//t.start();
}catch(IOException ex) {
System.out.println(ex);
}
}
private MainFrame parent;
private boolean enabled;
private Thread running;
}
/*
class ReadInput implements Runnable {
public ReadInput(JTextArea jta, InputStream i) {
runText = jta;
in = i;
}
public void run() {
BufferedInputStream bin = new BufferedInputStream(in);
byte[] b = new byte[100]; int n;
while(true) {
try {
if((n = bin.read(b, 0, 100)) != -1) {
String s = null;
s = new String(b, 0, n);
runText.append(s);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private JTextArea runText;
private InputStream in;
}
最近看到朋友分享的大学生自杀的新闻,心有所感,应该做一个自救网站,让轻生的学子们可以以一种匿名的方式,发泄自己和接受心理咨询.
我想,在现实世界,去找心理医生治疗自杀倾向,会背负很大的压力吧,比如同学异样的眼光,或者不知如何寻找心理医生.
而且自杀的冲动,永远是自杀者心底的一个秘密.他需要宣泄,而又无处宣泄.你会担心亲人为你担心,会担心影响到自己的朋友.
我始终坚信,任何人都不想死,我们有求生的本能,尤其对大学生来说,即无衣食之忧,也无不得不死的死局.
有调查显示,大多数人年轻时都曾有过自杀的冲动.况且现在的大学生,大学不适应感,社会和学业的压力,抑或是恋爱的破碎,再加之高层建筑容易诱导跳楼.所以发现自己有自杀的冲动,不必恐慌或者焦虑.
我们不过活在一个小小的星球上,再大的错误,贪欲和灾难也大不过这颗沙粒.宽恕自己曾经犯过的错误,宽恕他人对我们的不公.我们都是好人,不应因为他人的错误如此对待自己.
活下去,为了自己白发斑鬓的父母,为了那些爱我们的,以及我们爱的人.
本人并非什么心理医生,只是一个经常异想天开的年轻人.听过恶魔的私语,受过死神的蛊惑,他骑着灰色的马,来了,又走了.我还侥幸活着,却也失去了很多…很多…所以开设本页面供大家匿名发泄.我也害怕死亡,但大限将至时,我会坦然接受.我们应对死亡心怀敬畏,不应如此轻易亵渎死亡.
为了那些爱我们的,以及我们爱的人,活下去.
即便是为了不让死后被可恨之人嘲笑,也请活下去.
这句话算是庄子里比较有名的,老庄都是以比较雷人著称.
今天无意间到了百度百科的”圣人不死,大盗不止”条目:http://baike.baidu.com/view/675172.htm
好吧,被雷住了,各种断章取义,各种歪曲…唉,自家文化都搞不明白的淫啊…桑不起.
而后搜了一下这句话的解释,大部分同样只拿原文的第一部分说事,这也印证了当下的网络文化,道听途说者居多.很少有人愿意拿出原文来仔细读一读.
原文很有意思,可以说是影射XXX的,哈哈~大概意思就是说圣人即大盗,大盗即圣人.小贼偷金银珠宝,大盗欺世盗名.
第一部分总结为”世俗之所谓知者,有不为大盗积者乎?所谓圣者,有不为大盗守者乎?”,聪明人把钱财都放在保险箱里来防止小偷,但这不是在为大盗囤积财物么.同样的,圣人治国有道,但国家被大盗篡夺,不也是在为大盗守护财产么.
接下来一段~重点来了~庄子讲了一个小故事.大盗的徒弟问大盗,”盗亦有道呼?”大盗怒斥道,”怎么会TM没有呢! 能猜到谁家有宝贝是圣明,能争先恐后进去抢是勇敢,条子来了主动殿后是义气,懂得何时进退是智慧,舍得合理分配赃物是仁爱!不具备这五条,不能称为大盗!有木有!” 所以好人不懂怎么当圣人,就一事无成.坏人不懂怎么当圣人,也一事无成!但天下好人少坏人多,懂的怎么当圣人的人多了,自然对社会也是好处少,坏处多.所以让大家都不懂得怎么当圣人,也就没有了大盗.原文有木有!有木有!我真是hold不住了,吐槽无力啊!
在往下就是总结前两部分了,讲大盗如何盗国.推崇圣人,就等于是推崇大盗.人们用秤砣测量重量,那么大盗就去制定秤砣的标准.天下用仁爱规范道德行为,那么大盗就连同仁爱一起盗走.偷窃财物的小偷,抓住要被诛杀,偷窃国家的大盗,却被奉为诸侯.而且这些诸侯还给天下讲仁爱道义,这不也把仁爱偷走了么.那些追随大盗的部下,也将自己抬为诸侯,窃取权利,谋取私利,封官加爵也不能使其满足,重刑威慑也不能使其害怕,因为他们把这些都窃取了.
所以,世上有圣人,就有偷窃圣人之位的大盗.世上被人尊称为圣人的淫,亦有可能是欺世盗名的大盗.
The End!