Archive for the 'Ruby' Category

用 Ruby 查找 workspace 里 project 的依赖关系

2008-2-14 21:57 | by 2ndboy

  用 VC 6 做开发,项目一大起来,workspace 里 project 间的依赖关系就比较复杂,尤其是历史比较长,上手的人比较多的项目,之前用 PHP 实现了一个查找 VC 6 项目依赖关系的程序,但是总感觉别人用起来准备环境不太方便,于是假期里用 Ruby 重新实现了一遍。

  1. if ARGV.length <= 0
  2.      print 'Please enter filename of DSW: '
  3.      dsw = Kernel.gets.rstrip
  4.  elsif ARGV.length >= 1
  5.      if '-h' == ARGV[0] || 'help' == ARGV[0] || '--help' == ARGV[0]
  6.          puts 'Usage: ruby ' + $0 + ' dsw_filename'
  7.          exit
  8.      else
  9.          dsw = ARGV[0]
  10.      end
  11.  end
  12.  
  13.  rePath     = Regexp.new( '(.*(?:/|\\\\)).*' )
  14.  reProject  = Regexp.new( 'Project: "([^"]*)"="?([^"]*)"? - ' )
  15.  reTargType = Regexp.new( '# TARGTYPE ".*" 0x(\d+)' )
  16.  reConfig   = Regexp.new( '"\$\(CFG\)" == "[^"]* - Win32 ([^"]*)"' )
  17.  reOut      = Regexp.new( '/out:"[^"]*(?:/|\\\\)([^"]*\.[^"]*)"' )
  18.  reLink     = Regexp.new( '# ADD LINK32 ([^/]*)' )
  19.  
  20.  mdPath = rePath.match( dsw )
  21.  if nil != mdPath
  22.      basePath = mdPath[1]
  23.  end
  24.  
  25.  projects = Hash.new
  26.  
  27.  if !File.readable_real?( dsw )
  28.      puts "Can't open file - " + dsw
  29.      exit
  30.  end
  31.  
  32.  fileDsw = open( dsw, 'r' )
  33.  fileDsw.each_line{ |line|
  34.      mdProject = reProject.match( line )
  35.      if nil != mdProject
  36.          projectName = mdProject[1]
  37.          projects[projectName] = Hash.new
  38.          projects[projectName]['dsp']         = mdProject[2]
  39.          projects[projectName]['linkRelease'] = ''
  40.          projects[projectName]['linkDebug']   = ''
  41.  
  42.          config = ''
  43.          fileDsp = open( basePath + mdProject[2], "r" )
  44.          fileDsp.each_line{ |line|
  45.              mdTargType = reTargType.match( line )
  46.              if nil != mdTargType
  47.                  case mdTargType[1]
  48.                  when '0101'
  49.                      projects[projectName]['extName'] = '.exe'  # Win32 (x86) Application
  50.                  when '0102'
  51.                      projects[projectName]['extName'] = '.dll'  # Win32 (x86) Dynamic-Link Library
  52.                  when '0103'
  53.                      projects[projectName]['extName'] = '.exe'  # Win32 (x86) Console Application
  54.                  when '0104'
  55.                      projects[projectName]['extName'] = '.lib'  # Win32 (x86) Static Library
  56.                  else
  57.                      puts mdTargType
  58.                  end
  59.                  projects[projectName]['outRelease'] = projectName.downcase + projects[projectName]['extName']
  60.                  projects[projectName]['outDebug']   = projects[projectName]['outRelease']
  61.                  next
  62.              end
  63.  
  64.              mdConfig = reConfig.match( line )
  65.              if nil != mdConfig
  66.                  config = mdConfig[1]
  67.                  next
  68.              end
  69.  
  70.              mdOut = reOut.match( line )
  71.              if nil != mdOut
  72.                  if 'Release' == config
  73.                      projects[projectName]['outRelease'] = mdOut[1].downcase
  74.                  else
  75.                      projects[projectName]['outDebug']   = mdOut[1].downcase
  76.                  end
  77.                  # next  # Can't call next here
  78.              end
  79.  
  80.              mdLink = reLink.match( line )
  81.              if nil != mdLink
  82.                  if 'Release' == config
  83.                      projects[projectName]['linkRelease'] = mdLink[1].downcase
  84.                  else
  85.                      projects[projectName]['linkDebug']   = mdLink[1].downcase
  86.                  end
  87.                  next
  88.              end
  89.          }
  90.          fileDsp.close()
  91.      end
  92.  }
  93.  fileDsw.close()
  94.  
  95.  projects.each{ |key, value|
  96.      if '.lib' == value['extName']
  97.          next
  98.      end
  99.  
  100.      out = ''
  101.      projects.each{ |key2, value2|
  102.          if value['linkDebug'].include?( value2['outDebug'] )
  103.              out += ( '    ' + key2 + ' - ' + value2['outDebug'] + "\n" )
  104.          end
  105.      }
  106.  
  107.      if !out.empty?
  108.          puts 'Project: ' + key + ' - ' + value['outDebug']
  109.          puts out
  110.      end
  111.  }

  核心的部分用正则表达式实现,现在总觉得越是在实用中尝试使用正则表达式就越能感受到它的强大!

