2015-08-27 4 views
0

Я пытаюсь подсчитать количество подобных префиксных строк для строки в Ruby. например; ввод «ababaa» должен выводить 11;Вложенные петли в Ruby

ababaa = 6 
babaa = 0 
    abaa = 3 
    baa = 0 
    aa = 1 
    a = 1 

у меня, насколько ниже код, используя вложенный цикл, чтобы пройти через каждый из указанных выше как массив, но это выглядит, как будто рубин в настоящее время выводит количество только первого объекта Array, "ababaa".

Решено, спасибо :)

def string_suffix(string) 
num = 0 
ary = [] 
string.length.times do 
    ary << string[num..string.length] 
    num = num + 1 
end 
result = 0 
ary.each do |x| # ["ababaa", "babaa", "abaa", "baa", "aa", "a"] 
    x.chars.each_with_index do |c,index| 
    break unless c == string[index] 
     result = result + 1 
    end 
end 
return result 
end 

Я смотрел далеко и широко, и до сих пор не может решить эту проблему, он выглядит (окончательный, вложенная) массив разбивается после первой итерации «ary» Array и просто возвращает этот вывод.

+1

Вы назначили задание здесь: 'if x = string [count]'? Потому что '=' является присваиванием, а не проверяет равенство. Таким образом, выражение 'if' будет' true' в любое время, когда значение 'string [count]' является правдивым, что в любое время отличное от нуля. – lurker

+0

Нет, я этого не видел, спасибо. Результат все тот же, возвращая 6 – Harry

+1

Вы также каждый раз обнуляете «результат» через цикл 'ary.each'. Поместите 'result = 0' * перед *' ary.each ... '. Кажется, что 'num' не используется ни для чего после первого цикла, поэтому' num = 0' не требуется. – lurker

ответ

3

Вы возвращаете результат, пока находитесь в цикле. Вам необходимо переместить result = 0 из цикла и переместить оператор return result за пределы цикла. В настоящий момент функция проходит через первую итерацию цикла («ababaa», для которого все символы совпадают), но вы хотите, чтобы результат равнялся сумме всех результатов.

Кроме того, вместо того, чтобы делать:

count = 0 
x.chars.each do |x| 
    if x == string[count] 
     count = count + 1 
     result = result + 1 
    else 
     count = count + 1 
    end 
end 

Вы можете использовать функцию each_with_index, чтобы получить

x.chars.each_with_index do |c,index| 
    if c == string[index] 
     result = result + 1 
    end 
end 

Однако, поскольку вы пытаетесь подсчитать, сколько символов в подстроке являются префиксом строки, вы хотите сломать, когда вы сначала найдете символ c, который не равен строке [index], так что вы не закончите подсчет дополнительных символов. Затем петля становится:

x.chars.each_with_index do |c,index| 
    if c == string[index] 
     result = result + 1 
    else 
     break 
    end 
end 
+0

Блестяще, спасибо, хотя по какой-то причине в моей программе ваше второе предложение возвращается 13. – Harry

+0

См. Отредактированный вами комментарий по поводу изменения, которое я использовал. – Harry

+0

Это потому, что логика, которую вы используете, немного ошибочна, как объяснил lurker на комментарий к вашему вопросу. Вам нужно сломать, если c! = String [index], потому что тогда мы знаем, что больше не x является префиксом строки. Я добавлю его в свой ответ за вас. – JHobern

0

Я заметил, что вы возвращаете результат во второй цикл, в конце. Это означает, что после того, как вы пройдете первый элемент в своем массиве, функция возвращает только результат для первого элемента. Переместите оператор return вне цикла.

0

Как я понимаю, проблема заключается в следующем: дана строке s для каждого i = 0..s.size-1, вычислить число ведущих персонажей s[0..-i-1], которые соответствуют соответствующим символам (т.е. при тех же сдвиги) s[i..-1], и просуммировать эти s.size подытогов ,

Вот рубин, как способ сделать это, используя Enumerable#reduce (ака inject) и Enumerable#take_while:

str = "ababaa" 

arr = str.chars 
(0...arr.size).reduce(0) do |tot,i| 
    tot + arr[0..-i-1].zip(arr[i..-1]).take_while { |x,y| x == y }.size 
end 
    #=> 11 

Шаги:

arr = str.chars 
    #=> ["a", "b", "a", "b", "a", "a"] 
r = 0...arr.size 
    #=> 0...6 

Когда первый элемент r передается в блок, переменные блока:

tot = 0 
i = 0 

Расчет блока Поэтому следующим образом:

a = arr[0..-i-1].zip(arr[i..-1]) 
    #=> arr[0..-1].zip(arr[0..-1]) 
    #=> arr.zip(arr) 
    #=> ["a", "b", "a", "b", "a", "a"].zip(["a", "b", "a", "b", "a", "a"]) 
    #=> [["a", "a"], ["b", "b"], ["a", "a"], ["b", "b"], ["a", "a"], ["a", "a"]] 

b = a.take_while { |x,y| x == y } 
    #=> [["a", "a"], ["b", "b"], ["a", "a"], ["b", "b"], ["a", "a"], ["a", "a"]] 

tot + b.size 
    #=> 0 + 6 
    #=> 6 

Следует отметить, что этот расчет будет всегда равна arr.size для первого элемента arr переданного блока.

Когда следующий элемент arr передан блоку, переменная блока i установлена ​​в 1. tot, который мы только что вычислили, равно 6. Поэтому расчет блока составляет:

a = arr[0..-i-1].zip(arr[i..-1]) 
    #=> arr[0..-2].zip(arr[1..-1]) 
    #=> ["a", "b", "a", "b", "a"].zip(["b", "a", "b", "a", "a"]) 
    #=> [["a", "b"], ["b", "a"], ["a", "b"], ["b", "a"], ["a", "a"]] 

b = a.take_while { |x,y| x == y } 
    #=> [] 
tot + b.size 
    #=> 6 + 0 
    #=> 6 

Остальные вычисления аналогичны. После того, как все элементы arr были отправлены в блок, reduce возвращает значение tot.

Смежные вопросы