Fralcon
Fralcon

Reputation: 489

How can I get this condition met for a loop that changes a string to end?

I'm comparing a word against another string, which is changing by looping through the alphabet and inserting each letter at every position of the word.

@position_counter = 0

EDIT: Here is the code that letter_loop is running through.

@array = ["amethod", "variable", "block"]

def word_list_loop
  @match_counter = 0
  @array.each do |word|
    letter_loop(word)
  end
  puts @match_counter
end

CLOSE EDIT

def letter_loop(word)
  ("a".."z").each do |letter|
     word_plus_letter = @word.dup
     word_plus_letter.insert(@position_counter, letter)
     @match_counter+=1 if word.match(/\A#{word_plus_letter}\z/)
  end
  @position_counter+=1
  letter_loop(word) unless @position_counter == (@word.length + 1) 
end

The word I'm using for the argument is "method". But when I run this, I am getting a index 7 out of string (IndexError). Its looping through the alphabet for each position correctly, but it doesn't seem to get caught with the unless @position_counter == (@word.length + 1) to end.

I've tried a few other ways, with an if statement, etc, but I'm not able to get the method to complete itself.

Upvotes: 1

Views: 105

Answers (2)

mgibsonbr
mgibsonbr

Reputation: 22007

How many times are you running letter_loop? Are you sure the error happens in the first run? From what I see, if you call it a second time without resetting @position_counter to zero, it will begin with @word.length + 1 producing the exact error you see. Other than that, I couldn't find any problems with your code (ran just fine here on the first run).

Update: since you're using a recursive solution, and position_counter does not represent the state of your program (just the state of your method call), I'd suggest not declaring it as @position_counter but as an optional parameter to your method:

def letter_loop(word, position_counter=0)
  ("a".."z").each do |letter|
     word_plus_letter = @word.dup
     word_plus_letter.insert(position_counter, letter)
     @match_counter+=1 if word.match(/\A#{word_plus_letter}\z/)
  end
  position_counter+=1
  letter_loop(word, position_counter) unless position_counter == (@word.length + 1) 
end

If you can't/don't want to do this, just reset it before/after each use, like I suggested earlier, and it will work fine:

@array.each do |word|
  @position_counter = 0
  letter_loop(word)
end

(though I wouldn't recommend this second approach, since if you forget to reset it somewhere else your method will fail again)

Upvotes: 1

Alex D
Alex D

Reputation: 30445

I think the problem is that you are calling letter_loop from within @array.each, but you don't reset @position_counter to zero on each iteration of the @array.each loop.

If that doesn't fix your problem, add something like this as the first line of letter_loop:

puts "letter_loop word=#{word}, position=#{@position_counter}, matches=#{@match_counter}"

Then run the program and examine the output leading up to the IndexError.

Upvotes: 0

Related Questions