Puzzle

Possibility

Hi Dr. XXXX,

It is a naive thought and I hope you have time to give me some hints as to this lenghy, trivial puzzle to me.

It always bothers me a lot when I planned in c++ to design a class of logic object which describes any proposition as an object of this class. In my intuition, this class is to store all characteristics of a proposition such as the language expression of the proposition, the truth value, the possible logic operations rule like "and", "or" etc. It seems quite simple for me at beginning to overload the operator to implement logic operations.

But then I run into a puzzle, it seems that I can never assign truth value to a certain proposition as almost all proposition's truth value is uncertain. For example, "Today is colder than yesterday". I never know if this proposition is true or false as "today" and "yesterday" is undefined and the truth value varies when "today" is changing. What's worse, if I don't check the weather data from certain source like weather forecast, message from others, or try it by myself etc., I will have no way to settle the truth value of this proposition. And even I do all checking, still there will be some reason, I might give the wrong value, such as I checked wrong data, people lied to me, I have a fever.... So, I began to think all proposition is undefined with their truth value unless I explicitly assign one for it.

Yet it changed my view when we look at the proposition like "2 is bigger than 1" which is always true with no need to justify. I try to figour out that some propositions are describing "facts", some are describing "rules",and some are dealing with "hyperthesis" etc. However, it is still not a convincing explanation to me though I cannot tell why.

I am taking a statistic course "STAT 249" which greatly surprises me by applying many similar methods of logical operations. It hints me that maybe every proposition is indeed having a certain possibility to be true or false. Say "today is colder than yesterday" is only having roughly 50% of chance to be correct. Yet "2 is bigger than 1" is 100% of chance to be correct. Then we might define all proposition to be a kind of function of time t: proposition p--->f(t) where the range of function f(t) is either 1 or 0, or in other word true or false. For some proposition like "2 is bigger than 1" always has value of 1 for any value of t, that is always true for all time. And for other propositions, the value of function is varying between 1 and 0, that is sometimes true and sometimes false depending the domain of time t. This seems to explain well for my puzzle. Even for the most trouble one---truth simbol like "true" and "false", it gives a perfect solution: they are simply const function with value of 1 and 0 respectively for all possible time t.

Anyway there seems to be another approach to solve the problem with "2 is bigger than 1" by dissecting the proposition into several more propositions like: p= {"it is 2"}, q = {"it is 1"} , r ={"first is bigger than second"};

Then we can define: (p^q)-->r

For proposition like "today is colder than yesterday", it will be very complicated to change it into more propositions:

p = {temperature of today}; q= {temperature of yesterday};

r = {the first is bigger than second} ; s = {the first is colder than second}

Then we can define: r(p, q) --->s(p,q)

And this solution is not uniformal but maybe practical. It requires too much analysis for language itself. So it may not be practical for computer compared with the "statistic view" of truth value.

In my view, it is always a similar for human to recognize if a proposition is true or not by collecting some sample with experiments or observations at very early stage. As the accumulation of result of this proposition or hyperthesis goes up, the man counts the possibility or the number of truth value of that proposition. Then the truth value of a certain proposition is established on basis of "possibilities". So, it is also a good way to describe all propositions in this way to imitate the process of human being.

Thank you for your time and I am waiting for your advice.

关于数字显示的方法及其除法

Hi,

我的问题是怎样显示一个数字呢？我能想到的办法就是用连续除以10，将余数存入stack，直到商为0。再从stack中将余数一一取出，加30h显示。可是，我碰到一些问题：

1。8位和16位除法不同，我必须根据被除数大小采用两种不同的除法。所以，在作16位除法时我每次都要去判断结果是8位还是16位，以便采用不同的除法。这样会有问题吗？

2。我在codeview里无法trace,因为我运行时候总是报divide overflow的错误，后来我在dos环境里，直接运行cv去debug，一步步都ok,甚至结果都看到了，是正确的。可是，codeview里还是不能运行，直接运行exe文件还是报divide overflow的错误。我想知道，作除法时，怎样判断divide overflow的？是看flag 寄存器的某一个标志位吗？

谢谢。

黄清浙

