Homework Review
Warmup Exercise
Write a program that asks the user for all U.S. states they have visited (followed by a return). Typing "done" should terminate the program. Print all states to the screen.
Warmup Solution:
Let's set up an empty array of visited states and prompt the user for input.
visited = []
puts "Enter all the states you've been to! Type 'done' when you're finished:"
Warmup Solution:
Get the states from the user, then check to see if they entered "done". If so stop collecting input, otherwise push to the visited array.
state = gets.chomp.upcase
if state != 'DONE'
visited.push(state)
end
Warmup Solution:
We need a loop to keep collecting states from the user. But...
keep_going = true
while keep_going
state = gets.chomp.upcase
if state != 'DONE'
visited.push(state)
end
end
Warmup Solution:
... we need a way to exit the loop. So set 'keep_going' to false when the user enters done.
keep_going = true
while keep_going
state = gets.chomp.upcase
if state != 'DONE'
visited.push(state)
else
keep_going = false
end
end
Warmup Solution:
Finally we need to print out the states the user has visited. We can either join a comma separated array...
puts "You have visited the following states:"
puts visited.join(', ')
visited.each do |state|
puts state
end
...or loop through and print each state.
Warmup Solution:
# Write a program that asks the user for all U.S. states they have visited
# (followed by a return)
# Typing "done" should terminate the program.
# Print all states to the screen.
visited = []
puts "Enter all the states you've been to! Type 'done' when you're finished:"
keep_going = true
while keep_going
state = gets.chomp.upcase
if state != 'DONE'
visited.push(state)
else
keep_going = false
end
end
puts "You have visited the following states:"
puts visited.join(', ')
Ruby Exercise:
Write a program that splits the class into teams of 2. If there's an odd number of students the last group should be a group of 3.
Jaime's Process
Let's walk through this exercise together from scratch!
I like to start simple. First let's set up an array of students, assign it to a variable and print it to the terminal to make sure it's working.
# Write a program that splits the class into teams of 2.
# If there's an odd number of students the last group should be a group of 3.
students = ['Daniele', 'Alesia','Anita',
'Ben', 'Thomas', 'Matthew',
'Mark', 'Jennifer', 'Cameron']
puts students
student_shuffle.rb
2 Legit 2 Git
It's a good habit to push your code to Github once you get something working. Let's walk through the steps once more.
Push to Github
Push to Github
- Name your repository something meaningful like "ruby" to indicate this is the home for your ruby programs.
- Note the green checkmark indicating approval for your naming skills
- Click the green "Create repository" button at the bottom.
Push to Github
Sweet! You set up your repo remotely!
Next we have to link it to your local Ruby folder.
- Fortunately Github provides a list of instructions that we can loosely follow
- Let's start with #2 and run "git init" in our terminal to initialize our repository. We only have to do this once per repo.
$ git init
Push to Github
- (We'll deviate from the third instruction a bit)
- Let's add ALL our files to the staging area by typing:
- Sadly we get no feedback.
PRO TIP: Check the status of your files by running:
$ git status
$ git add .
Push to Github
- Now we have to commit to our local repository
- And then add the hook to the remote repo. This is
another one of those things we only have to do once
This adds a hidden file to your ruby folder so github can track your files. Don't be scared; it's legit!
$ git commit -m "first commit"
$ git remote add origin https://github.com/jpanaia/ruby.git
Push to Github
- The last step is pushing to the remote repository
- Good job! Let's go back to github.com and see how it's changed...
$ git push origin master
We're published!
Our file is officially stored in version control. Let's practice pushing to Github as we work. You should get in the habit of committing early and often.
GITHUB = RESUME
Do the Shuffle
Back to our code....
Next we want to randomize our student array. There are several ways to do this. Let's use the ".shuffle!" method and test it.
Curious about methods you can use with arrays?
http://www.ruby-doc.org/core-2.2.0/Array.html
students = ['Daniele', 'Alesia','Anita',
'Ben', 'Thomas', 'Matthew',
'Mark', 'Jennifer', 'Cameron']
# shuffle the student array
students.shuffle!
puts students
Back to Git
We got something else working! This is so exciting I think we should push to Github.
$ git status
Let's add to the staging area.
$ git add .
2 Legit 2 Git
$ git status
We see our file has been staged.
Next step is committing to the local repo w/ a message
$ git commit -m "shuffled student array"
And check the status again.
2 Legit 2 Git
Finally we'll push to the remote repository.
$ git push origin master
Now we have 2 commits saved.
Students
Let's refocus on our array of students. Using an until loop we can iterate through our array. We can simply print out the count to make sure it's working.
# set an array of students
students = ['Daniele', 'Alesia', 'Anita', 'Ben', 'Thomas', 'Matthew', 'Mark', 'Jennifer', 'Cameron']
# shuffle student array
students.shuffle!
# set a count
count = 0
# until count is the number of students
until count == students.length
# Test loop
puts count
# increase the count
count += 1
end # end until
Students
Now, instead of counting let's print each student.
# set a count
count = 0
# until count is the number of students
until count == students.length
# output each student
puts "#{students[count]}"
# increase the count
count += 1
end # end until
How would we output students in pairs?
Students
We can add 1 to the array's index to print the next student.
# set a count
count = 0
# until count is the number of students
until count == students.length
# output students in pairs
puts "#{students[count]} & #{students[count+1]}"
# increase the count
count += 1
end # end until
Hm..this still isn't quite right. How can we fix it?
Students
We increase the count by 2 to account for pairs of students. We're very close but still missing that 9th student.
# set a count
count = 0
# number of students
num_students = students.length - 1
# until count is the number of students
until count == num_students
# output students in pairs
puts "#{students[count]} & #{students[count+1]}"
# increase the count
count += 2
end # end until
Git Real
This is a great time to push to Github. Remember how?
$ git add .
$ git commit -m "paired up students"
$ git push origin master
Looks Good
We'll need to set up a condition to output different results depending on our position in the loop. Once it hits the 6th spot (3 from the end) we assign that group 3 members.
# set an array of students
students = ['Daniele', 'Alesia', 'Anita', 'Ben', 'Thomas', 'Matthew', 'Mark', 'Jennifer', 'Cameron']
# shuffle student array
students.shuffle!
# set a count
count = 0
# number of students
num_students = num_students - 1
until count == num_students
if count < num_students - 3
# output pairs of students
puts "#{students[count]} & #{students[count+1]}"
else
puts "#{students[count]}, #{students[count+1]} & #{students[count+2]}"
end
# increase the count
count += 2
end # end until
A Bug
BUT...what happens if we only have 8 students instead of 9 (sorry Cam).
# set an array of students
students = ['Daniele', 'Alesia', 'Anita', 'Ben', 'Thomas', 'Matthew', 'Mark', 'Jennifer']
Even vs Odd
At this point it's clear that we have to test for even and odd numbers of students.
How would we do this in real life?
A Snag
We'll use the modulus (%) operator to
determine evenness / oddness.
-
If the number of students divided by 2 has a remainder of 1 it's ODD
-
If the number of students divided by 2 has a remainder of 0 it's EVEN
We can see this demonstrated in irb.
Hooray!
We can fix the bug by adding a condition for odd vs even number of students.
until count == number_of_students
# odd # students
if number_of_students % 2 == 1
if count < num_students - 3
# output pairs of students
puts "#{students[count]} & #{students[count+1]}"
else
puts "#{students[count]}, #{students[count+1]} & #{students[count+2]}"
break
end
else # even # students
# output pairs of students
puts "#{students[count]} & #{students[count+1]}"
end
# increase the count
count += 2
end # end until
Ruby Challenge
How could we modify this code to take user input instead of hard-coding a student array?
Think back to our warmup exercise...
My Solution
# empty student array
students = []
student = ''
# prompt user
puts "Who showed up to class today? Type 'done' when finished:"
while student != 'done'
student = gets.chomp
# push student into students array
students.push(student)
end
# pop off last element 'done'
students.pop
# shuffle student array
students.shuffle!
# set a count
count = 0
puts "\nYour teams are:"
until count == students.length
# Odd # students
if number_of_students % 2 == 1
if count < number_of_students - 3
# output pairs of students
puts "#{students[count]} & #{students[count+1]}"
else
puts "#{students[count]}, #{students[count+1]} & #{students[count+2]}"
break
end
else # even # students
# output pairs of students
puts "#{students[count]} & #{students[count+1]}"
end
# increase the count
count += 2
end # end until
new code!
Git Out
Are you sick of git puns yet?
Go ahead and add, commit and push to Github.
Another Snag
Anyone see the bug in this code? There's one special case that I've completely neglected.
What happens if only one student comes to class?
See if you can add some logic to fix this.
1 Lonely Student
until count == students.length
# One student
if number_of_students == 1
puts "#{students[0]} is a team of 1"
break
else
# Odd # students
if number_of_students % 2 == 1
# 3 students or more
if count < students.length - 3
# output pairs of students
puts "#{students[count]} & #{students[count+1]}"
else
puts "#{students[count]}, #{students[count+1]} & #{students[count+2]}"
break
end
else # even # students
# output pairs of students
puts "#{students[count]} & #{students[count+1]}"
end
end
# increase the count
count += 2
end # end until
Push to Github
# Write a program that prints the lyrics
# to 99 Bottles of Beer on the Wall
# example output:
# 99 bottles of beer on the wall
# 99 bottles of beer
# Take one down pass it around
#
# 98 bottles of beer on the wall
# 98 bottles of beer on the wall
# 98 bottles of beer
# Take one down, pass it around
99 Bottles Program
Write a program that prints the lyrics to 99 Bottles of Beer on the Wall
# N number of bottles
number_of_bottles = 99
until number_of_bottles == 0
# Do something
end
99 Bottles Program
Let's define the number of bottles to start with (99, duh!). Then we'll loop until we're out of beer!
# N number of bottles
number_of_bottles = 99
until number_of_bottles == 0
# print 2 lines using number of bottles
# print refrain (doesn’t change)
# print a line using number - 1
end
99 Bottles Program
Let's outline our solution
# N number of bottles
number_of_bottles = 99
until number_of_bottles == 0
# print 2 lines using number of bottles
puts "#{number_of_bottles} bottles of beer on the wall"
puts "#{number_of_bottles} bottles of beer"
# print refrain (doesn’t change)
puts "Take one down, pass it around"
#print a line using N -1
puts "#{number_of_bottles - 1} bottles of beer on the wall\n\n"
end
99 Bottles Program
Now print a bunch of strings (with interpolation!) to sing our song. What happens when we run this code?
number_of_bottles = 99
until number_of_bottles == 0
# print 2 lines using N
puts "#{number_of_bottles} bottles of beer on the wall"
puts "#{number_of_bottles} bottles of beer"
# print refrain (doesn’t change)
puts "Take one down, pass it around\n\n"
#print a line using N -1
puts "#{number_of_bottles - 1} bottles of beer on the wall"
number_of_bottles -= 1
end
99 Bottles Program
A pesky infinite loop!
We need to decrement (-=). Now we're pretty close. How would we ensure correct grammar at 1 bottle of beer?
if number_of_bottles == 1
puts "#{number_of_bottles} bottle of beer on the wall"
puts "#{number_of_bottles} bottle of beer"
# print refrain (doesn’t change)
puts "Take it down, pass it around"
puts "No more bottles of beer on the wall!"
else
# print 2 lines using N
puts "#{number_of_bottles} bottles of beer on the wall"
puts "#{number_of_bottles} bottles of beer"
# print refrain (doesn’t change)
puts "Take one down, pass it around"
if number_of_bottles == 2
puts "1 bottle of beer on the wall\n\n"
else
#print a line using N -1
puts "#{number_of_bottles - 1} bottles of beer on the wall\n\n"
end
end
99 Bottles Program
Here it is! We have to add a few special cases.
if number_of_bottles > 1
# print 2 lines using N
puts "#{number_of_bottles} bottles of beer on the wall"
puts "#{number_of_bottles} bottles of beer"
# print refrain (doesn’t change)
puts "Take one down, pass it around"
# print a line using N -1
puts "#{number_of_bottles - 1} bottles of beer on the wall\n\n"
else
# print 2 lines using N
puts "1 bottle of beer on the wall"
puts "1 bottle of beer"
# print refrain (doesn’t change)
puts "Take it down, pass it around"
# print a line using N -1
puts "No more bottles of beer on the wall!"
end
99 Bottles Program
Let's also add logic to ensure correct grammar when we get down to 1 bottle.
We're close here but it still needs more love...
A few different ways to solve a Ruby problem
5 Questions Problem
- Ask the user 5 yes or no questions
- Compare their answer to a list of correct answers
- Print the number of correct answers
# Ask the user 5 yes or no questions
# Compare their answers to a list of correct answers
# Print the number of correct answers
Ways to approach this
-
Arrays
-
Hashes
-
Methods
Array Approach
questions = [ 'Are narwhals real?',
'Is today Halloween?',
'Do dogs say meow?',
'Does 2+2 = 4?',
'Is Jaime awesome?']
correct_answers = ['Y', 'N', 'N', 'Y', 'Y']
Let's create 2 arrays to hold our questions & correct answers
Array Approach
puts "Please answer Y or N to the following questions!"
Let's first prompt the user ...
questions.each do |question|
puts "Q: #{question}"
user_answer = gets.chomp.upcase
end
Array Approach
Now we print out each question using a loop and save the user's answer in a variable.
Array Approach
index = 0
score = 0
Let's initialize some variables at the top of our code to keep track of our score and the array index.
Array Approach
questions.each do |question|
puts "Q: #{question}"
user_answer = gets.chomp.upcase
if user_answer == correct_answers[index]
# Do Something
end
end
Let's compare the user's answer against the correct answer using the array index
Array Approach
questions.each do |question|
puts "Q: #{question}"
user_answer = gets.chomp.upcase
if user_answer == correct_answers[index]
score += 1
end
index += 1
end
We increase the score by 1 point each time the answers match. We also increment the index variable in order to work our way through array of answers
Array Approach
puts "You got #{score}/5 correct answers!"
Now that we have our score let's print it out to let the user know how they did
Array Approach
if user_answer == 'Y' || user_answer == 'N'
if user_answer == correct_answers[index]
score += 1
end
index += 1
else
puts "Try again: Y or N?"
end
Let's add some validation to make sure we're only accepting "Y" or "N" answers from the user
Array Approach
questions.each do |question|
puts "Q: #{question}"
user_answer = gets.chomp.upcase
if user_answer == 'Y' || user_answer == 'N'
if user_answer == correct_answers[index]
score += 1
end
index += 1
else
puts "Try again: Y or N?"
redo
end
end
Don't forget "redo" to start the loop over again if their answer was invalid.
Array Approach
questions = [ 'Are narwhals real?',
'Is today Halloween?',
'Do dogs say meow?',
'Does 2+2 = 4?',
'Is Jaime awesome?']
correct_answers = ['Y', 'N', 'N', 'Y', 'Y']
index = 0
score = 0
puts "Please answer Y or N to the following questions!"
questions.each do |question|
puts "Q: #{question}"
user_answer = gets.chomp.upcase
if user_answer == 'Y' || user_answer == 'N'
if user_answer == correct_answers[index]
score += 1
end
index += 1
else
puts "Try again: Y or N?"
redo
end
end
puts "You got #{score}/5 correct answers!"
Hash Approach
Another approach is to set up a hash that holds the questions and correct answers in key value pairs.
questions_answers = {'Are narwhals real?'=> 'Y',
'Is today Halloween?'=> 'N',
'Do dogs say meow?' => 'N',
'Does 2+2 = 4?' => 'Y',
'Is Jaime awesome?' => 'Y'}
score = 0
puts "Please answer Y or N to the following questions!"
Hash Approach
Again we prompt the user to answer the question and also initialize a score variable.
Hash Approach
Then we loop over the hash using the key and value, print the question and get the user's answer.
questions_answers.each do |question, correct_answer|
puts "Q: #{question}"
user_answer = gets.chomp.upcase
end
Hash Approach
Add in the same validation and scoring we used in the array approach.
if user_answer == 'Y' || user_answer == 'N'
if user_answer == correct_answer
score += 1
end
else
puts "Try again: Y or N?"
redo
end
Hash Approach
Finally we output the user's score!
puts "You got #{score}/#{questions_answers.count} correct answers!"
Hash Approach
questions_answers = {'Are narwhals real?' => 'Y',
'Is today Halloween?' => 'N',
'Do dogs say meow?' => 'N',
'Does 2+2 = 4?' => 'Y',
'Is Jaime awesome?' => 'Y'}
score = 0
puts "Please answer Y or N to the following questions!"
questions_answers.each do |question, correct_answer|
puts "Q: #{question}"
user_answer = gets.chomp.upcase
if user_answer == 'Y' || user_answer == 'N'
if user_answer == correct_answer
score += 1
end
else
puts "Try again: Y or N?"
redo
end
end
puts "You got #{score}/#{questions_answers.count} correct answers!"
Making Methods
What if we wanted to break this into methods? We could start by declaring instance variables at the top.
@questions_answers = {'Are narwhals real?' => 'Y',
'Is today Halloween?' => 'N',
'Do dogs say meow?' => 'N',
'Does 2+2 = 4?' => 'Y',
'Is Jaime awesome?' => 'Y'}
@score = 0
Making Methods
Next we can break out the prompt into its own method.
def prompt
puts "Please answer Y or N to the following questions!"
end
Making Methods
def put_score
# Do something
end
We can also break out a method to print the score.
Making Methods
def put_score(s,q_a)
puts "You got #{s}/#{q_a.count} correct answers!"
end
Don't forget to pass in local score and question/answer variables!
Making Methods
def ask_questions
@questions_answers.each do |question, correct_answer|
puts "Q: #{question}"
user_answer = gets.chomp.upcase
if user_answer == 'Y' || user_answer == 'N'
if user_answer == correct_answer
@score += 1
end
else
puts "Try again: Y or N?"
redo
end
end
end
Now let's put the bulk of our code in it's own method. Remember we're using instance variables.
Making Methods
Add a main method to call the prompt, ask_questions and put_score methods. Then call "main."
def main
prompt
ask_questions
put_score(@score)
end
main
@questions_answers = {'Are narwhals real?' => 'Y',
'Is today Halloween?' => 'N',
'Do dogs say meow?' => 'N',
'Does 2+2 = 4?' => 'Y',
'Is Jaime awesome?' => 'Y'}
@score = 0
def prompt
puts "Please answer Y or N to the following questions!"
end
def ask_questions
@questions_answers.each do |question, correct_answer|
puts "Q: #{question}"
user_answer = gets.chomp.upcase
if user_answer == 'Y' || user_answer == 'N'
if user_answer == correct_answer
@score += 1
end
else
puts "Try again: Y or N?"
redo
end
end
end
def put_score(s,q_a)
puts "You got #{s}/#{q_a.count} correct answers!"
end
def main
prompt
ask_questions
put_score(@score,@questions_answers)
end
main
Method Solution
Homework
Build a quiz program that gets a few inputs from the user including:
- number of questions
- questions
- answers
Then clear the screen and begin the quiz. Keep score!
Ruby Exercises
By tts-jaime
Ruby Exercises
FT
- 1,267