16
\$\begingroup\$

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 < 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!"
\$\endgroup\$
2
  • 2
    \$\begingroup\$ @DonQuiKong Arqade called - it wants its question title back. :-) \$\endgroup\$
    – hBy2Py
    Commented Aug 28, 2017 at 14:50
  • 1
    \$\begingroup\$ Quick tip: You can replace all that string concatenation and to_scalls with string interpolation like this: puts "NO, NOT SINCE #{rand(1930..1950)}!" \$\endgroup\$
    – daniero
    Commented Aug 28, 2017 at 16:23

2 Answers 2

17
\$\begingroup\$

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 < 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!"
\$\endgroup\$
4
  • 2
    \$\begingroup\$ Ack, camelCase Ruby :( \$\endgroup\$
    – ArtOfCode
    Commented Aug 28, 2017 at 13:09
  • \$\begingroup\$ @ArtOfCode: I haven't worked with Ruby in years, so I had to look up a style guide... but you're right, of course. \$\endgroup\$ Commented Aug 28, 2017 at 13:21
  • \$\begingroup\$ maybe bye_shouts_in_a_row ? \$\endgroup\$ Commented Aug 28, 2017 at 15:16
  • \$\begingroup\$ @JuanCarlosOropeza: good call, heh. \$\endgroup\$ Commented Aug 28, 2017 at 15:23
0
\$\begingroup\$
#I changed the code ever so slightly, but it does the same thing.

puts "Tell Grandmaw bye. Keep in mind that she is hard of hearing, and is 
lonely, so you need to be loud and you may even need to repeat yourself 
several times!"

counter = 0

while counter < 3 do
  user_input = gets.chomp

  if user_input == "BYE"
      counter += 1
      puts "HUH?!"
  elsif user_input == ""
      counter = 0
      puts "ARE YOU GOING TO  TALK?!"
  elsif user_input == user_input.upcase
      counter = 0
      random_year = rand(1930..1950).to_s
      puts "NO, NOT SINCE #{random_year} !"
  elsif user_input != user_input.upcase
      counter = 0
      puts "HUH?! SPEAK UP, SONNY!!"
  end
end
puts "Bye, dear!"

Instead of using else followed by a line-break and then using the if statement, you can just use the elsif statement, which combines the two. It's a minor thing, but it's slightly more "elegant". Usually I only use the else statement if the value is purely boolean rather than conditional. Also, I added in a line code that factors in if the users just presses enter (meaning they don't have any input at all) by using:

elsif user_input == ""
    puts "ARE YOU GOING TO TALK?!"
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.