.DOSSEG
.MODEL SMALL
.STACK 100H
.DATA
ARRAY DB 115,125,125,140,110
MSG DB "IT IS 3!", "$"
BUFFER DB 10 DUP(?)
.CODE
START:
MOV AX, @DATA
MOV DS, AX
MOV AX, OFFSET ARRAY
PUSH AX
MOV AX, 5
PUSH AX
CALL SUMARRAY
XOR AX, AX
POP AX
MOV BL, 10
XOR CX, CX
;MOV AH, 0
CMP AH, 0
JNE DOUBLEDIVIDE
DIVIDE:
DIV BL
XOR DX, DX
MOV DL, AH
MOV AH, 0
ADD DL, 30H
PUSH DX ; STORE RESULT IN STACK
INC CX ; COUNTER +1
CMP AL, 0
JE ENDDIVIDE
JMP DIVIDE
DOUBLEDIVIDE:
DIV BX
ADD DL, 30H
PUSH DX
INC CX
CMP AX, 0
JE ENDDIVIDE
JMP DOUBLEDIVIDE
ENDDIVIDE:
POP DX;
MOV AH, 02H
INT 21H
LOOP ENDDIVIDE
ENDQUICK:
MOV AX, 4C00H
INT 21H
SUMARRAY PROC NEAR
GETPARAM:
PUSH BP;
MOV BP, SP
PUSH BX;
PUSH CX
PUSH DX
PUSH AX
MOV CX, [BP+4] ;ARRAY SIZE
MOV BX, [BP+6] ; ARRAY ADD
MOV DX, 0; SUM
SUMLOOP:
MOV AX, [BX]
MOV AH, 0
ADD DX, AX
ADD BX, 1;
LOOP SUMLOOP;
MOV [BP+6], DX; PUSH RESULT IN STACK
POP AX
POP DX
POP CX
POP BX
POP BP
RET 2;
SUMARRAY ENDP
END START

Nick Huang

Qustion:

黄兄你好，

小弟有如下数题百思不得其解，恳请指点。

Assignment3

3 ; 6; 12(ii);14;15;16;17

还有几个关于SET的概念：

A∪B = { Q(x)→P(Q)} = ??

∪B = { P(Q)→Q(x)} = ??

Answer:

1. Assignment3 No.3: 这个题目的意思是确定f是否为onto.在确定是否为onto时候其实我们更关心的是co-domain里是否每一个元素都有包括在function f里面。显然，这道题里面的自变量有两个，m,n。我们要确定的是这两个子变量所组成的函数的值是否覆盖了整个自然数。例如，iii)f(m,n) = |m|+|n| 很明显的，他的值是非负的，所以，一定没有覆盖所有的自然数。经验就是，讨论是否onto时候，主要关心的是co-domain的值，至于domain不要被他的复杂所迷惑。

2。Assignment3 no.6: 这个题目的意思是求组合函数。在学了关系（relation)以后，可以更好的理解，如f@g,假如我们把f,g看作关系（函数本身就是一种关系）那么就表示为从关系g的起始集合里的某个元素a对应g的终止集合里的某个元素b,同时这个元素b恰好是关系f的起始集合里的元素，那么关系f里b所对应的终止集合的元素c就和a组成了一种新的关系，这个新的关系就是组合关系f@g。

请注意，这里是g的起始元素到f的终止元素，和记号f@g的顺序正好相反。

回到函数，f@g就是表示函数g是函数f的自变量，也就是复合函数，所以，你只需要把函数f的自变量用函数g来替换就可以了。

3。A3 no. 12ii) a congruent b(mod m) ==> gcd(a,m)==gcd(b,m)

这个题目有几种思路。 最简单的是应用欧几里德算法的一个推论（p178) a = bq+r ==>gcd(a,b)==gcd(b,r)

