﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-hainan-最新评论</title><link>http://www.cppblog.com/hainan/CommentsRSS.aspx</link><description /><language>zh-cn</language><pubDate>Wed, 18 Jul 2007 15:12:02 GMT</pubDate><lastBuildDate>Wed, 18 Jul 2007 15:12:02 GMT</lastBuildDate><generator>cnblogs</generator><item><title>re: 读书的时光</title><link>http://www.cppblog.com/hainan/archive/2007/05/06/20067.html#23542</link><dc:creator>nan</dc:creator><author>nan</author><pubDate>Sun, 06 May 2007 15:24:00 GMT</pubDate><guid>http://www.cppblog.com/hainan/archive/2007/05/06/20067.html#23542</guid><description><![CDATA[         看了，《律政俏佳人》后，感觉生活又充满了激情，好想像篇中的女主人公那样生活，生命诸多挑战、、、、、、我当时看的时候简直是愤青一个。<br>       、、、、、、<br>       人大概都是这样，非得有外物刺激，才开始又一次励志，即使到头来是枉然。<br>       于是开始抱怨时运的不济，命途多舛倒好，好歹终日有事可做。<img src ="http://www.cppblog.com/hainan/aggbug/23542.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hainan/" target="_blank">nan</a> 2007-05-06 23:24 <a href="http://www.cppblog.com/hainan/archive/2007/05/06/20067.html#23542#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>re: 世界上最难的一道题！</title><link>http://www.cppblog.com/hainan/archive/2007/05/05/20065.html#23455</link><dc:creator>小新新</dc:creator><author>小新新</author><pubDate>Sat, 05 May 2007 11:50:00 GMT</pubDate><guid>http://www.cppblog.com/hainan/archive/2007/05/05/20065.html#23455</guid><description><![CDATA[德国人养金鱼咯!<img src ="http://www.cppblog.com/hainan/aggbug/23455.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hainan/" target="_blank">小新新</a> 2007-05-05 19:50 <a href="http://www.cppblog.com/hainan/archive/2007/05/05/20065.html#23455#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>re: 读书的时光</title><link>http://www.cppblog.com/hainan/archive/2007/04/29/20067.html#23179</link><dc:creator>Hainan's CppBlog</dc:creator><author>Hainan's CppBlog</author><pubDate>Sun, 29 Apr 2007 05:07:00 GMT</pubDate><guid>http://www.cppblog.com/hainan/archive/2007/04/29/20067.html#23179</guid><description><![CDATA[糜烂的生活依然继续，<br>我已是焦头烂额。<br>几千次的痛下决心，<br>终于练就了嘴上功夫。<br>或是干脆让糜烂肆恣，<br>也落得个自在。<br>、、、、、、<br>躲进被窝成一统，<br>管他春夏与秋冬。<img src ="http://www.cppblog.com/hainan/aggbug/23179.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hainan/" target="_blank">Hainan's CppBlog</a> 2007-04-29 13:07 <a href="http://www.cppblog.com/hainan/archive/2007/04/29/20067.html#23179#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>re: 生活的磨砺啊(1)</title><link>http://www.cppblog.com/hainan/archive/2007/04/29/21066.html#23174</link><dc:creator>雪个驴</dc:creator><author>雪个驴</author><pubDate>Sun, 29 Apr 2007 04:47:00 GMT</pubDate><guid>http://www.cppblog.com/hainan/archive/2007/04/29/21066.html#23174</guid><description><![CDATA[                                有感于今日之人民医院的全数字化......<br>    以前有个什么头疼脑热的就去附近的诊所，叫什么什么堂的。出门便是，方便快捷。自来广东上学之后越发觉自己是乡里娃了，<br>这里竟没有私人诊所（这样说未免有些夸张，据说是有，但不是给人看的），动不动就以什么院啊站啊的标榜，听起来好生气派，但<br>对于来自消费水平低的地方的人来说大都是不怎么敢进的。<br>    一日鄙人抱恙，多半觉得的是肠胃炎，这已是旧疾。本想去学校的医疗室看看算了，花上几十块。不料男友见我神情痛苦，眉头<br>紧锁的已不见五官，执意拉我去某某人民闪医院。嚇！我脑子里顿时一阵闪算，妈呀，好几百块啊，这足足是我一个月的伙食费啊。<br>脸上稍露难色，但还是去了,真是死要面子活受罪。<br>    到了医院门口，他搀着我，我手捂着肚子，挪进了赫然写着急诊的地方。哇，简直是门庭若市，看来老百姓还是“信任”规格化、<br>正统化的东西，似乎从那里出出进进的也比较有面子。进去有个保安站在门口，这就着实让我了没了安全感（我向来对穿制服的没什么<br>好感）。先是填了个有关个人资料的单子，然后我找了个位子坐下，他站在一个很长很长的队的队尾，领了一张医疗卡，卡上是个人<br>资料交些钱方可就医。我们很费周折的找到了医生的栖地，又得排队，当然队是要排的，命可以不要，规章制度却是要的，在中国，<br>如果。<br><br>    我强忍着剧痛，其他患者看着我的表情面无表情，医生就更不用说了，简单的问过症状，就开了方子，在电脑上点了几下就完成了<br>全部过程。古时不是有望、闻、问、切，难道时至今日，有了先进的检测仪器就不需要了吗？轮到我时，问倒是做到了，我对他说可能<br>是肠胃炎，当然我不是有扰医生“专业”的判断，只是就我以前的病历经验看。但他置若罔闻，因为他是医生。于是让我做尿检、血检，<br>对此我不能说什么。以为可以直接做完了事，没想又要跑到楼下在不同的窗口，同样又在长长的队尾，交钱方可进行治疗的下一环节，<br>我没跟着去，我已经是步履维艰了，一个人捂着肚子蹲在角落，每一个路过我身边的人都知道我脸上是快要死的表情。好怀念家对面的诊<br>所啊，此时。医生会根据轻重缓急诊治。做完了化验之后竟然完全正常，真希望出点什么事，应一下的医生的话。我惊呼，惊呼那位业内<br>资深的主治医生说这个没问题的话，那就是肠胃炎了。天啊，他把看病当做是在用排除法做题吗？照这样人人都可以做医生，挂牌上岗。<br>这还能为我国解决不少就业问题呢，但可能犯罪率就要上升了。我当时想啐他两口，简直无异于江湖术士，如果说医院是一坨屎，那医<br>生就是那坨屎上的苍蝇。他们跟他们身上穿的白大褂一样麻木、冷酷与无能。<br>    但凡大医院，先不管什么病，先让你做化验、CT、B超，让你把什么引进国际先进治疗仪用个遍，当然这时你的钱也花的差不多了，<br>走的话已经花费不菲了，不走又的受宰割，唉！<br>    接下来就是注射了，这总该顺利点吧。可医务人员告诉我们必须去对面的那个急诊室注射。此时我已毫无耐心，想一走了知，死就死了。<br>可是已经花了钱了，于是乎男友又搀着我走出了医疗室，医院的中央有花园、长椅，痛使我不能抬头，我的眼皮微微抬起，瞟了一下，人<br>们倒挺惬意。他为了逗我就说，你看我搀着你，你又捂着肚子，别人还以为你、、、、、、怀孕了呢，我想骂他，但嘴憋不住笑，扑哧全出来了。<br>    他呢还是得排队交钱，我的天，又要跑回刚才那个急诊区的窗口。。已经好几个小时过去了，病还没治医院就先把人弄死了。<br>我终于算是躺在了注射的椅子上，已经是在注射止痛药了，但好像没丝毫起色，痛就这样开始肆恣，于是又叫来另一位医生，他倒是很快诊断<br>我是肠痉挛，唉，本来是很轻的病情，硬是给这一整套数字化系统拖严重了。又于是又注射2针阿托品、、、、、、<br>    我有点晕呼呼的了、、、、、、<br>    我发誓死也不来这鬼地方了，现代社会不是什么数字化都好的。我拿着厚厚的医疗单，作为明天向我妈申报伙食费的凭证。我走出医院，回头看看，<br>依旧门庭若市，中国人，搞不明白。<br><br><br><img src ="http://www.cppblog.com/hainan/aggbug/23174.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hainan/" target="_blank">雪个驴</a> 2007-04-29 12:47 <a href="http://www.cppblog.com/hainan/archive/2007/04/29/21066.html#23174#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>re: 最近上课不用心</title><link>http://www.cppblog.com/hainan/archive/2007/04/24/22674.html#22717</link><dc:creator>Hainan's CppBlog</dc:creator><author>Hainan's CppBlog</author><pubDate>Tue, 24 Apr 2007 04:48:00 GMT</pubDate><guid>http://www.cppblog.com/hainan/archive/2007/04/24/22674.html#22717</guid><description><![CDATA[@江水兽<br>你是学电子的啊？<img src ="http://www.cppblog.com/hainan/aggbug/22717.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hainan/" target="_blank">Hainan's CppBlog</a> 2007-04-24 12:48 <a href="http://www.cppblog.com/hainan/archive/2007/04/24/22674.html#22717#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>re: 最近上课不用心</title><link>http://www.cppblog.com/hainan/archive/2007/04/24/22674.html#22713</link><dc:creator>江水兽</dc:creator><author>江水兽</author><pubDate>Tue, 24 Apr 2007 04:03:00 GMT</pubDate><guid>http://www.cppblog.com/hainan/archive/2007/04/24/22674.html#22713</guid><description><![CDATA[有同感！<br>估计可能是由于这学期的几门专业课有点难学：电子线路 电磁场理论。所以要认真和努力！共勉了！<img src ="http://www.cppblog.com/hainan/aggbug/22713.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hainan/" target="_blank">江水兽</a> 2007-04-24 12:03 <a href="http://www.cppblog.com/hainan/archive/2007/04/24/22674.html#22713#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>re: 世界上最难的一道题！</title><link>http://www.cppblog.com/hainan/archive/2007/03/28/20065.html#20769</link><dc:creator>Hainan's CppBlog</dc:creator><author>Hainan's CppBlog</author><pubDate>Wed, 28 Mar 2007 07:02:00 GMT</pubDate><guid>http://www.cppblog.com/hainan/archive/2007/03/28/20065.html#20769</guid><description><![CDATA[@pengkuny<br>#include &lt;iostream&gt;<br>#include &lt;string&gt;<br>#include &lt;fstream&gt;<br><br>using namespace std;<br><br>int main(void)<br>{<br> string Title[5] = {&quot;国籍&quot;,&quot;颜色&quot;,&quot;宠物&quot;,&quot;饮料&quot;,&quot;香烟&quot;};<br> struct problem{<br>  string nation;<br>  string color;<br>  string pet;<br>  string drink;<br>  string cigarette;<br> } House[5];//房子从左到右编号 <br><br> House[0].nation = &quot;挪威&quot;;//挪威人住在第一个房子里面<br> House[1].color = &quot;蓝色&quot;;//挪威人和住在蓝房子的人相邻,即蓝房子是第2个房子 <br> House[2].drink = &quot;牛奶&quot;;// 住在中间那个房子里的人喝牛奶<br><br> for (int e=1; e&lt;5; e++) //表示英国人的房子序号<br> for (int r=1; r&lt;5; r++)//表示瑞典人的房子序号<br> for (int d=1; d&lt;5; d++)//表示丹麦人的房子序号<br> for (int g=0; g&lt;5; g++)//表示绿房子的序号<br> for (int p=0; p&lt;5; p++)//表示抽Pall Mall牌香烟的人的房子序号<br> for (int y=0; y&lt;5; y++)//表示黄色房子的序号<br> for (int b=0; b&lt;5; b++)//表示喝啤酒人的房子序号<br> for (int h=0; h&lt;5; h++)//表示养马的人的房子序号<br> for (int cat=0; cat&lt;5; cat++)//表示养猫的人的房子序号<br> {<br>  int Germany = 10 - 0 - e - r - d; //表示德国人的房子序号,德国人抽Prince牌香烟；<br>  int Blends = 10 - p - y - b - Germany;//表示抽Blends牌香烟的人的房子序号<br>  int white = 10 - 1 - e - g - y; //表示白房子的序号<br>  int water = 10 - 2 - d - g - b; //表示喝矿泉水的人的房子序号<br>  int fish = 10 - r - p - h - cat;//表示养鱼的人的房子序号<br>  <br>  bool A1 = (e!=1); //英国人住在红色的房子里；根据房子和国家判断 <br>  bool A2 = (r!=e); //瑞典人养狗作为宠物；根据国家和宠物判断 <br>  bool A3 = (d!=e &amp;&amp; d!=r &amp;&amp; d!=2);//丹麦人喝茶；根据国家和饮料判断<br>  bool A4 = (g!=1 &amp;&amp; g!=2 &amp;&amp; g!=e &amp;&amp; g!=d);//绿房子的主人喝咖啡；根据颜色和饮料判断<br>  bool A5 = (p!=r); //抽Pall Mall牌香烟的人养鸟；根据香烟和宠物判断<br>  bool A6 = (y!=e &amp;&amp; y!=1 &amp;&amp; y!=g &amp;&amp; y!=p);//黄色房子里的人抽Dunhill牌香烟；根据颜色和香烟判断 <br>  bool A7 = (b!=2 &amp;&amp; b!=d &amp;&amp; b!=g &amp;&amp; b!=p &amp;&amp; b!=y);//抽BlueMaster牌香烟的人喝啤酒；根据香烟和饮料判断<br>  bool A8 = (h!=r &amp;&amp; h!=p &amp;&amp; (h==y+1 || h==y-1));//养马的人和抽Dunhill牌香烟的人相邻,根据香烟和宠物判断<br>  bool A9 = (white == g + 1); //绿房子紧挨着白房子，在白房子的左边；<br>  bool A0 = (cat==Blends-1 || cat==Blends+1);//Blends牌香烟的人和养猫的人相邻；<br>  bool A11 = (water==Blends-1 || water==Blends+1);//抽Blends牌香烟的人和喝矿泉水的人相邻<br>  <br>  if (A1 &amp;&amp; A2 &amp;&amp; A3 &amp;&amp; A4 &amp;&amp; A5 &amp;&amp; A6 &amp;&amp; A7 &amp;&amp; A8 &amp;&amp; A9 &amp;&amp; A0 &amp;&amp; A11)<br>  {//把满足条件的序号填入结构数组 <br>   House[e].nation = &quot;英国&quot;;<br>   House[e].color = &quot;红色&quot;;<br>   House[r].nation = &quot;瑞典&quot;;<br>   House[r].pet = &quot;狗&quot;;<br>   House[d].nation = &quot;丹麦&quot;;<br>   House[d].drink = &quot;茶&quot;;<br>   House[g].color = &quot;绿色&quot;;<br>   House[g].drink = &quot;咖啡&quot;;<br>   House[p].cigarette = &quot;Pall Mall&quot;;<br>   House[p].pet = &quot;鸟&quot;;<br>   House[y].color = &quot;黄色&quot;;<br>   House[y].cigarette = &quot;Dunhill&quot;;<br>   House[b].cigarette = &quot;BlueMaster&quot;;<br>   House[b].drink = &quot;啤酒&quot;;<br>   House[h].pet = &quot;马&quot;;<br>   House[Germany].nation = &quot;德国&quot;;<br>   House[Germany].cigarette = &quot;Prince&quot;;<br>   House[Blends].cigarette = &quot;Blends&quot;;<br>   House[white].color = &quot;白色&quot;;<br>   House[water].drink = &quot;矿泉水&quot;;<br>   House[cat].pet = &quot;猫&quot;;<br>   House[fish].pet = &quot;鱼&quot;;  <br>   <br>   goto end;<br>  }<br> }<br>end:<br> for (int i=0; i&lt;5; i++)<br>  cout &lt;&lt; Title[i] &lt;&lt; &quot;\t&quot;;<br> cout &lt;&lt; endl &lt;&lt; endl;<br> <br> for (i=0; i&lt;5; i++)<br> {<br>  cout &lt;&lt; House[i].nation &lt;&lt; &quot;\t&quot;; <br>  cout &lt;&lt; House[i].color &lt;&lt; &quot;\t&quot;; <br>  cout &lt;&lt; House[i].pet &lt;&lt; &quot;\t&quot;; <br>  cout &lt;&lt; House[i].drink &lt;&lt; &quot;\t&quot;; <br>  cout &lt;&lt; House[i].cigarette &lt;&lt; &quot;\t&quot;; <br>  cout &lt;&lt; endl;<br> }<br> //输出到文件 <br> ofstream out(&quot;爱因斯坦的思考题.txt&quot;);<br> for (i=0; i&lt;5; i++)<br>  out &lt;&lt; Title[i] &lt;&lt; &quot;\t&quot;;<br> out &lt;&lt; endl &lt;&lt; endl;<br> <br> for (i=0; i&lt;5; i++)<br> {<br>  out &lt;&lt; House[i].nation &lt;&lt; &quot;\t&quot;; <br>  out &lt;&lt; House[i].color &lt;&lt; &quot;\t&quot;; <br>  out &lt;&lt; House[i].pet &lt;&lt; &quot;\t&quot;; <br>  out &lt;&lt; House[i].drink &lt;&lt; &quot;\t&quot;; <br>  out &lt;&lt; House[i].cigarette &lt;&lt; &quot;\t&quot;; <br>  out &lt;&lt; endl;<br> }<br> out.close();<br> <br>   system(&quot;pause&quot;); <br>   return 0;<br>}<br><br><br>这是看得懂的实现<img src ="http://www.cppblog.com/hainan/aggbug/20769.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hainan/" target="_blank">Hainan's CppBlog</a> 2007-03-28 15:02 <a href="http://www.cppblog.com/hainan/archive/2007/03/28/20065.html#20769#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>re: 世界上最难的一道题！</title><link>http://www.cppblog.com/hainan/archive/2007/03/20/20065.html#20220</link><dc:creator>pengkuny</dc:creator><author>pengkuny</author><pubDate>Tue, 20 Mar 2007 08:16:00 GMT</pubDate><guid>http://www.cppblog.com/hainan/archive/2007/03/20/20065.html#20220</guid><description><![CDATA[Introduction<br>I found this interesting puzzle in Manfred Becker's article Einstein's riddle solved in C++. So I rushed to run his code for an easy answer. However several minutes had passed without a solution on the screen before I had to quit it, and went back to the source code for a clue. And I found a time table that states it takes 2 days 19 hours 24 minutes on a 700MHz Pentium III!<br><br>Although I understand that Becker's solution is just to demonstrate object oriented design, I think it would be better to have a fast solution for our impatient guys.<br><br>Here is a copy of the problem for easy reference and for the sake of completeness:<br><br>Einstein's riddle<br>There are 5 houses in five different colors in a row. <br>In each house lives a person with a different nationality. <br>These five owners drink a certain type of beverage, smoke a certain brand of cigar and keep a certain pet. <br>No owners have the same pet, smoke the same brand of cigar or drink the same beverage. <br>The question is: Who owns the fish?<br>Einstein's hints<br>The Brit lives in the red house. <br>The Swede keeps dogs as pets. <br>The Dane drinks tea. <br>The green house is on the immediate left of the white house. <br>The green house's owner drinks coffee. <br>The person who smokes Pall Mall rears birds. <br>The owner of the yellow house smokes Dunhill. <br>The man living in the center house drinks milk. <br>The Norwegian lives in the first house. <br>The man who smokes Blends lives next to the one who keeps cats. <br>The man who keeps horses lives next to the man who smokes Dunhill. <br>The owner who smokes BlueMaster drinks beer. <br>The German smokes Prince. <br>The Norwegian lives next to the blue house. <br>The man who smokes Blends has a neighbor who drinks water. <br>Class Design Considerations<br>Einstein spoke of houses and persons. It seems natural that we need a class of houses (CHouse) and a class of persons (CPerson) as Becker did it this way. However, if you think a little more about the relationship between these classes, you will notice that they have a one to one relationship. People often talk about homeowners. So why don't we just have one class for them? Sure, we can do it by viewing a person as a owner of a house and treating a person as a property in a house as well :)<br><br> Collapse<br>enum Problem_Constants<br>{ <br>    COUNT_HOUSES = 5, <br>    COUNT_CATEGORIES = 5, <br>    COUNT_HINTS = 15,<br>    BITS_CatID = 3,<br>    COUNT_EXTENDED_CatID = 1 &lt;&lt; BITS_CatID  //  COUNT_EXTENDED_CatID = 8<br>};<br><br>// Property Category ID<br>enum CatID <br>{<br>    COLOR,<br>    NATIONALITY,<br>    BAVERAGE,<br>    CIGAR,<br>    PET<br>};<br><br>// Property Identifications<br>enum PropID<br>{<br>    BLUE       = (0 &lt;&lt; BITS_CatID) | COLOR,    <br>    GREEN      = (1 &lt;&lt; BITS_CatID) | COLOR,         <br>    RED        = (2 &lt;&lt; BITS_CatID) | COLOR,      <br>    WHITE      = (3 &lt;&lt; BITS_CatID) | COLOR,     <br>    YELLOW     = (4 &lt;&lt; BITS_CatID) | COLOR, <br><br>    BRIT       = (0 &lt;&lt; BITS_CatID) | NATIONALITY,   <br>    DANE       = (1 &lt;&lt; BITS_CatID) | NATIONALITY,        <br>    GERMAN     = (2 &lt;&lt; BITS_CatID) | NATIONALITY,   <br>    NORWEGIAN  = (3 &lt;&lt; BITS_CatID) | NATIONALITY, <br>    SWEDE      = (4 &lt;&lt; BITS_CatID) | NATIONALITY,  <br><br>    BEER       = (0 &lt;&lt; BITS_CatID) | BAVERAGE,<br>    COFFEE     = (1 &lt;&lt; BITS_CatID) | BAVERAGE, <br>    MILK       = (2 &lt;&lt; BITS_CatID) | BAVERAGE,<br>    TEA        = (3 &lt;&lt; BITS_CatID) | BAVERAGE,<br>    WATER      = (4 &lt;&lt; BITS_CatID) | BAVERAGE,<br><br>    BLENDS     = (0 &lt;&lt; BITS_CatID) | CIGAR,<br>    BLUEMASTER = (1 &lt;&lt; BITS_CatID) | CIGAR,<br>    DUNHILL    = (2 &lt;&lt; BITS_CatID) | CIGAR,<br>    PALLMALL   = (3 &lt;&lt; BITS_CatID) | CIGAR,<br>    PRINCE     = (4 &lt;&lt; BITS_CatID) | CIGAR,<br><br>    BIRD       = (0 &lt;&lt; BITS_CatID) | PET,<br>    CAT        = (1 &lt;&lt; BITS_CatID) | PET,<br>    DOG        = (2 &lt;&lt; BITS_CatID) | PET,<br>    FISH       = (3 &lt;&lt; BITS_CatID) | PET,<br>    HORSE      = (4 &lt;&lt; BITS_CatID) | PET<br>};<br><br>enum HouseID<br>{<br>    HOUSE0, HOUSE1, HOUSE2, HOUSE3, HOUSE4<br>};<br><br>class CHouse<br>{<br>private:<br>    enum <br>    {    <br>        // EMPTY is a flag to indicate a null property of any category.<br>        // Its value must not be equal to any<br>        // real property (any element of PropID).<br>        EMPTY  = (0 &lt;&lt; BITS_CatID) | PET + 1<br>    };<br><br>    PropID m_property[COUNT_CATEGORIES];<br><br>// constructor<br>public:<br>    CHouse() <br>    {<br>        for (int i = 0; i &lt; COUNT_CATEGORIES; i++)<br>            m_property[i] = EMPTY;<br>    }<br><br>// operations<br>public:<br>    int IsEmpty(CatID cid)          { return m_property[cid] == EMPTY; }<br>    int IsEmpty(PropID pid)         { return IsEmpty(GetCatID(pid)); }<br>    int GetPropIndex(CatID cid)     { return GetIndex(m_property[cid]); }<br>    void SetProperty(PropID pid)    { m_property[GetCatID(pid)] = pid; }<br>    void ClearProperty(PropID pid)  { m_property[GetCatID(pid)] = EMPTY;}<br><br>private:<br>    CatID GetCatID(PropID pid)  <br>      { return (CatID) (pid &amp; (COUNT_EXTENDED_CatID - 1)); }<br>    int GetIndex(PropID pid)    { return pid &gt;&gt; BITS_CatID; }<br>};<br>Simple as it is, isn't? CHouse has only one data member m_property that is an array indexed by category (CatID) and used to hold the 5 properties. A CHouse object is self-contained, which knows nothing about its neighbors. We all know that a dog is a pet and beer is beverage. To please its users, CHouse understands this type-of relation by means of its member function GetCatID(PropID pid) and the composite definition of PropID.<br><br>Let's move to the other part of the problem, the hints, which describe the associations of properties and owners. We need a class to represent the hints. I bet, you will notice that the hints vary considerably at a glance. It is obvious that we will not end up with a simple uniform class like CHouse. Well, we will attack these variations by abstraction and derivation.<br><br>So what are in common, in all the hints? They all have to do with at least one property and one possible owner of the property. Therefore we name a base class CHint for the hints, and make it have two data members m_pid0 and m_pNewOwner, to represent the property and the possible owner. A CHint object also needs access to any CHouse object because the property (m_pid0) in it can be owned by any house owner that meets the hint. We put an array of 5 CHouse objects in CHint as a static data member. Before we continue with CHint method members, take a look at its blue print:<br><br> Collapse<br>class CHint<br>{<br>protected:<br>    const PropID m_pid0;  // a property in the hint<br>    CHouse* m_pNewOwner0; // ptr to a would-be owner<br>                          // of the property to meet the hint<br>    CHouse* m_pNext;      // the next house to be checked and filled<br><br>    static CHouse house[COUNT_HOUSES]; // array of the houses<br>private:<br>    // array of pointers to house owners indexed by PropID<br>    static CHouse* propowner[COUNT_CATEGORIES*COUNT_EXTENDED_CatID];<br>    static int count_solutions; // count of solutions found<br><br>// constructor<br>protected:<br>    CHint(PropID pid0) : m_pid0(pid0) {}<br><br>public:<br>    // starting from house specified by m_pNext, seek and assign the <br>    // first eligible houseowner(s) with properties. <br>    //<br>    // return value:<br>    //       0 : failed    <br>    // nonzero : successful<br>    //<br>    virtual int AssignPropToNextEligibles() = 0;    <br><br>    // undo AssignPropToNextEligibles<br>    virtual void RemovePropFromPrevEligibles() = 0;<br>    // reset the seek to start position<br>    virtual void ResetSeekPosition() = 0;<br>    // print out a solution<br>    static  void PrintOut();<br><br>// helpers<br>protected:<br>    void RemoveProperty();   // remove property from new owner<br>    int AssignPropertySetNextPos(CHouse* p0, CHouse* pNext);<br><br>// property register operations<br>protected:<br>    static CHouse* GetPropertyOwner(PropID pid) <br>                     { return propowner[pid]; }<br>    static void RegisterOwnership(PropID pid, CHouse* pOwner) <br>    {    <br>        propowner[pid] = pOwner;<br>    }<br><br>// counter<br>public:<br>    static int GetSolutionCount()  { return count_solutions; };<br>private:<br>    static void IncSolutionCount() { count_solutions++; };<br><br>// helper<br>    // verify a solution and check for errors<br>    static CHouse* VerifyCurrentSolution();<br>};<br>There are three pure virtual functions in it, that make CHint an abstract class. Just as a CHouse object knows nothing about its neighbors, a CHint object should know nothing about other CHint objects, in order to keep things simple. But a CHint object should have a method of finding all possible houses that meet the requirements of the hint. It is not necessary that the method returns a list of all possible house owners at a time. Instead, we want it find one house owner (m_pNewOwner) for its property (m_pid0) at a time, in an order. This can deliver better overall efficiency due to less memory traffic. These three virtual functions come in to fill the bill.<br><br>AssignPropToNextEligibles() finds the next matching house owner and assigns the property to him. Data member m_pNext is used to keep AssignPropToNextEligibles() knowing where to resume its work. <br>RemovePropFromPrevEligibles() is used to undo the property assignments made by AssignPropToNextEligibles() so that we can call AssignPropToNextEligibles() again to find yet another owner. <br>The last virtual function ResetSeekPosition() is an interface to reset the seek to its start position. <br>Those pure virtual functions can be viewed as place holders and specifications. Any class derived from CHint still has to implement these three functions.<br><br>The static data member propowner and its functions GetPropertyOwner and RegisterOwnership are included in CHint for easy access to the owner of any property. The data member and these 2 functions are an implementation of a property ledger so that we can avoid doing a linear search every time we need to know who owns a specific property.<br><br>The static functions VerifyCurrentSolution and PrintOut that verifies and prints out a solution respectively, are quite foreign to the CHint class from a concept point of view. I include them here simply because they also need access to the 5 houses. If I were a fundamentalist in OOP design, I would probably kick them out and give them a read only service instead.<br><br>Now we can derive classes from CHint. Hint 8 and 9 deal with only one property that the base class already provides. But each of them has a known house number. So we define the class this way:<br><br>// class for any hint of Known house number<br>//<br>class CKnownHouseHint : public CHint<br>{<br>private:<br>    CHouse* const m_pKnownHouse;<br><br>public:<br>    CKnownHouseHint(HouseID i, PropID pid) : <br>        CHint(pid), m_pKnownHouse(&amp;house[i]) {}<br><br>private:<br>    virtual int AssignPropToNextEligibles();    <br>    virtual void ResetSeekPosition()           { m_pNext = m_pKnownHouse; }<br>    virtual void RemovePropFromPrevEligibles() { RemoveProperty(); }<br>};<br>The rest of the hints involve two properties that can be owned by different owners. We reflect this difference by deriving a CMultiPropertiesHint class:<br><br>// class for any hint that involves Multiple properties<br>//<br>class CMultiPropertiesHint : public CHint<br>{<br>protected:<br>    // a property in the hint<br>    const PropID m_pid1;<br>    // ptr to a would-be owner of the property to meet the hint<br>    CHouse* m_pNewOwner1;<br><br>// implementations<br>protected:<br>    virtual void RemovePropFromPrevEligibles();<br><br>// constructor<br>protected:<br>    CMultiPropertiesHint(PropID pid0, <br>      PropID pid1) : CHint(pid0), m_pid1(pid1) { }<br><br>// helpers<br>protected:<br>    void ResetSeekPositionToFirstHouse() { m_pNext = &amp;house[HOUSE0]; }<br>    int AssignPropertiesSetNextPos(CHouse* p0, CHouse* p1, CHouse* pNext);<br>};<br>CMultiPropertiesHint is still an abstract base class for further derivations, though it provides some useful services.<br><br>Some hints only deal with a single house owner, hint 1 for example. CSingleHouseHint is derived from CMultiPropertiesHint for those hints:<br><br>// class for the any hint that only involves a Single houseowner<br>//<br>class CSingleHouseHint : public CMultiPropertiesHint<br>{<br>// constructor<br>public:<br>    CSingleHouseHint(PropID pid0, <br>      PropID pid1) : CMultiPropertiesHint(pid0, pid1) { }<br><br>// implementations<br>private:<br>    virtual int AssignPropToNextEligibles();    <br>    virtual void ResetSeekPosition() { ResetSeekPositionToFirstHouse(); }<br>};<br>Some hints deal with two house owners, hint 15 for instance. CNeighborsHint is derived from CMultiPropertiesHint for those hints:<br><br>// class for any hint that involves<br>// 2 Neighbors without a directional restriction<br>//<br>class CNeighborsHint : public CMultiPropertiesHint<br>{<br>private:<br>    int m_NextReverse; // are the properties to be filled in reverse order?<br><br>// constructor<br>public:<br>    CNeighborsHint(PropID pid0, <br>      PropID pid1) : CMultiPropertiesHint(pid0, pid1) { }<br><br>// implementations<br>private:<br>    virtual int AssignPropToNextEligibles();    <br>    virtual void ResetSeekPosition()        <br>    { <br>        ResetSeekPositionToFirstHouse(); <br>        m_NextReverse = 0;<br>    }<br>};<br>Hint 4 also talks about two houses. But the houses should be in a sequential order. We have only one instance of this kind, yet we have to derive a class for it to complete CHint class family:<br><br>// class for any hint that involves<br>// 2 Neighbors Ordered by direction<br>//<br>class COrderedNeighborsHint : public CMultiPropertiesHint<br>{<br>// constructor<br>public:<br>    COrderedNeighborsHint(PropID pid0, <br>      PropID pid1) : CMultiPropertiesHint(pid0, pid1) {}<br><br>// implementations<br>private:<br>    virtual int AssignPropToNextEligibles();    <br>    virtual void ResetSeekPosition() { ResetSeekPositionToFirstHouse(); }<br>};<br>I skip the implementations of these classes here. You can find them in the source file.<br><br>Since the riddle now can be well represented by a set of CHint objects and a set of CHouse objects, let's start to crack the puzzle by defining a class CSolver:<br><br>// class for finding the solutions<br>//<br>class CSolver<br>{<br>private:<br>    static CHint* hint[COUNT_HINTS]; // array of pointers to CHint objects<br>    static int count_nodes; // count of nodes searched<br><br>// operations<br>public:<br>    static void DoTheWork(); // search driver<br><br>// helpers<br>private:<br>    static void Search(CHint** ppCHint); // search engine<br>    static void PrintEinsteinRiddleDescription();<br>    static void IncNodeCount() { count_nodes++; };<br>    static int GetNodeCount() { return count_nodes; };<br>};<br>CSolver encapsulates those 15 hints in a static array of pointers to CHint objects. In the implementation file, we simply create these objects and initialize the array in a single step:<br><br> Collapse<br>// Array of pointers to CHint objects, i.e. a list of hints.<br>//<br>CHint* CSolver::hint[COUNT_HINTS] = <br>{<br>    new CSingleHouseHint(BRIT, RED),                // Hint 1<br>    new CSingleHouseHint(SWEDE, DOG),               // Hint 2<br>    new CSingleHouseHint(DANE, TEA),                // Hint 3<br>    new COrderedNeighborsHint(GREEN, WHITE),        // Hint 4<br>    new CSingleHouseHint(GREEN, COFFEE),            // Hint 5<br>    new CSingleHouseHint(PALLMALL, BIRD),           // Hint 6<br>    new CSingleHouseHint(YELLOW, DUNHILL),          // Hint 7<br>    new CKnownHouseHint(HOUSE2, MILK),              // Hint 8<br>    new CKnownHouseHint(HOUSE0, NORWEGIAN),         // Hint 9<br>    new CNeighborsHint(BLENDS, CAT),                // Hint 10<br>    new CNeighborsHint(HORSE, DUNHILL),             // Hint 11<br>    new CSingleHouseHint(BLUEMASTER, BEER),         // Hint 12<br>    new CSingleHouseHint(GERMAN, PRINCE),           // Hint 13<br>    new CNeighborsHint(NORWEGIAN, BLUE),            // Hint 14<br>    new CNeighborsHint(BLENDS, WATER)               // Hint 15<br>};<br>Now CSolver can work with pointers to CHint objects and forget about the differences among those objects. CSolver has a single public interface function DoTheWork(), which will be called by the main() function. DoTheWork() will delegate the real work to the Search function.<br><br>Brutal Search<br>Here is a simplified version of the exhaustive Search function:<br><br>void CSolver::Search(int index_of_hint)<br>{<br>    <br>    hint[index_of_hint]-&gt;ResetSeekPosition(); // reset to start position.<br><br>    // seek each set of eligibles &amp; assign<br>    // properties to them if needed.<br>    while (hint[index_of_hint]-&gt;AssignPropToNextEligibles()) <br>    {<br><br>        if (index_of_hint != 15 - 1) // if the hint is not the last one.<br>            Search(index_of_hint + 1); // search with next hint.<br>        else  // all hints have been met.<br>            CHint::PrintOut(); // a solution has been found.<br>        // undo the assign operations.<br>        hint[index_of_hint]-&gt;RemovePropFromPrevEligibles();<br>    }<br>}<br>As you see, Search is a recursive function. It tries to find a match for the current hint. If it has found one, it then calls itself with the next hint, provided that the current hint is not the last one where it prints a solution, and continues the search. If it has finished finding all possible matches or it has failed finding any match for the current hint, it returns the control to the previous hint.<br><br>DoTheWork() will make the first call with index_of_hint = 0.<br><br>Performance<br>It takes 0.016 seconds on a 1.6GHz P4 and 0.056 seconds on a 166Mhz Pentium MMX, when the standard clock() were used to do the timing in a previous version.<br><br>The current version uses high resolution performance counters to get more accurate results. However, different runtime sessions still showed quiet big variations of time. A little profiling work indicated, the program spends more than 80% of its time in printing out a solution! I had to optimize the drawing code a little bit in order to reduce the variations. After these tweaks, it takes only 0.0014 seconds on a 2.60GHz P4.<br><br>It is much faster than I had expected anyways. Now I think an old 8086 can easily crack the riddle too. Unfortunately, I could not find one.<br><br>Update<br>It would be interesting if we could gain some insight into the puzzle by playing with the program. Here are some:<br><br>Hint 15 is proved to be redundant because exactly the same solution is produced after it is commented out in the hint list. We can also leave out Hint 5 to make it more challenging for those who prefer pencils and papers.<br><br>Some tweaks in Version 1.04 (12/23/2003) makes it easier to add or delete hints in the list.<br><br><img src ="http://www.cppblog.com/hainan/aggbug/20220.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hainan/" target="_blank">pengkuny</a> 2007-03-20 16:16 <a href="http://www.cppblog.com/hainan/archive/2007/03/20/20065.html#20220#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>re: 世界上最难的一道题！</title><link>http://www.cppblog.com/hainan/archive/2007/03/19/20065.html#20135</link><dc:creator>Hainan's CppBlog</dc:creator><author>Hainan's CppBlog</author><pubDate>Mon, 19 Mar 2007 05:23:00 GMT</pubDate><guid>http://www.cppblog.com/hainan/archive/2007/03/19/20065.html#20135</guid><description><![CDATA[答对啦！<img src ="http://www.cppblog.com/hainan/aggbug/20135.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hainan/" target="_blank">Hainan's CppBlog</a> 2007-03-19 13:23 <a href="http://www.cppblog.com/hainan/archive/2007/03/19/20065.html#20135#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>re: 世界上最难的一道题！</title><link>http://www.cppblog.com/hainan/archive/2007/03/18/20065.html#20098</link><dc:creator>小豆子</dc:creator><author>小豆子</author><pubDate>Sun, 18 Mar 2007 14:20:00 GMT</pubDate><guid>http://www.cppblog.com/hainan/archive/2007/03/18/20065.html#20098</guid><description><![CDATA[德国人养鱼<img src ="http://www.cppblog.com/hainan/aggbug/20098.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hainan/" target="_blank">小豆子</a> 2007-03-18 22:20 <a href="http://www.cppblog.com/hainan/archive/2007/03/18/20065.html#20098#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>