青蛙过河问题

我很早就看到这个问题(最早是在一款经典的解密类游戏里),玩法很简单:每只青蛙都可以向前或者越过前面的青蛙跳一格(跟小时候的六角玻璃弹子棋很像:)),直到全部跳到对面。

具体的编程就是简单的穷举法了,因为左右对称,所以有两种解法。直接上个Python代码:

Python语言: 青蛙过河
#!/usr/bin/env python
# -*- coding:UTF-8 -*-
# 计算青蛙跳石头过河问题:
# 每只青蛙可以向前跳一步到空的石头或越过前面的一只青蛙跳到石头
# 初始状态:>>>+<<<
# 最终状态:<<<+>>>
# +为空石头,>和<为方向相反的青蛙   

trace_stack = []

def recursive(frog_list, final_list):
    global trace_stack

    if frog_list == final_list:
        trace_stack.append(frog_list)
        return True

    index = frog_list.index(‘+’)

    # 空石头右边第一只
    if index+1 < len(frog_list):
        if frog_list[index+1] == ‘<‘:
            temp = frog_list[:]
            temp[index],temp[index+1] = temp[index+1],temp[index]
            if recursive(temp, final_list):
                trace_stack.append(frog_list)
                return True

        # 空石头右边第二只
        if index+2 < len(frog_list):
            if frog_list[index+2] == ‘<‘:
                temp = frog_list[:]
                temp[index],temp[index+2] = temp[index+2],temp[index]
                if recursive(temp, final_list):
                    trace_stack.append(frog_list)
                    return True

    # 空石头左边第一只
    if index1 >= 0:
        if frog_list[index1] == ‘>’:
            temp = frog_list[:]
            temp[index],temp[index1] = temp[index1],temp[index]
            if recursive(temp, final_list):
                trace_stack.append(frog_list)
                return True

        # 空石头左边第二只
        if index2 >= 0:
            if frog_list[index2] == ‘>’:
                temp = frog_list[:]
                temp[index],temp[index2] = temp[index2],temp[index]
                if recursive(temp, final_list):
                    trace_stack.append(frog_list)
                    return True

    return False

def main():
    global trace_stack
    frog_count = 3
    frog_str = ‘>’*frog_count + ‘+’ + ‘<‘*frog_count
    frog_list = [i for i in frog_str]
    final_list = frog_list[:]
    final_list.reverse()

    if recursive(frog_list, final_list):
        try:
            while True:
                line = trace_stack.pop()
                print “”.join(line)
        except:
            pass

if __name__ == “__main__”:
    main()

运行结果:

MVC学习

引言:

A Wise old computer scienist once said: Make your data structure smart and your code dump.

We need SMART Models, THIN Controllers, and DUMB Views.

最早用MVC还是在MFC中的文档视图框架,不过给人感觉比较繁琐,没怎么好印象。前几天无聊看了一下Python的Django框架,发现它采用了一种MTV(Model Template View)的框架,和MVC差不多。看来MVC使用很广泛,我顺便学习了一下好用在的项目中。

一般来说MVC中Controller控制数据流、Model存数据、View显示数据对应于数据的输入、处理和输出。Controller设计时要thin尽量简洁,Model则必须smart处理各种数据,View则尽可能dumb按部就班的显示Model的数据就可以了。

在C++中MVC可以用Observer观察者模式实现,只是Observer少了一个控制器Controller。在实际程序中Controller对应于鼠标键盘之类的处理,所以一个窗口类就可以搞定了。View的话在windows中就是Canvas之类的画布,每一个Canvas对应一个View。实际实现中,我用多个Canvas访问同一个Model,操作起来好像windows的远程控制界面一样:)。最后也是最重要的就是Model了,简单点的应用一个数据结构就够了,如果复杂的话就要考虑数据库了。

我自己写的程序中Model试着采用Sqlite3数据库,但是每次操作Model都要频繁的访问硬盘,把我的硬盘弄的咔咔响。一般数据库出现这种情况,就要考虑用事务处理插入或修改记录,但现在操作Model却是随机的,所以事务用不着。最后只好用Sqlite3的内存数据库,程序启动时把硬盘中的数据库文件导入内存,程序退出时再保存到硬盘中。

最后补充一点:Sqlite3导入内存数据库时要注意Page size要设置成跟硬盘中的一样,关于Sqlite3用起来还真不错,看来数据库也要好好学一下。

参考:

wiki

阮一峰:谈谈MVC模式

Model-View-Controller

Model View Controller

图片里隐藏文件技术

今天同事孙工传给我一张特殊的图片,用压缩文件打开这张图片发现里面还隐藏着一个txt文档。其实图片隐藏文件有很多方法,可以参考这篇文章,同事用到的就是上面提到的第一种方法–尾部追加法:把压缩文件加到图片末尾,解压直接用解压软件打开图片。

在Windows下敲命令: copy /b A.JPG + B.zip C.JPG,结果如下:

我大致看了一下zip的文件头,头两个字节Ascii为”PK”(估计是pkzip的缩写吧),估计zip通过”PK”定位文件开始,丢掉之前的所有数据,不过貌似这样做有点风险。

简单网络库SimpleNet

我一直想找一个简洁好用的C++网络库,看了一些有名的库比如:POCO、libevent、C++ Socket Libary、ZMQ、Etwork、Boost的ASIO,要么太复杂难用要么功能太少。我实在不行就自己仿照Etwork写了一个取名SimpleNet,只实现了简单的TCP服务器和客户端功能,简洁就是美啊:)。

话说网络库看多了也就那么回事,如果不考虑性能之类而且只实现基本功能的话,也就是操作Socket、listen、bind,然后Select死循环,如果考虑异步的话加个线程搞定。但实际实现起来的话也要考虑很多细节问题。

首先当然是网络模型,在Windows下那就是Select了,话说IOCP这货估计很难搞定(libenvent好像还不支持)。

接下来就是怎么管理连接Session了,如果每个Session都开个线程的话互相通信起来比较麻烦,适合于提供单独的服务(例如HTTP服务器)。这里就直接搞个Map由Session管理器管理。

看到Etwork上的Session扩展是通过Notify类接口实现,这个具体应用其他估计很麻烦不如直接扩展Session来到快。创建Session就用那个工厂方法,顺便复习一下设计模式,最后出来的UML图就变这样了:

代码在Google Code的trunkProjectSimpleNet下Code,附带了一个SimpleNet实现的聊天室实现:)。