从题目知：m|a - b(congruent定义)==> exist q(a- b = qm) (整除的定义）==〉exist q(a= b + qm)(移项）

==〉gcd(a,b) = gcd（b,m) (运用上述的推论）

solution中实际上给出了一个对推论的简单证明：

a - qm 和 a - m有同样的divisor(可以找一找书上的定理或者简单证明如下：

exist x(x|a and x|m)(假设a和m有同样的divisor的话） ==>exist x exist q(x|a-qm and x|m)

(这个是定理，p154 corollary,就是m=1,n=-q的情况.）

==> gcd(a,m) == gcd(a-qm,m)(因为gcd是公约数中最大的一个而已。）

在运用题目的部分：

m|a - b(congruent定义)==> exist q(a- b = qm) (整除的定义）==〉exist q(b= a- qm)(移项）

所以， gcd(a,m) = gcd(a-qm, m) = gcd(b, m)(把b=a-qm代入）

4。 A3 no. 14.:这个题目的证明很繁杂，solution的思路也比较难想到，我的证明想法就是tutor的提示，先考虑n是否能被5整除，就是n=5k如果能被5整除可以很容易去证明底数是80的那个（当然你还是要用到题目要求的n市奇数的条件，所以你要进一步假设k是奇数k=2h+1,所以n=5(2h+1) = 10h+5)

当n不能被5整除时候，分4种情况：余数分别是1，2，3，4，同时类似地让n还是奇数，比如余数为2时候,n=5k+2,这时候k只能是奇数n才能是奇数，所以,n=5(2h+1)+2 = 10h+7。这样你再参考以下solution的方法判断奇偶数，就可以了。

5。 A3 no. 15:这些题目你要参考tutorial的笔记，要点就是比如第二题：x~2 congruent 3(mod 4)这一步有一个隐含的结论就是{x~2 mod 4|x is integer} =={x~2 mod 4| x =0, 1,2,3}, 就是说x平方除以4的余数等于x取0，1，2，3所得的余数一样，这个证明，你可以看一下tutorial的笔记，或者你记住这个结论也应该可以吧。

6。A3 no. 16:这个题目前面1，2的证明应该很简单，全部是根据floor, ceil的定义。第3，4的证明我觉得solution的反证法不好，因为，考虑的情况应该有4种，很麻烦，不如我的证明法简单易懂。

7。A3 no. 17：这个题目证明有很多小题，你对那一题不清楚呢？或者，星期一早上到H-513碰头再说吧。

8。 A∪B = { Q(x)→P(Q)} = （这里有一点错误，第一个B应该为B的补集--complement，你是从哪里拷贝的？我还真没有办法找到这样的图片来改正。哈哈。）

∪B = { P(Q)→Q(x)} =

简单的证明可以帮助你理解：

假定 P(x) <==>(def) x in A; Q(x) <==> (def) x in B

x in A U not B <==> all x( x in A or not x in B) <==> all x[not Q(x) or P(x)]

<==> all x[Q(x) --> P(x)] (注意这里都是逻辑关系，我只是说了如果有一个元素x属于这个集合的话就相当于逻辑上的相应关系。）

而集合是可以有逻辑关系来定义的。比如：{x| (x in A) or (not x in B)}就定义了上述集合。

而从集合的运算我们又可以得到：（我贴不出了，相信你明白的。）

所以，我的经验就是，集合是集合，逻辑是逻辑，符号和关系只是类似，并不能混用，但是两者又有联系，集合可以用逻辑来定义，逻辑可以用集合来表现，更好理解。

最后一个就是exclusive or,你可以在图上的红点和灰点看出来。

关于不定指令集的问题

这是我的备忘录，将来学comp229再来解决：在固定指令集中，fetch总是可以取到完整的一条指令。可是，在不定指令集中

怎么才能取到下一条完整指令？该取多少bytes?

这个问题解决了：问朱春明同学，他说的很好，我们就取最长的指令好了，有什么关系？反正纪录的是下一条指令的首地

址。好！

关于RSA加密系统的猜想

问题：

您好！有个加密问题想请教您，比如rijindael 是256bit 加密的，如果我的password是8位或100位，是否破解时间一样（用穷举法）。这里所指的258bit是怎样一种概念，是否最长password为256位。

我的解答：

老实说， 我并不是很确定256bit加密究竟是怎样的，但是，以我现在学到的离散数学的知识，我猜想他应该是应用RSA公共密匙系统，因为这是互联网上最普遍应用的一种加密系统。所谓公共密匙实际上是建立在余数定理上的一种算法。他的基本算法不复杂，任何一本 离散数学的书里应该都有，我也写过这样的加密解密程序：
http://www3.sympatico.ca/qingzhehuang/RSA2.htm
首先，我解释一下公共密匙的概念，以往的私有密匙的问题在于，你知道加密的密匙，一般你就自然知道怎样解密了。所以，当你把密匙一起随信息传送的时候，如果，密匙被截获，加密就毫无秘密可言了。公共密匙是即使你知道了加密的密匙，你要破解解密的密匙，所要耗费的时间是比天文数字还要大，所以，几乎不可能。
具体算法解释起来需要不少数学基础知识和定理，原理简单说来就是，寻找两个非常大的质数p,q,把他们的乘积作为公共密匙分发给用户来加密解密，这样，而加密的钥匙exp是每一个用户自定义的加密的钥匙，当然有一定的规则。加密时候，把每一个字母或数字的exp的幂除以p*q的余数就是加密的结果。而解密的时候，必须利用(p-1)*(q-1)的乘积结合exp来计算出一个解密的钥匙dexp，每一个加密的数字的dexp次幂除以p*q的余数就还原成原来的结果，这里面有一系列的证明。
最本质的问题在于要破解密码必须要知道dexp，而要知道dexp必须要知道(p-1)*(q-1),而要知道(p-1)*(q-1)单单靠知道p*q的乘积对你并没有多少帮助，你可以想象你要计算
(p-1)*(q-1)唯一的办法就是知道p和q。从公共密匙p*q推算出p和q，除了一个个的尝试，没有更好的办法，因为p,q是质数，单单知道他们的乘积没有给你任何捷径来计算p和q。
当我们选择两个非常大的p,q，比如各自有200位数字，或者要256bit才能表示的质数时候（这是一个非常大的数字了换成10进制有将近100位数字。），理论上从p*q来计算出p和q用最强的计算机也要几十亿年。（关于时间我们的教科书上没有说是十进制的200位还是2进制，我想差不多都是太长太长了。）
所以，如果我猜想的不错，256bit加密法用穷举的办法来破解几乎是不可能的。你的自定义的密匙exp的长度在这里与破解p和q并无直接的关系，因为你最终无论如何都要知道p和q才能计算出解密的dexp。
当然，这一切都是建立在加密系统为RSA的基础上的，我曾经观察过这里银行，学校等等的密码验证加密系统都是RSA。你可以双击浏览器的底边上的那把小黄色的锁，看加密的证书系统，看看是不是有一个public key RSA 1024bits 或者256bits就知道了。
你如果对RSA系统还有什么问题，我们尽可以一起讨论。

逻辑仅仅是征途上的航标灯？？？

假如给我们一棵搜索树，每个节点代表一个逻辑判断，从一个已知真伪的节点出发根据一系列的所谓“逻辑”关系去试图到达某一个目的节点，这个过程我们通常称作“逻辑推理”。从广义的搜索来看，逻辑的与或仅仅是节点之间相对关系。

例如，所谓“或”说的是当你到达某一个节点继续前进有一系列子节点供选择时候，从“或”中任意选一个都可以继续。

所谓“与”说的是当你达到某一个节点继续前进有一系列子节点供选择时候，必须要同时选择这些子节点才可以继续前进，可是，我们真的有“分身术”同时走多个路径吗？

这其中似乎蕴含着某种深奥的东西，绝非“串联，并联”这么肤浅。

我在想也许几百年后的考古学家都是计算机，他们所感兴趣的课题就是人类的思想发展，那么我的这些日记加垃圾就是一份极好的素材。

这个问题很严重！

问题：

我最近有个作业　是叫用Matlab做的　我知道是比较简单的　但我的确不会做啊
试求一个3行3列矩阵A：
1.各行各列元素和为7,各元素>=0.
2.
┌─┐ ┌─┐
1 3.5
A * 0.5 = 3.5
0 3.5
└─┘ └─┘
3.用MATLAB 软件实现.

回答：

hi,
1. 我没有用过matlab不懂，很抱歉，不过，我想他的原理和maple应该差不多，是工程计算的，对吧？（实际上我也没有用过maple,这里纯粹有些无端了。）
2。 不过问题应该不会太难，我向所有的软件都可以解决一个基本的问题：多元一次方程组的解是可以用软件计算的。这个只要学过线性代数的就知道，用矩阵来表示系数，用消元法，我自己就写过，很早以前了，（大约是在冬季。 哈哈。。。）
http://www.staroceans.com/Matrix3.htm
所以，我敢肯定你所说的matlab一定有这个基本的功能，问题是怎样表达：
你的矩阵式3x3就是说有9个未知数，所以需要9各独立方程，你的各行各列的和给了你6各方程，你还需要3格，这三个就是最后那个矩阵乘法，我想你一定知道，这个乘法会再给你3各方程吧？这样你就已经获得了求解所必要的9x9的矩阵系数了，明白我的意思吗？你所要求解的9个变量应该组成的方程式：
a1A+b1B+c1C+d1D+e1E+f1F+g1G+h1H+i1I = const1
a2A+b2B+c2C+d2D+e2E+f2F+g2G+h2H+i2I = const2
...
a9A+b9B+...
其中的a1,b1...这些就是你的系数，他们可以为零，你有这样9个独立的方程式，就可以解9个变量了。
假如matlab不提供这个基本功能，或者你找他们索赔，或者我写给你，（就在我的链接里，应该有，我忘了。）哈哈，开玩笑了。
以上都是开玩笑，但是你的问题给我了当头一棒，因为，他非常的重要：就是我所写的所有的搜索的问题都是有一个起始点，或者说搜索树有一个root,可是你提出的问题，却是目前我无法解决的：无限的搜索，无根的搜索树！这个问题很严重！首先，对自然数我可以用归纳法的模式扩展，因为，自然数是一个well-ordered的集合，它有一个最小值0，可是队有理数就没有办法了。其次，搜索的初始条件是不确定的，下次搜索需要增加的差值，也是不确定的，这个问题似乎是自动机模型所不能解决的，我一点主意也没有。谢谢你的问题，请允许我把这个问题记录在我的网页上。
希望对你有帮助，你是学工程的吧？
Nick Huang/Qingzhe Huang

真正的问题：

在我心目中基本上任何问题都可以用一个搜索来解决，只是搜索的级别不同，或者说层面，这个意思不好表达，比如我们有一个函数，我们让他去解决一个问题，可是当我们有很多的函数解决具体的问题，我们需要一个更高级的函数来调用这一系列函数来解决一个更高级的问题，这就是high-order-function的意思。而所有的搜索都是基于一个有根的树，这一点不妨用自动机的角度来看，我们可以有很多的或者根本没有final state，可是不能没有起始点，而且只能有一个。这一点从数据结构的角度来看，我们不允许重复，因为，有环的搜索只会陷入死循环。树的定义就是没有环的图。

问题是我们找不到起始点，或者说有无限或者说有很多的可能的起始点的话，我们的搜索会变得不可行，这才是问题！

这个证明是否合理？

hi,
我很想听听各位对comp335里关于“计算机程序不能证明某些问题的证明”。
原来的证明简要如下：
http://www.staroceans.com/helloworld.htm#problem
假设有一个程序turing可以把另一个程序的输出作为他的输入，然后检测这个输入是否为"hello,world"在输出一个检测结果。
比如，如果输入为"hello,world"，则程序输出"yes"，反之则输出"hello, world"。（这里，我们可以认为输入程序没有任何输出也形同一种输出，即没有输出"hello,world"。）
现在，假设以turing程序自身作为自己的输入程序来检验自己，书上的证明是这样的，假如，程序最终的输出为"yes",则意味着输入程序的地输出为"hello,world"，可是，根据假设我们的turing程序输出的是"yes"，这是矛盾的。所以，这样的turing程序是不可能存在的。所以证明了有些问题是计算机程序所不可能解决的。
http://www.staroceans.com/helloworld.htm#explain
问题在于，我对这个证明有些怀疑：我们都知道program这个概念一般是指source code。而程序在运行的时候我们称之为process。一个program可以由多个process。而且这些process可以有不同的行为，取决于具体的运行环境。
因此，问题中的两个turing程序应该理解为两个turing program的两个process。自然两个process是可以有独立的输入输出，也自然有着互不相干的运行结果，所以，以上的证明中的矛盾并不存在，因为压根就使两个不同的输入输出，何来矛盾之有？
各位对此有什么看法？
Nick Huang/Qingzhe Huang

与jeppeter君商榷

>I am interesting with you site ,and i think that the CFGReader
> can be rewrite with the typical object oriented ,just using fstream
>instead of FILE* vector instead of char arrays and so on ,this will give
>more beautiful coding style.
> jeppeter

Hi,
Thank you for your message.
I understand your concerns about using "FILE" instead of "fstream". However,
as long as OO is concerned, I don't agree your point. We all understand that
OO intends to hide the implementation details from users, thus this "FILE"
is only an
implentation details as long as I don't expose it to my class-users.
As you know, the "fstream" is inhereted from "iostream" and its purpose is
to give a uniformal interface for all I/O methods. In other words, they want
you to treat all I/O in a similar way. To achieve this goal, it has a lot of
details to
take care. However, for my CFG-Reader the only purpose is to read from a
file. (If the user want to input from terminal by typing, it will be
regarded as unrealistic because it is complicatedly long and error-prone.
That's the reason for file-input. ) Then why should I use the complicated
"fstream". Besides "fstream" is supposed to check words. And for me, char by
char checking is necessary. So, I choose to use "FILE".
As for vector instead of char[], I am not quite sure. Since I did expose the
string to my user. It is logically to be some user-friendly data structure.
But a wrapper class will easily solve the interface problem, what do you
think?
By the way, where are you? studying or working? How do you find my web site?
By google?
I am happy to find some pals with same interest.
Keep in touch,
Nick Huang/Qingzhe Huang

Unix learning notes:

Here goes the problem...

> Hi,
>
> I loggin to alpha and edit the .cshrc as showed in your slides. But when
> I checked the version of java , it is still 1.4.1 by "java -version". At
> first I thought I have made some mistakes in .cshrc, but I checked and
> cannot find any error in file cshrc. Can you check the file attached for
> me? thank you for your help,
The newer account have two 'set path=' statements: after if() and after
then(). You changed the one for Linux I should think.

Here is the result...

Hi,
Thank you for your message, you are right! I don't understand the "if", so I
change the wrong place. It works now.
have a nice day,
Nick Huang/Qingzhe Huang

How should I change the environment variables?

set env PATH /mypath/ :$PATH

This will add /mypath/ before the old path. And you can also append the path.

The several stupid mistakes when using java first time...

1. The file name must be exactly same as class name. What an absurd request? It is very obvious the JDK writer

is such a lazy, arrogant guy!

2. You must add public before the class. What a meaningless idea? Is there any private class? Possibly yes.

3. Don't forget the class usually starts with capital letter. It is sensable.

This is a little example of callback function.

    这个小例子是我们都玩过的剪刀石头布。有一个裁判程序（judge)，你和我都有一个出手的程序(youFight, meFight)和以及各自的策略数据(yourStrategy,

    myStrategy)。使用的时候就把他们都当作参数带入裁判程序。

    为什么要这样写呢？原因就是flexibility，假如，你忽然想要改变策略数据的话，就换一个参数带入就好了，裁判时不用变得。你也可以改变你的出牌的方法

    也就是重新定义一个新函数，只要参数类型个数，返回值类型与现在的一样就可以了，比如说，改变shift的值，或者就干脆用随机数等等。

    #include <iostream>

    using namespace std;

    //this is not a program, but a joke...hahha...
    const int MatchNumber=10;

    //you know what they are, right?
    //we all play this little game
    enum FightType
    {Scissor, Stone, Cloth};

    char* typeStr[3]={"Scissor", "Stone", "Cloth"};

    //this is the sequence you might play
    int yourStrategy[MatchNumber]={2,1,0,2,1,2,0,2,1,1};
    //this is the sequence I might play
    int myStrategy[MatchNumber]={0,1,2,1,2,1,0,2,1,0};

    //this is the match judge, with two your play function and your strategy
    //and my function and my strategy
    void judge(int (* youPlay)(int* yourParam, int theNumber), int* yourParam,
    			 int (*myPlay)(int* myParam, int theNumber), int* myParam);

    //actually this is the function you defined here
    int youFight(int* youParam, int index);
    //I won't repeat
    int meFight(int* myParam, int index);

    int main()
    {
    	judge(youFight, yourStrategy, meFight, myStrategy);
    	return 0;
    }

    void judge(int (* youPlay)(int* theParam, int index), int* yourParam,
    			 int (*myPlay)(int* theParam, int index), int* myParam)
    {
    	int you, me;
    	for (int i=0; i<MatchNumber; i++)
    	{
    		you=youPlay(yourParam, i);
    		me=myPlay(myParam, i);
    		cout<<"your type is:"<<typeStr[you]<<endl;
    		cout<<"my type is:"<<typeStr[me]<<endl;
    		switch (you-me)
    		{

    		case 0:

    			cout<<"it is a tie on match no."<<i+1<<endl;
    			break;
    		case 1:
    		case -2:
    			cout<<"you win on match no. "<<i+1<<endl;
    			break;
    		case -1:
    		case 2:
    			cout<<"you lose on match no."<<i+1<<endl;
    			break;
    		}
    	}
    }

    //you can change your strategy simple by....
    int youFight(int* youParam, int index)
    {
    	//actually you can define any method you imagine
    	return yourStrategy[(index+5)%MatchNumber];
    }

    int meFight(int* myParam, int index)
    {
    	//by shifting the current strategy, you have a new one
    	return myStrategy[(index+2)%MatchNumber];
    }

This is the example of template class acting as your callback parameter in template function

    #include <iostream>

    using namespace std;

    //this is not a program, but a joke...hahha...
    const int MatchNumber=10;

    //you know what they are, right?
    //we all play this little game
    enum FightType
    {Scissor, Stone, Cloth};

    char* typeStr[3]={"Scissor", "Stone", "Cloth"};

    class YourPlay
    {
    private:
    	static int yourStrategy[MatchNumber];
    public:
    	static int youFight(int index)
    	{
    		//actually you can define any method you imagine
    		return yourStrategy[(index+5)%MatchNumber];
    	}
    };

    class MyPlay
    {
    private:
    	static int myStrategy[MatchNumber];
    public:
    	static int meFight(int index)
    	{
    		//by shifting the current strategy, you have a new one
    		return myStrategy[(index+2)%MatchNumber];
    	}
    };

    //the static strategy is initialized here
    int YourPlay::yourStrategy[MatchNumber]={2,1,0,2,1,2,0,2,1,1};
    int MyPlay::myStrategy[MatchNumber]={0,1,2,1,2,1,0,2,1,0};

    //THIS IS THE BUG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    //you cannot declare the template function
    //compiler don't recognize it!!!
    //believe it or not, try declare it as following:
    /*
    template<class yourPlayClass , class myPlayClass>
    void judge();
    */
    //and put the implementation below after "MAIN" function
    //then you will get memory access error, because
    //what you declared is not implemented!!!!!
    template<class yourPlayClass , class myPlayClass>
    void judge()
    {
    	int you, me;
    	for (int i=0; i<MatchNumber; i++)
    	{
    		you=yourPlayClass::youFight(i);
    		me=myPlayClass::meFight(i);
    		cout<<"your type is:"<<typeStr[you]<<endl;
    		cout<<"my type is:"<<typeStr[me]<<endl;
    		switch (you-me)
    		{

    		case 0:

    			cout<<"it is a tie on match no."<<i+1<<endl;
    			break;
    		case 1:
    		case -2:
    			cout<<"you win on match no. "<<i+1<<endl;
    			break;
    		case -1:
    		case 2:
    			cout<<"you lose on match no."<<i+1<<endl;
    			break;
    		}
    	}
    }

    int main()
    {
    	judge<YourPlay, MyPlay>();
    	return 0;
    }

    The bug I want to ask about...

Hi Sir,
The following code defined a friend function which overloads the operator "<<" with "ostream". But compiler cannot reconize it as "friend" function:
#include <iostream>
using namespace std;
class Test
{
friend ostream& operator<<(ostream& out, const Test& dummy);
private:
int data;
public:
Test();
};
int main()
{
Test T;
cout<<T;
return 0;
}
Test::Test()
{
data=15;
}
//the function is already defined as friend, but compiler is blind.
ostream& operator<<(ostream& out, const Test& dummy)
{
out<<dummy.data<<endl;//access private member of "Test"
return out;
}
The error message is "error C2248: 'data' : cannot access private member declared in class 'Test'
d:\program files\microsoft visual studio\myprojects\arena\arena.cpp(9) : see declaration of 'data'"
So, I have to put the definition of "friend" function within the declaration of class as following:

    #include <iostream>

    using namespace std;

    class Test
    {
    	friend ostream& operator<<(ostream& out, const Test& dummy)
    	{
    		out<<dummy.data<<endl;//access private member of "Test"
    		return out;
    	}

    private:
    	int data;
    public:
    	Test();
    };

    int main()
    {
    	Test T;
    	cout<<T;
    	return 0;
    }

    Test::Test()
    {
    	data=15;
    }

I would be grateful if you have an explanation or solution to this kind of problems.
Thank you for your time.
Nick Huang/Qingzhe Huang

    问题：

    。。。我现在有一个问题想请教你:计算机网络里面的"距离向量路由算法"的演示软件如何实现啊,希望你帮忙,万分感激 !

    回答：

刚听到距离向量路由算法以为是什么神奇的东西，google了一下才知道可能是这么回事。
每个路由器维护一个路由表，这个路由表实际上就是Bellman-ford的最大流的一个图，图利的每个edge的weight应该是连接着响铃两个路由器的距离，我像最简单的就是用到达时间来表示，当然这样问题就变成了最小流的，不过算法还是Bellman-ford的算法，（最土的就是把这些时间t表达为100000-t,这里1000000是一个很大的数就行了，就还是最大流问题了。）
运用Bellman-ford算法可以找出一条最短路径，而这个什么“距离向量路由算法”协议自己规定超过15节点的路径就是不通的路径。应该就是这样的。
我当时学算法的时候曾经想写一个bellman-ford的算法的实现，后来实在是太忙了，再加上这个算法确实有些麻烦，我找到一个伪代码，
http://en.wikipedia.org/wiki/Bellman-Ford_algorithm
不过当我匆匆扫了一眼这个算法，我觉得你没有必要用这个，因为dijkstra的算法也能做到，唯一的不足是要求weight必须为正直，在网络里面，距离当然是正的了，我的意思是路由表里面的路径都是双向的，对吧？（关于网络通讯这些EE的课程我只上过一门入门的课，不是很清楚，）不存在说从A到B可以走，从B到A就不能走的情况，对吧？
如果有什么错误记得告诉我一声，我也可以学习一下。

    // Define datatypes for a graph
    record vertex {
        list edges
        real distance
        vertex predecessor
    }
    record edge {
        node source
        node destination
        real weight
    }

    function BellmanFord(list vertices, list edges, vertex source)
       // This implementation takes in a graph, represented as lists of vertices
       // and edges, and modifies the vertices so that their distance and
       // predecessor attributes store the shortest paths.

       // Step 1: Initialize graph
       for each vertex v in vertices:
           if v is source then v.distance = 0
           else v.distance := infinity
           v.predecessor := null

       // Step 2: relax edges repeatedly
       for i from 1 to size(vertices):
           for each edge uv in edges:
               u := uv.source
               v := uv.destination             // uv is the edge from u to v
               if v.distance > u.distance + uv.weight
                   v.distance := u.distance + uv.weight
                   v.predecessor := u

       // Step 3: check for negative-weight cycles
       for each edge uv in edges:
           u := uv.source
           v := uv.destination
           if v.distance > u.distance + uv.weight
               error "Graph contains a negative-weight cycle"