Deaf grandma doesn't allow me to leave until I say bye three times So, I'm working through Chris Pine's "learn to program" and I have been banging my head against the wall regarding the "deaf grandma" lesson. 

I think I got it.

I'm looking for advice regarding indentations, and/or structuring of the code to make it easier to read, for myself and others. 

Here's the premise:


  Write a Deaf Grandma program. 
  Whatever you say to grandma (whatever you type in), she should respond with HUH?! SPEAK UP, SONNY!, unless you shout it (type in all capitals). If you shout, she can hear you (or at least she thinks so) and yells back, NO, NOT SINCE 1938! To make your program really believable, have grandma shout a different year each time; maybe any year at random between 1930 and 1950. (This part is optional, and would be much easier if you read the section on Ruby's random number generator at the end of the methods chapter.) You can't stop talking to grandma until you shout BYE.
  
  Hint: Don't forget about chomp! 'BYE'with an Enter is not the same as 'BYE' without one! 
  
  Hint 2: Try to think about what parts of your program should happen over and over again. All of those should be in your while loop.
  
  Extend your Deaf Grandma program: What if grandma doesn't want you to leave? When you shout BYE, she could pretend not to hear you. Change your previous program so that you have to shout BYE three times in a row. Make sure to test your program: if you shout BYE three times, but not in a row, you should still be talking to grandma.


Here's my solution:

puts "say hi to grandma"

bye = 0

while bye &lt; 3 do
  input = gets.chomp

  if input == "BYE"
  bye = bye + 1
  puts "HEH?!"
  else
    if input == input.upcase
    bye = 0
    puts "NO, NOT SINCE " + rand(1930..1950).to_s + "!"
    else
    puts "HUH?! SPEAK UP SONNY!"
    bye = 0
    end
  end
end

puts "EH?! OH, BYE DEAR!"
There are a few small changes that I would make:


Indent the bodies of if/else blocks.
Moving the bye = 0 line to the top of the else block reduces code duplication, and it'll make your code more clear, because it will read like: 'if the input is "BYE", increase the 'bye' counter, else, reset it to 0'.
Ruby has a += operator: bye += 1 is shorthand for bye = bye + 1.
The name bye isn't very accurate, something like bye_shouts_in_a_row is probably better. Picking accurate, meaningful names is often difficult, but it can make code (much) easier to understand, and that makes working with it easier as well.


Applying these gives the following result:

puts "say hi to grandma"

bye_shouts_in_a_row = 0

while bye_shouts_in_a_row &lt; 3 do
  input = gets.chomp

  if input == "BYE"
    bye_shouts_in_a_row += 1
    puts "HEH?!"
  else
    bye_shouts_in_a_row = 0
    if input == input.upcase
      puts "NO, NOT SINCE " + rand(1930..1950).to_s + "!"
    else
      puts "HUH?! SPEAK UP SONNY!"
    end
  end
end

puts "EH?! OH, BYE DEAR!"