2014-04-29 89 views
3

找到发生的数字符串中的我是新来的Ruby和solving IOI questions学习它。如何通过红宝石

样本输入文件的第一行是“O”的数目。如果它是1,那么它需要找到“IOI”,如果是2,则“IOIOI”等

第二个数字13讲述在第三行字符的数目。问题是找到'IOI'的发生次数。

下面的例子应该给4

我做的方法,使用if语句在一个while循环。但它给出了ioioi.rb:14: syntax error, unexpected keyword_end (SyntaxError)的错误。我在while循环中试图找到前3个字符是否相等,如果它是增加一个count。并删除第一个字符并重复该过程。

样品输入文件

1 
13 
OOIOIOIOIIOII 

输出应该是

4 

我班IOIOI

def self.frequency(file_name) 
    file = File.new(file_name, 'r').each_line.map(&:strip) 
    count = 0 
    o_str = file.shift # '1' 
    o_num = o_str.to_i 
    findme = "IO" * o_num + "I" 
    length = file.shift # '13' 
    input = file.join 
    while file.size > 0 do 
     if file[0..(2*o_num)].eql?(findme) 
     count += 
     end 
     file = file[1..-1] # delete the first letter 
    end 
    count 
    end 
+0

count + = 1,推测是 –

+0

在while语句后不需要''file = File.new(file_name,'r')。'each_line.map(&:strip)'' file = File.readlines(file_name)' – bjhaid

+0

这个IOI链接不幸对讲英语的人不利。什么是IOI问题? –

回答

1

您缺少的+=功能的说法,因此Ruby试图阅读下一行作为参数。相反,它得到if块的end - 但是count +=语句不完整,所以尚未准备好结束块。

2

@Kyle回答了你的问题。这是一种以类似Ruby的方式来实现它的方法。

编辑: @steenslag提出了两个很好的改进我的代码的建议,我很乐意采纳。我原本:

def countem(n, str) 
    target = ('IO'*n + 'I').split('') 
    str.split('').each_cons(2*n+1).reduce(0) {|tot,e| tot + (e==target ? 1 : 0)} 
end 

他的主要建议是,我使用count而非reduce,也以更直接的方式构建target。这些变化如下所示。

代码

的这里关键是要利用方法Enumerable#each_cons的:

def countem(n, str) 
    target = ['I','O']*n << 'I' 
    str.split('').each_cons(2*n+1).count { |e| e==target } 
end 

str = "OOIOIOIOIIOII" 
countem(1, str) #=> 4 
countem(2, str) #=> 2 
countem(3, str) #=> 1 

说明

n = 1 
str = "OOIOIOIOIIOII" 

target = ['I','O']*n << 'I' 
    #=> ["I", "O", "I"] 

a = str.split('') 
    #=> ["O", "O", "I", "O", "I", "O", "I", "O", "I", "I", "O", "I", "I"] 
b = a.each_cons(2*n+1) #=> a.each_cons(3) 
    #=> #<Enumerator: ["O", "O", "I", "O", "I", "O", "I", "O", 
    #     "I", "I", "O", "I", "I"]:each_cons(3)> 

要查看枚举的内容:

b.to_a 
    #=> [["O", "O", "I"], ["O", "I", "O"], ["I", "O", "I"], ["O", "I", "O"], 
    # ["I", "O", "I"], ["O", "I", "O"], ["I", "O", "I"], ["O", "I", "I"], 
    # ["I", "I", "O"], ["I", "O", "I"], ["O", "I", "I"]] 

最后,计数的b即等于target的元素:

b.count { |e| e==target } 
    #=> 4 
+0

谢谢@nsenslag。我最初尝试'计数',但有一个问题,所以切换到'减少'。我不知道我做错了什么,但是,“count”好得多。我会做出改变。 –

3

使用正则表达式:

def countem(n, str) 
    str.scan(/I(?=#{'OI' * n})/).size 
end 

p countem(1, 'OOIOIOIOIIOII') # => 4 
p countem(2, 'OOIOIOIOIIOII') # => 2 
p countem(3, 'OOIOIOIOIIOII') # => 1 
p countem(4, 'OOIOIOIOIIOII') # => 0 

正则表达式l ooks为“我”(并消耗它),然后使用正向预测匹配字符串的其余部分,以便它不被消耗。这使剩下的字符串可用于更多匹配。

+0

这很酷,韦恩。我从来没有想过用这种方式使用正则表达式。很好的解释。 –

+0

@Cary谢谢! –

+1

这是一个正则表达式最好的解决问题的完美例子。 –