现在主要在知乎,地址:https://www.zhihu.com/people/qqrrm 老的文章在:http://blog.csdn.net/pyp

发布新日志

  • 宋词分析改编版(ruby)

    2014-02-02 23:50:10

    很久之前写的了,在别的地方,blog多就总忘,还是在这里留一个备份吧。现在是ruby2.0版了,有时间还是应该重构一下。还有,我专门买了一个移动硬盘安装ubuntu,笔记本也用wubi安装了一个,所以现在主要在ubuntu下学习ruby,坑就少多了,大家也可以学习一下ruby。



    上一次我写的宋词分析,是在Windows环境下的,缺省编码是GBK(936),所以在处理UTF-8的时候,需要转换为GBK,再进行处理分析。 
        不过现在已经是ruby1.9版了,那么就改一下,在uft-8下处理程序,主要就是把原宋词文件内容从gbk编码为utf-8,再进行相应的处理,dos下需要chcp 65001转换为utf-8编码,再执行才可以看到正确结果,否则就是乱码。 
        我用的SciTE,在Options->Open Global Options File中,code.page=65001,output.code.page=65001去除前面的#,就可以正确处理utf-8文字了。 
        嗯,Windows就是麻烦,Linux和mac一直想玩玩,但是单位无法上网,需要联网的东西太费事了。 
        还有就是改写为utf-8版后,计数和gbk版的不同了,gbk版的,和原文的计数一致,utf-8版的,一是计数多了,二是很多后面的也提到了前面,不知道为什么,也许是gbk->utf-8转换的时候,一些文字出现问题了吧。 



    #coding: utf-8
    require "iconv"

    NUM1 = 2 #分词长度
    NUM2 =500  #显示大于多少的记录

    def splitword(s,l)    #分词,s是字符串,l是字符分词长度
      lt  = s.length
      k = Array.new
      0.upto(lt-l) do |i| 
        k<<s[i..i+l-1]
      end
      return k
    end

    t = Time.now

    x = Array.new     #记录分词结果的数组
    File.open("ci.txt", "r")  do |file|
      file.each do |line|    
        line = Iconv.conv("UTF-8//IGNORE","GBK", line)    
        line.chomp!
        column = line.split(/,|。|!|?|、/)          #使用标点分割
        column.delete_if {|i| i.length >10 }    #去除大于10个字的语句
        column.each do |col| 
          splitword(col,NUM1).each{|i| x<<i} if col.length>NUM1 # 分词
        end 
      end
    end

    h = Hash.new
    h = x.inject(Hash.new(0)){|hash,x| hash[x] += 1; hash} #把数组内容进行计数为hash
    h.delete_if {|key, value| value <NUM2}               #去除hash中小于指定数值的部分

    y = Array.new
    y  = h.sort {|a,b| b[1]<=>a[1]}                      # 从大到小排序
    y.each_index {|i| puts "#{i+1} #{y[i][0]} = #{y[i][1]}" }

    puts "运行时间是:"<<(Time.now-t).to_s<<"秒"
  • 花朵数(ruby)

    2011-12-28 17:53:55

    花朵数,也可以称之为水仙花数,水仙花数 一个N位的十进制正整数,如果它的每个位上的数字的N次方的和等于这个数本身,则称其为花朵数。比如153是3位数,那么1^3+5^3+3^3=153,所以153是水仙花数。
    其实我原先写过的,但是只是3位的,这次扩充到任意的位数,但实际上,7位数就要30秒了,8位数没有等到返回。
    大概就是3≤N≤7,而且没有比较好的方法可以优化此过程。

    #coding:utf-8

    N = 4

    (('1'<<'0'*(N-1)).to_i..('9'*N).to_i).each do |i|   #从10...到99... 循环
      n = 0.upto(N-1).inject(0) { |sum,j|  sum + i.to_s[j].to_i**N}  #N次方加和
      p i if n==i
    end

    优化一下:

    #coding: utf-8
    N = 6
    ('1'<<'0'*(N-1)..'9'*N).each do |i|
      n = 0.upto(N-1).inject(0) {|sum,j| sum + (i[j].to_i)**N }
      puts "#{N}"<<"位花朵数是:"<<"#{i}"  if n== i.to_i
    end

  • 蒙特卡洛方法求π值(ruby)

    2011-12-26 17:54:44

    就是在一个正方形里面随机投掷,看在圆内的数目是多少,可以求得PI值。

    #coding:utf-8

    N =999999   # 投掷次数
    sum = 0

    for i in 1..N
      x = rand()
      y = rand()
      sum+=1 if x*x+y*y<1
    end
     
     p 4*sum/N.to_f
  • 一道好玩的题(ruby)

    2011-12-26 17:51:36

    原文在http://www.cnblogs.com/BrainDeveloper/archive/2011/12/24/2300279.html

    有N个数,编号1到n。按照以下规则进行删除数,求最后剩下的那个数。【1<= n <= 1000000000】

    规则:

    1 . 如果当前序列的个数大于1,则删除所有序列中第平方数的位置的数。

    2. 将进行1操作剩下的数,重新排在一起,重复操作1,直接当前序列数为1个数时,这个数就是结果。


    #coding:utf-8     

    NUM =99999       #最大值

    a = (1..NUM).to_a

    def value(arr)      #去除平方位置的数
      for i in 1..Math.sqrt(NUM)
        arr[i*i-1] = nil
      end
      return arr.compact!
    end

    n = Time.now
    until a.length == 1  #算是递归吧
      value(a)  
    end
    p Time.new-n

    p a



  • 东风何处是人间(ruby版)

    2011-12-15 17:48:43

    在今年3月份的,就看到这个帖子《东风何处是人间》了,对宋词进行分词计数,当时就保存了这个帖子,想以后有时间写个ruby版的。后来就忘记了
    近期这个帖子大火啊,也终于抽出时间写ruby版的了。
    个人水平有限,程序写的很糟糕,至少比原文的看着复杂多了,不知道是否能有ruby高手给大家写个示例。

    数据:《全宋词》文本


    #coding: utf-8
    require "iconv"

    s1 = Iconv.conv 'gbk','utf-8',","
    s2 = Iconv.conv 'gbk','utf-8',"。"
    s3 = Iconv.conv 'gbk','utf-8',"!"
    s4 = Iconv.conv 'gbk','utf-8',"?"
    s5 = Iconv.conv 'gbk','utf-8',"、"

    NUM1 = 2  #分词长度
    NUM2 =500  #显示大于多少的记录

    def splitword(s,l)    #分词,x是字符串,l是字符分词长度
      lt  = s.length
      k = Array.new
      0.upto(lt-l) do |i|
        k<<s[i..i+l-1]
      end
      return k
    end

    x = Array.new     #记录分词结果的数组

    File.open("ci.txt","r") do |file|
      file.each do |line|
        if line.length<500 and line.length>10
          line.gsub!(s2,s1)     #把标点都替换为",",再统一进行分割
          line.gsub!(s3,s1)
          line.gsub!(s4,s1)
          line.gsub!(s5,s1)
          line.chomp!
          column = line.split(s1)       #用逗号分割
          column.delete_if {|i| i.length >10 } #去除大于10个字的语句
          column.each do |col|
            splitword(col,NUM1).each{|i| x<<i}  if col.length>=NUM1 # 分词
          end 
        end
      end
    end

    h = Hash.new
    h = x.inject(Hash.new(0)){|hash,x| hash[x] += 1; hash} #把数组内容进行计数为hash
    h.delete_if {|key, value| value <NUM2}               #去除hash中小于指定数值的部分

    y = Array.new
    y  = h.sort {|a,b| b[1]<=>a[1]}                      # 从大到小排序
    y.each_index {|i| puts "#{i+1} #{y[i][0]} = #{y[i][1]}" }
  • 张老师的生日问题(ruby版)

    2011-11-25 19:49:27

    一个烂大街的题,前两天刚好看到别人解这个题,用c++实现的,网上还有很多的java版的等等,我就改成了ruby版的,ruby版的程序算是比较短的了吧,还是有些函数式的影子,而不是纯粹的ruby化面向对象。

    小明和小强都是张老师的学生,张老师的生日是M月N日,2人都知道张老师的生日
      是下列10组中的一天,张老师把M值告诉了小明,把N值告诉了小强,张老师问他们知道他的生日是那一天吗?
      3月4日 3月5日 3月8日
      6月4日 6月7日
      9月1日 9月5日
      12月1日 12月2日 12月8日
      小明说:如果我不知道的话,小强肯定也不知道
      小强说:本来我也不知道,但是现在我知道了
      小明说:哦,那我也知道了
      请根据以上对话推断出张老师的生日是哪一天


    ruby版程序,就是按照条件排除,把数组内值非设定的都为nil,剩下的就是张老师的生日了。

    month = [3,3,3,6,6,9,9,12,12,12]  # 月份
    date = [4,5,8,4,7,1,5,1,2,8] #日期

    #单一日期对应月份的值全部设置为nil
    date.each_index do |i|           
      month.each_index { |j| date[j] = nil  if month[j] ==month[i]  }  if date.count(date[i]) == 1
    end  
      
    #剩余的日期,去掉重复的
    date.each do |i| 
      date.each_index { |j|  date[j] = nil if  i == date[j] }  if date.count(i) ==2
    end

    #把日期为nil的对应月份也设置为nil
    date.each_index do |i|
      month[i] = nil if date[i] == nil
    end
      
    #去掉重复的月份
    month.each do |i|   
      month.each_index { |j|  month[j] = nil if  i == month[j] } if month.count(i) ==2
    end

    #月份nil对应的日期为nil
    month.each_index do |i|
      date[i] = nil if month[i] == nil
    end

    #剩下的日期就是张老师的生日了。
    print "Teacher's birthday is #{month.compact[0]}-#{date.compact[0]}"


  • (2)米小国河内塔ruby版

    2010-07-08 15:35:42

    def hanoi(n, a, b, c)
       if(n == 1)
         p "盘" << n.to_s << " 由 " << a << " 移至 " << c
       else
         hanoi(n - 1, a, c, b)
         p "盘" << n.to_s << " 由 " << a << " 移至 " << c
         hanoi(n - 1, b, a, c)
       end
    end

    p "请录入盘数:"

    while ( n = gets().to_i ) <= 0
       p "请录入整数:"
       next
    end

    hanoi(n,'a','b','c')


    这个的难点在gets输入,当时写了很多次,感觉都不够简洁漂亮。这个也不算很满意,但是就这样吧,反正也只是练习。
    还有数字一定要记得to_s,否则就出现\001这样的内容了。
  • (1)米小国帕斯卡三角形ruby版

    2010-07-08 15:24:14

    米小国奇想世界》是一本很好的书,里面写了很多经典算法的实现,C或java版本的,我学习ruby的时候,也就用这里面的内容进行实习。
    对于开发我还是比较差的,没有当过程序员,只是有些学习的兴趣,所以代码写的滥的时候,大家提醒一声,呵呵。
    我用的InstantRails2.0,ruby 1.8.6-111,很老的版本了,只是要学习《Web开发敏捷之道--应用Rails进行敏捷Web开发》,否则就升到1.9版了,但是这也是无所谓的事情,我写代码也不至于用到新版本的特性。
    编译器用的NetBeans6.8,试用了几个不同的编译器,还是觉得在Windows下这个最好用。

    米小国帕斯卡三角形ruby版代码:

    def combi(n,r)
      p = 1
      for i in 1..r do
        p=p*(n-i+1)/i
      end
      p
    end

    N=19 #列数
    M=4  #间隔

    for m in 0..N do
      print " "*M*(N-m)
      for s in 0..m do
        print combi(m,s).to_s <<   " "*(2*M-combi(m,s).to_s.length)
      end
     
      print "\n"
    end


    代码没什么说的,很简单,其实写这段代码,我大部分的时间都花在如何更漂亮的输出上面了,呵呵。

Open Toolbar