Google Code Jam

2005-11-23 20:36 | by 2ndboy

  昨天在 Solidot.org 上看到 Google 要专程在中国举行一次 Code Jam 大赛,由于对 Google 举办的编程比赛会出什么题目比较感兴趣就去注册了一把。比赛平台用的是 TopCoder 开发的一个专门用于程序竞赛的 Java 程序,默认界面是黑色的,看起来比较 Cool!

  进入练习后的解题界面分上下两部分,上面是用英文描述的题目,下面是代码输入窗口,写好代码后可以点击下面的编译按钮进行编译,还可以用系统提供的测试用例测试程序。解题时有 4 种语言可选:Java、C++、C# 和 VB。从看到题目开始计时,到提交了编译通过的代码后计时停止。如果再次提交代码会减分,代码被别人的测试用例挑战成功也要减分(别人加分)。

  由于 12 月 12 号才开始第一轮选拔赛,所以现在只能看到 3 个练习题,都比较简单,想必正式的比赛是不会出这么简单的题目吧?!尤其是后几轮。最近都在抽时间看 Ruby,正好可以拿这个练练手:-)就用那个 250 分的题开刀吧,题目是这样的:给定一个 20×20 的字符矩阵,左上角坐标为 (0,0),初始方向向下。开始时矩阵中每个点的值都是“.”,输入数据是若干条指令,指令只有两种,“LEFT”和“FORWARD n”,“n”是步长。程序要按照给定的一系列指令在矩阵中 walk,最终的输出就是按照指令 walk 后留下的轨迹,走过的地方用“X”标记,测试用例可以保证不会走出这个矩阵的范围。我用 Ruby 写的程序如下:

  1. class DrawLines
  2.    def execute( commands )
  3.      direction = x = y = 0
  4.      result = []
  5.      for i in 0 ... 20
  6.        result.push( '.' * 20 )
  7.      end
  8.      commands.each{ | command |
  9.        if( "LEFT" == command )
  10.          direction = ( direction + 1 ) % 4
  11.        else
  12.          steps = command.split( ' ' )[1]
  13.          result[y][x] = 'X'
  14.          for i in 0 ... steps.to_i
  15.            case direction
  16.              when 0 then y += 1  # Down
  17.              when 1 then x += 1  # Right
  18.              when 2 then y -= 1  # Up
  19.              when 3 then x -= 1  # Left
  20.            end
  21.            result[y][x] = 'X'
  22.          end
  23.        end
  24.      }
  25.      return result
  26.    end
  27.  end

  这个比我用 C++ 写的代码短多了,Ruby 的 iterater 起了很大的作用!不过由于对 Ruby 还不太熟,很多方法还是要中间查文档才知道的:-)想要测试这段代码可以这样:

  1. ( (DrawLines.new).execute( [ "FORWARD 19", "LEFT", "FORWARD 19", "LEFT", "FORWARD 19", "LEFT", "FORWARD 19" ] ) ).each{ |item| print "#{item}\n" }