Learn to Program Answer Key
This here is an answer key for the exercises in Chris Pine's wonderful Learn to Program book. The answers, while not the prettiest or most efficient code, have been tested to work as the problems were understood.
Please excuse some of the formatting, it may not make the code as readable as it should be.
If you have better solutions to any of the problems please feel free to pass them along.
PAGE 12 2.4 A Few Things to Try
1. Hours in a year
puts 365 * 24
2. Minutes in a decade
puts 10 * 365 * 24 * 60
3. Seconds I'm old, 8/8/76 to 5/7/07 (9:45pm)
puts (30 * 365 * 24 * 60 * 60) + (272 * 24 * 60 * 60) + (21 * 60 * 60) + (45 * 60)
4. 912,000,000 seconds, how old?
puts 912000000/60/60/24/365
PAGE 26 5.4 A Few Things to Try
ask first, middle, last name. greet with full name.
puts 'What is your first name?'
nameF = gets.chomp
puts 'What is your middle name?'
nameM = gets.chomp
puts 'What is your last name?'
nameL = gets.chomp
puts ''
puts 'Hi ' + nameF + ' ' + nameM + ' ' + nameL
2. Ask for favorite number. Add one and suggest the result is bigger and better.
ask for favorite number. add 1 to the number and suggest the result is bigger and better than favorite number.
puts 'What is your favorite number?'
numFAV = gets.chomp
numBET = numFAV.to_i + 1
puts ''
puts 'Your favorite number ' + numFAV.to_s + ' is nice, however ' + numBET.to_s + ' is bigger and better.'
PAGE 32 Last Paragraph
puts 'What is your first name?'
fname = gets.chomp
puts 'What is your middle name?'
mname = gets.chomp
puts 'What is your last name?'
lname = gets.chomp
numletters = fname.length + mname.length + lname.length
puts 'Did you know, there are ' + numletters.to_s + ' letters in your full name?'
PAGE 35 6.2 A Few Things to Try
puts 'What do you want!?'
want = gets.chomp
puts 'WHADDYA MEAN "I WANT ' + want.upcase + '" ?!? YOU\'RE FIRED'
2. Program to display a table of contents.
page_width = 60
puts ('Table of Contents'.center(page_width))
puts ''
puts ('Chapter 1: Getting Started'.ljust(page_width/2) + 'page 1'.rjust(page_width/2))
puts ('Chapter 2: Numbers'.ljust(page_width/2) + 'page 9'.rjust(page_width/2))
puts ('Chapter 3: Letters'.ljust(page_width/2) + 'page 13'.rjust(page_width/2))
PAGE 49 Sidebar
input = ''
while input != 'bye'
input = gets.chomp
if input != 'bye'
puts input
end
end
puts 'Come again soon!'
PAGE 55 7.5 A Few Things to Try
bottles = 99
while bottles != 0
puts bottles.to_s + ' bottles of beer on the wall'
puts bottles.to_s + ' bottles of beer'
bottles = bottles - 1
puts 'take one down, pass it around'
if bottles == 1
puts bottles.to_s + ' bottle of beer on the wall'
else
puts bottles.to_s + ' bottles of beer on the wall'
end
puts ''
if bottles == 1
puts bottles.to_s + ' bottle of beer on the wall'
puts bottles.to_s + ' bottle of beer'
bottles = bottles - 1
puts 'take one down, pass it around'
puts bottles.to_s + ' bottles of beer on the wall'
end
end
2. A Deaf Grandma program.
say = 'hi grammy'
while say != 'BYE'
say = gets.chomp
while say != say.upcase
puts 'HUH? SPEAK UP SONNY!'
say = gets.chomp
end
year = rand(21) + 1930
puts 'NO, NOT SINCE ' + year.to_s
end
3. Extend your Deaf Grandma program.
say1 = ''
say2 = ''
say3 = ''
while say1 != 'BYE' || say2 != 'BYE' || say3 != 'BYE'
while say1 != 'BYE'
say1 = gets.chomp
if say1 == say1.upcase
year1 = rand(22) + 1929
puts 'NO, NOT SINCE ' + year1.to_s
else
puts 'HUH?! SPEAK UP, SONNY!'
end
if say1 != 'BYE'
say2 = ''
say3 = ''
end
end
while say2 != 'BYE'
say2 = gets.chomp
if say2 == say2.upcase
year2 = rand(22) + 1929
puts 'NO, NOT SINCE ' + year2.to_s
else
puts 'HUH?! SPEAK UP, SONNY!'
end
if say2 != 'BYE'
say1 = ''
say3 = ''
end
end
while say3 != 'BYE'
say3 = gets.chomp
if say3 == say3.upcase
year3 = rand(22) + 1929
puts 'NO, NOT SINCE ' + year3.to_s
else
puts 'HUH?! SPEAK UP, SONNY!'
end
if say3 != 'BYE'
say1 = ''
say2 = ''
end
end
end
4. Leap Years.
puts 'Input a starting year:'
start_year = gets.chomp
puts 'Input an ending year:'
end_year = gets.chomp
puts ''
while start_year.to_i <= end_year.to_i
if start_year.to_f%400 == 0
puts start_year
elsif start_year.to_f%100 == 0
elsif start_year.to_f%4 == 0
puts start_year
end
start_year = start_year.to_i + 1
end
PAGE 62 Last Paragraph
array = ['one', 'two', ['alpha', 'beta']]
puts array
PAGE 63 8.3 A Few Things to Try
puts 'Type in as many words as you want. When finished press \'Enter\' on an empty line'
x = 0
word = 'word1'
array =[]
while word != ''
word = gets.chomp
array[x] = word
x = x + 1
end
puts ''
puts array.sort
A more straight-forward alternative, courtesy Adrian:
word = 'word'
words =[]
puts 'Please type as many words per line then press the Enter Key.'
puts 'When you are finished press the Enter Key without typing anything.'
while word != ''
word = gets.chomp
words = words.push word
end
puts ''
puts 'Your original values:'
puts words
puts ''
puts 'Your values sorted:'
puts words.sort
puts ''
. . . and another alternative, courtesy Stephen:
awords = []
word = "x"
puts "Type as many words as you want, or press \"enter\" to quit."
while word != ""
#get word from user
word = gets.chomp
#add to array
awords.push word
end
#user exited loop test for array before printing
if awords.empty?
puts "Now sorting what you typed.. thanks."
puts awords.sort
end
. . . one more from Joraaver:
puts "Type in as many words as you want. When you are done, press \'Enter'\ on the next line."
# array for the entries
words = []
entry = "0"
# taking responses and pushing them into the array
while entry != ""
entry = gets.chomp
words.push entry
end
# displaying data
puts "Thanks for your input. Sorting data ..."
puts words.sort
2. Rewrite table of contents program from p. 35 using arrays.
toc = ['Table of Contents', 'Chapter 1: Getting Started', 'page 1','Chapter 2: Numbers','page 9',
'Chapter 3: Letters','page 13']
page_width = 60
puts (toc[0].center(page_width))
puts ''
puts (toc[1].ljust(page_width/2) + toc[2].rjust(page_width/2))
puts (toc[3].ljust(page_width/2) + toc[4].rjust(page_width/2))
puts (toc[5].ljust(page_width/2) + toc[6].rjust(page_width/2))
Joraaver offers another solution:
toc = ["Table of Contents","Chapter 1: Getting Started", "page 1",
"Chapter 2: Numbers", "page 9", "Chapter 3: Letters", "page 13"]
line_width = 60
i = 0
puts(toc[0].center(line_width))
puts ""
# loop to define when to stop putting lines for the contents.
until i == 6
puts(toc[i += 1].ljust(line_width/2) + toc[i += 1].rjust(line_width/2))
end
PAGE 72 Top of Page
def say_moo number_of_moos
puts 'mooooooo....'*number_of_moos
end
puts say_moo(3)
PAGE 76 9.4 A Few Things to Try
def ask question
puts question
reply = gets.chomp.downcase
while reply != 'yes' && reply != 'no'
puts 'Please answer "yes" or "no".'
puts question
reply = gets.chomp.downcase
end
if reply == 'yes'
return true
else
return false
end
end
puts 'Hello, and thank you for ...'
puts
ask 'Do you like eating tacos?'
ask 'Do you like eating burritos?'
wets_bed = ask 'Do you wet the bed?'
ask 'Do you like eating chimichangas?'
ask 'Do you like eating sopapillas?'
puts 'Just a few more questions...'
ask 'Do you like drinking horchata?'
ask 'Do you like eating flautas?'
puts
puts 'DEBRIEFING'
puts 'Thank you for ...'
puts
puts wets_bed
Erez Ben offers an alternative:
def ask question
while question != ''
puts question
reply = gets.chomp.downcase
if reply == 'yes'
return true
elsif reply == 'no'
return false
end
puts ' Please answer "yes" or "no".'
end
end
puts ' Hello, and thank you for...'
puts
ask ' Do you like eating tacos?' # Ignore this return value
ask ' Do you like eating burritos?' # And this one
wets_bed = ask ' Do you wet the bed?' # Save this return value
ask ' Do you like eating chimichangas?'
ask ' Do you like eating sopapillas?'
puts ' Just a few more questions...'
ask ' Do you like drinking horchata?'
ask ' Do you like eating flautas?'
puts
puts ' DEBRIEFING:'
puts ' Thank you for...'
puts
puts wets_bed
Eelco also offers an alternative:
def ask question
while true
puts question
reply = gets.chomp.downcase
if reply == 'yes'
return true
else if reply == 'no'
return false
else
puts ' Please answer "yes" or "no".'
end
end
end
end
puts ' Hello, and thank you for...'
puts
ask ' Do you like eating tacos?' # Ignore this return value
ask ' Do you like eating burritos?' # And this one
wets_bed = ask ' Do you wet the bed?' # Save this return value
ask ' Do you like eating chimichangas?'
ask ' Do you like eating sopapillas?'
puts ' Just a few more questions...'
ask ' Do you like drinking horchata?'
ask ' Do you like eating flautas?'
puts
puts ' DEBRIEFING:'
puts ' Thank you for...'
puts
puts wets_bed
2. Old-school Roman numerals.
def roman number
m_length = 0
d_length = 0
c_length = 0
l_length = 0
x_length = 0
v_length = 0
i_length = 0
if number >= 1000
m_length = number/1000
number = number%1000
end
if number >= 500
d_length = number/500
number = number%500
end
if number >= 100
c_length = number/100
number = number%100
end
if number >= 50
l_length = number/50
number = number%50
end
if number >= 10
x_length = number/10
number = number%10
end
if number >= 5
v_length = number/5
number = number%5
end
if number < 5
i_length = number/1
number = number%10
end
puts 'M'*m_length + 'D'*d_length + 'C'*c_length + 'L'*l_length + 'X'*x_length +
'V'*v_length + 'I'*i_length
end
roman 2999
3. Modern Roman numerals.
def roman number
m_length = 0
n900_length = 0
d_length = 0
n400_length = 0
c_length = 0
n90_length = 0
l_length = 0
n40_length = 0
x_length = 0
n9_length = 0
v_length = 0
n4_length = 0
i_length = 0
if number >= 1000
m_length = number/1000
number = number%1000
end
if number >= 900
n900_length = number/900
number = number%900
end
if number >= 500
d_length = number/500
number = number%500
end
if number >= 400
n400_length = number/400
number = number%400
end
if number >= 100
c_length = number/100
number = number%100
end
if number >= 90
n90_length = number/90
number = number%90
end
if number >= 50
l_length = number/50
number = number%50
end
if number >= 40
n40_length = number/40
number = number%40
end
if number >= 10
x_length = number/10
number = number%10
end
if number >= 9
n9_length = number/9
number = number%9
end
if number >= 5
v_length = number/5
number = number%5
end
if number >= 4
n4_length = number/4
number = number%4
end
if number < 4
i_length = number/1
number = number%10
end
puts 'M'*m_length + "CM"*n900_length + 'D'*d_length + 'CD'*n400_length + 'C'*c_length +
'XC'*n90_length + 'L'*l_length + 'XL'*n40_length + 'X'*x_length + 'IX'*n9_length +
'V'*v_length + 'IV'*n4_length + 'I'*i_length
end
x = ''
while x != 'exit'
puts 'Enter a number, and the equivalent roman numeral will be returned.'
puts 'Type exit to quit.'
x = gets.chomp
roman x.to_i
end
PAGE 83 Bottom of the page.
M = 'land'
o = 'water'
world = [
[o,o,o,o,o,M,o,o,o,o,o],
[o,o,o,o,M,M,o,o,o,o,o],
[o,o,o,o,o,M,o,o,M,M,o],
[o,o,o,M,o,M,o,o,o,M,o],
[o,o,o,o,o,M,M,o,o,o,o],
[o,o,o,o,M,M,M,M,o,o,o],
[M,M,M,M,M,M,M,M,M,M,M],
[o,o,o,M,M,o,M,M,M,o,o],
[o,o,o,o,o,o,M,M,o,o,o],
[o,M,o,o,o,M,M,o,o,o,o],
[o,o,o,o,o,M,o,o,o,o,o]]
def continent_size world, x ,y
if x < 0 or x > 10 or y < 0 or y > 10
return 0
end
if world[y][x] != 'land'
return 0
end
size = 1
world [y][x] = 'counted land'
size = size + continent_size(world, x-1, y-1)
size = size + continent_size(world, x , y-1)
size = size + continent_size(world, x+1, y-1)
size = size + continent_size(world, x-1, y )
size = size + continent_size(world, x+1, y )
size = size + continent_size(world, x-1, y+1)
size = size + continent_size(world, x , y+1)
size = size + continent_size(world, x+1, y+1)
size
end
puts continent_size(world, 5, 5)
PAGE 84 10.2 Sorting
# starting condition
list = [ ]
# ask the question
puts 'Enter a list of words, press \'enter\' to quit and they will be returned sorted.'
word = 'one'
# get the words in the first list
while word != ''
word = gets.chomp
list.push word
end
# sort definition wrapper method
def sort array
count = -2
# count number of words in first list
array.each do |word|
count = count + 1
end
recursive_sort(array, [ ], [ ], count)
end
# recursive sort method definition
def recursive_sort listA, listB, sorted, nums
# local variables
x = 0
y = 0
z = 0
# cycle I
while x <= nums
if listA[x] <= listA[y]
y = y + 1
if y == nums + 1
sorted.push listA[x]
x = x + 1
y = 0
z = z + 1
end
else
listB.push listA[x]
x = x + 1
y = 0
end
end
# cycle II
nums = nums - z
listA = [ ]
x = 0
y = 0
z = 0
if nums < 0
x = nums + 5
end
while x <= nums
if listB[x] <= listB[y]
y = y + 1
if y == nums + 1
sorted.push listB[x]
x = x + 1
y = 0
z = z + 1
end
else
listA.push listB[x]
x = x + 1
y = 0
end
end
nums = nums - z
x = 0
y = 0
z = 0
if nums < 0
puts 'sorted list: '
puts sorted
else recursive_sort(listA, [ ], sorted, nums)
end
end
sort list
PAGE 85 10.3 A Few Things to Try
# starting condition
list = [ ]
# as the question
puts 'Enter a list of words, press \'enter\' to quit and they will be returned randomly shuffled.'
word = 'one'
# get the words in the first list
while word != ''
word = gets.chomp
list.push word
end
# define shuffle method
def shuffle array
# starting conditions of local variables
randomized = [ ]
count = -2
x = 0
y = 0
array.each do |word|
count = count + 1
end
while y <= count
x = rand(count+1)
if array[x] != 'used'
randomized.push array[x]
array [x] = 'used'
y = y + 1
end
end
puts randomized
end
shuffle list
2. Dictionary sort method.
# starting condition
list = [ ]
# ask the question
puts 'Enter a list of words, press \'enter\' to quit and they will be returned sorted.'
word = 'one'
# get the words in the first list
while word != ''
word = gets.chomp
list.push word
end
# sort definition wrapper method
def sort array
count = -2
# count number of words in first list
array.each do |word|
count = count + 1
end
recursive_sort(array, [ ], [ ], count)
end
# recursive sort method definition
def recursive_sort listA, listB, sorted, nums
# local variables
x = 0
y = 0
z = 0
# cycle I
while x <= nums
if listA[x].downcase <= listA[y].downcase
y = y + 1
if y == nums + 1
sorted.push listA[x]
x = x + 1
y = 0
z = z + 1
end
else
listB.push listA[x]
x = x + 1
y = 0
end
end
# cycle II
nums = nums - z
listA = [ ]
x = 0
y = 0
z = 0
if nums < 0
x = nums + 5
end
while x <= nums
if listB[x].downcase <= listB[y].downcase
y = y + 1
if y == nums + 1
sorted.push listB[x]
x = x + 1
y = 0
z = z + 1
end
else
listA.push listB[x]
x = x + 1
y = 0
end
end
nums = nums - z
x = 0
y = 0
z = 0
if nums < 0
puts 'sorted list: '
puts sorted
else recursive_sort(listA, [ ], sorted, nums)
end
end
sort list
PAGE 92 10.5 A Few More Things To Try
def english_number number
if number < 0 # no neg numbers
return 'Please enter a number that isn\'t negative'
end
if number == 0
return 'zero'
end
# no more special cases, no more returns
num_string = '' # This is the string we will return, define it an start 'empty'
ones_place = [ 'one', 'two', 'three',
'four', 'five', 'six',
'seven', 'eight', 'nine']
tens_place = [ 'ten', 'twenty', 'thirty',
'forty', 'fifty', 'sixty',
'seventy', 'eighty', 'ninty']
teenagers = [ 'eleven', 'twelve', 'thirteen',
'fourteen', 'fifteen', 'sixteen',
'seventeen', 'eighteen', 'nineteen']
# "left" is how much of the number we still have to write
# "write" is which part we are writing out at the time
left = number
# trillions
write = left/1000000000000
left = left - write*1000000000000
if write > 0
trillions = english_number write
num_string = num_string + trillions + ' trillion'
if left > 0
num_string = num_string + ' '
end
end
# billions
write = left/1000000000
left = left - write*1000000000
if write > 0
billions = english_number write
num_string = num_string + billions + ' billion'
if left > 0
num_string = num_string + ' '
end
end
# millions
write = left/1000000
left = left - write*1000000
if write > 0
millions = english_number write
num_string = num_string + millions + ' million'
if left > 0
num_string = num_string + ' '
end
end
# thousands
write = left/1000
left = left - write*1000
if write > 0
thousands = english_number write
num_string = num_string + thousands + ' thousand'
if left > 0
num_string = num_string + ' '
end
end
write = left/100 # how many hundreds left
left = left - write*100 # subtract off those hundreds
if write > 0
# recursion
hundreds = english_number write
num_string = num_string + hundreds + ' hundred'
if left > 0
# adds a space
num_string = num_string + ' '
end
end
write = left/10 # how many tens left
left = left - write*10 # subtract off those tens
if write > 0
if ((write == 1) and (left > 0))
# exception for teenagers
num_string = num_string + teenagers[left-1]
# -1 because of the array ordering [0] is eleven etc.
# with teenagers the digit in the ones place is taken care of so nothing left
left = 0
else
num_string = num_string + tens_place[write-1]
end
if left > 0
# add a space
num_string = num_string + '-'
end
end
write = left # how many ones left
left = 0 # subtract off those ones
if write > 0
num_string = num_string + ones_place[write-1]
end
# now we just return the num_string
num_string
end
puts english_number( 0)
puts english_number( 9)
puts english_number( 10)
puts english_number( 11)
puts english_number( 17)
puts english_number( 32)
puts english_number( 88)
puts english_number( 99)
puts english_number(100)
puts english_number(101)
puts english_number(234)
puts english_number(3211)
puts english_number(999999)
puts english_number(1000000000000)
puts english_number(1000)
puts english_number(10000)
puts english_number(1000000)
puts english_number(10000000)
puts english_number(1000000000)
puts english_number(10000000000)
3. Wedding number format.
def english_number number
if number < 0 # no neg numbers
return 'Please enter a number that isn\'t negative'
end
if number == 0
return 'zero'
end
# no more special cases, no more returns
num_string = '' # This is the string we will return, define it an start 'empty'
ones_place = [ 'one', 'two', 'three',
'four', 'five', 'six',
'seven', 'eight', 'nine']
tens_place = [ 'ten', 'twenty', 'thirty',
'forty', 'fifty', 'sixty',
'seventy', 'eighty', 'ninty']
teenagers = [ 'eleven', 'twelve', 'thirteen',
'fourteen', 'fifteen', 'sixteen',
'seventeen', 'eighteen', 'nineteen']
# "left" is how much of the number we still have to write
# "write" is which part we are writing out at the time
left = number
# trillions
write = left/1000000000000
left = left - write*1000000000000
if write > 0
trillions = english_number write
num_string = num_string + trillions + ' trillion'
if left > 0
num_string = num_string + ' '
end
end
# billions
write = left/1000000000
left = left - write*1000000000
if write > 0
billions = english_number write
num_string = num_string + billions + ' billion'
if left > 0
num_string = num_string + ' and '
end
end
# millions
write = left/1000000
left = left - write*1000000
if write > 0
millions = english_number write
num_string = num_string + millions + ' million'
if left > 0
num_string = num_string + ' and '
end
end
# thousands
write = left/1000
left = left - write*1000
if write > 0
thousands = english_number write
num_string = num_string + thousands + ' thousand'
if left > 0
num_string = num_string + ' and '
end
end
write = left/100 # how many hundreds left
left = left - write*100 # subtract off those hundreds
if write > 0
# recursion
hundreds = english_number write
num_string = num_string + hundreds + ' hundred'
if left > 0
# adds a space
num_string = num_string + ' and '
end
end
write = left/10 # how many tens left
left = left - write*10 # subtract off those tens
if write > 0
if ((write == 1) and (left > 0))
# exception for teenagers
num_string = num_string + teenagers[left-1]
# -1 because of the array ordering [0] is eleven etc.
# with teenagers the digit in the ones place is taken care of so nothing left
left = 0
else
num_string = num_string + tens_place[write-1]
end
if left > 0
# add a space
num_string = num_string + ' and '
end
end
write = left # how many ones left
left = 0 # subtract off those ones
if write > 0
num_string = num_string + ones_place[write-1]
end
# now we just return the num_string
num_string
end
puts english_number( 0)
puts english_number( 9)
puts english_number( 10)
puts english_number( 11)
puts english_number( 17)
puts english_number( 32)
puts english_number( 88)
puts english_number( 99)
puts english_number(100)
puts english_number(101)
puts english_number(234)
puts english_number(3211)
puts english_number(999999)
puts english_number(1000000000000)
puts english_number(1000)
puts english_number(10000)
puts english_number(1000000)
puts english_number(10000000)
puts english_number(1000000000)
puts english_number(10000000000)
puts english_number(1976)
4. 'Ninety-nine Bottles of Beer" using english_number.
def english_number number
if number < 0 # no neg numbers
return 'Please enter a number that isn\'t negative'
end
if number == 0
return 'zero'
end
# no more special cases, no more returns
num_string = '' # This is the string we will return, define it an start 'empty'
ones_place = [ 'one', 'two', 'three',
'four', 'five', 'six',
'seven', 'eight', 'nine']
tens_place = [ 'ten', 'twenty', 'thirty',
'forty', 'fifty', 'sixty',
'seventy', 'eighty', 'ninty']
teenagers = [ 'eleven', 'twelve', 'thirteen',
'fourteen', 'fifteen', 'sixteen',
'seventeen', 'eighteen', 'nineteen']
# "left" is how much of the number we still have to write
# "write" is which part we are writing out at the time
left = number
# trillions
write = left/1000000000000
left = left - write*1000000000000
if write > 0
trillions = english_number write
num_string = num_string + trillions + ' trillion'
if left > 0
num_string = num_string + ' '
end
end
# billions
write = left/1000000000
left = left - write*1000000000
if write > 0
billions = english_number write
num_string = num_string + billions + ' billion'
if left > 0
num_string = num_string + ' '
end
end
# millions
write = left/1000000
left = left - write*1000000
if write > 0
millions = english_number write
num_string = num_string + millions + ' million'
if left > 0
num_string = num_string + ' '
end
end
# thousands
write = left/1000
left = left - write*1000
if write > 0
thousands = english_number write
num_string = num_string + thousands + ' thousand'
if left > 0
num_string = num_string + ' '
end
end
write = left/100 # how many hundreds left
left = left - write*100 # subtract off those hundreds
if write > 0
# recursion
hundreds = english_number write
num_string = num_string + hundreds + ' hundred'
if left > 0
# adds a space
num_string = num_string + ' '
end
end
write = left/10 # how many tens left
left = left - write*10 # subtract off those tens
if write > 0
if ((write == 1) and (left > 0))
# exception for teenagers
num_string = num_string + teenagers[left-1]
# -1 because of the array ordering [0] is eleven etc.
# with teenagers the digit in the ones place is taken care of so nothing left
left = 0
else
num_string = num_string + tens_place[write-1]
end
if left > 0
# add a space
num_string = num_string + '-'
end
end
write = left # how many ones left
left = 0 # subtract off those ones
if write > 0
num_string = num_string + ones_place[write-1]
end
# now we just return the num_string
num_string
end
bottles = 999
while bottles != 0
puts english_number(bottles).to_s + ' bottles of beer on the wall'
puts english_number(bottles).to_s + ' bottles of beer'
bottles = bottles - 1
puts 'take one down, pass it around'
if bottles == 1
puts english_number(bottles).to_s + ' bottle of beer on the wall'
else
puts english_number(bottles).to_s + ' bottles of beer on the wall'
end
puts ''
if bottles == 1
puts english_number(bottles).to_s + ' bottle of beer on the wall'
puts english_number(bottles).to_s + ' bottle of beer'
bottles = bottles - 1
puts 'take one down, pass it around'
puts english_number(bottles).to_s + ' bottles of beer on the wall'
end
end
PAGE 104 11.6 A Few Things To Try
Picture-download/file-rename program
# Mac gives a 'cross-device link error' when using File.rename
# to move between Volumes. So assume all pics are moved from camera drive
# to a folder on the computer, 'camera', and then need to be renamed and moved
# to a pictures folder on the desktop.
folder_name = 'Desktop/pics/'
pic_names = Dir['camera/**/*.{JPG,jpg}']
puts 'what would you like to call this batch?'
batch_name = gets.chomp
puts
print 'Downloading '+ pic_names.length.to_s+' files: '
pic_number = 1
pic_names.each do |name|
print '.'
new_name = if pic_number < 10
folder_name.to_s + batch_name + '0' + pic_number.to_s + '.jpg'
else
folder_name.to_s + batch_name + pic_number.to_s + '.jpg'
end
if File.exist? new_name
puts
puts 'DANGER: file names already exist, exiting!'
puts
exit
else
File.rename name, new_name
end
pic_number = pic_number + 1
end
puts
puts 'Done'
2. Build your own playlists.
def shuffle array
x = 0
track_number = 0
number_songs = 0
playlist = [ ]
number_songs = array.length
while x < number_songs
track_number = rand(number_songs)
if array[track_number] != ''
playlist.push array[track_number]
array[track_number] = ''
x = x + 1
else
end
end
filename = 'Desktop/playlist.m3u'
File.open filename, 'w' do |f|
f.puts playlist
end
end
tracks = Dir['Desktop/music/**/*.{ogg,mp3,m4a}']
shuffle tracks
3. Mixed random better playlist.
# music_shuffle tries to minimize clumping at the beginning of playlist,
# does not generate a perfectly mixed up playlist
# just less clumpy
def music_shuffle array
x = 0
track_number = 0
number_songs = 0
playlist = [ ]
full_song_name = [ ]
album_on_deck = ''
previous_album = ''
number_songs = array.length
while x < number_songs
track_number = rand(number_songs)
full_song_name = array[track_number].split'/'
album_on_deck = full_song_name[2]
if album_on_deck != previous_album
if array[track_number] != ''
playlist.push array[track_number]
array[track_number] = ''
x = x + 1
else
end
previous_album = album_on_deck
else
end
end
filename = 'Desktop/playlist.m3u'
File.open filename, 'w' do |f|
f.puts playlist
end
end
tracks = Dir['Desktop/music/**/*.{ogg,mp3,m4a}']
music_shuffle tracks
PAGE 108 12.2 A Few Things To Try
birth_time = Time.mktime(1976, 10, 7, 11, 40, 54)
billion_seconds_old = birth_time + 1000000000
puts billion_seconds_old
2. Happy Birthday!
x = 0
puts 'What year were you born in?'
year = gets.chomp
while x != 1
puts 'What month were you born in?'
month = gets.chomp.downcase
if month == 'january'
month = 1
x = 1
elsif month == 'february'
month = 2
x = 1
elsif month == 'march'
month = 3
x = 1
elsif month == 'april'
month = 4
x = 1
elsif month == 'may'
month = 5
x = 1
elsif month == 'june'
month = 6
x = 1
elsif month == 'july'
month = 7
x = 1
elsif month == 'august'
month = 8
x = 1
elsif month == 'september'
month = 9
x = 1
elsif month == 'october'
month = 10
x = 1
elsif month == 'november'
month = 11
x = 1
elsif month == 'december'
month = 12
x = 1
else
puts 'Please type in a month'
x = 0
end
end
puts 'What day were you born on?'
day = gets.chomp
right_now = Time.new
birth_day = Time.mktime(year.to_i, month.to_i, day.to_i)
years_old = (right_now - birth_day)/(60*60*24*365)
puts ''
years_old.to_i.times do
puts 'spank'
end
PAGE 113 12.6 A Few Things To Try
# Create new hash
roman_numeral = { }
status = 'invalid'
# Defining the roman numeral hash
roman_numeral['I'] = 1
roman_numeral['V'] = 5
roman_numeral['X'] = 10
roman_numeral['L'] = 50
roman_numeral['C'] = 100
roman_numeral['D'] = 500
roman_numeral['M'] = 1000
while status != 'valid'
# Request a Roman numeral, capitalize input and put in array
puts 'Please input a Roman Numeral'
input_numeral = gets.chomp.upcase
no_of_chars = input_numeral.length
input_array = [ ]
counter1 = 0
while counter1 < no_of_chars
input_array.push input_numeral[counter1]
counter1 = counter1 + 1
end
# Check each character in the array to see if its a Roman Numeral
counter2 = 0
input_array.each do |input_letter|
roman_numeral.each do |rom_letter,number|
if input_letter.chr == rom_letter
counter2 = counter2 + 1
else
end
end
end
if counter2 == input_array.length
status = 'valid'
else
status = 'invalid'
puts 'Error: Not all characters are valid roman numerals'
end
end
# Convert roman numeral letter array to array of numbers
number_array = [ ]
input_array.each do |letter|
letter = letter.chr
number = roman_numeral[letter]
number_array.push number
end
# Add/Subtract number array one at a time starting from right
counter3 = number_array.length - 1
# Starting value, first number
number = number_array[counter3]
counter3 = counter3 - 1
while counter3 > -1
# Sum from left to right
if number_array[counter3] < number_array[counter3+1]
number = number - number_array[counter3]
else
number = number + number_array[counter3]
end
counter3 = counter3 - 1
end
puts number
2. Birthday Helper
# Program needs .txt input file.
filename = 'birthdays.txt'
birth_dates = { }
File.open filename do |f|
f.each_line do |entry|
date = entry[-13..-1]
name = entry[0..-15]
birth_dates[name] = date
end
end
puts 'Enter a name and their next birthday will be returned'
name = gets.chomp
date = birth_dates[name]
year = date[-5..-1].to_i
day = date[-9,2].to_i
month_string = date[-13,3]
if month_string == 'Jan'
month = 1
elsif month_string == 'Feb'
month = 2
elsif month_string == 'Mar'
month = 3
elsif month_string == 'Apr'
month = 4
elsif month_string == 'May'
month = 5
elsif month_string == 'Jun'
month = 6
elsif month_string == 'Jul'
month = 7
elsif month_string == 'Aug'
month = 8
elsif month_string == 'Sep'
month = 9
elsif month_string == 'Oct'
month = 10
elsif month_string == 'Nov'
month = 11
elsif month_string == 'Dec'
month = 12
end
today = Time.new
birthdate = Time.mktime(year,month,day)
birthday = Time.mktime(2008,month,day)
if birthday < today
next_birthday = Time.mktime(2009,month,day)
age = (next_birthday - birthdate)/(60*60*24*365)
age = age.to_i
puts name + '\'s next birthday will be ' + next_birthday.to_s
puts 'and they will be ' + age.to_s + ' years old'
else
age = (birthday - birthdate)/(60*60*24*365)
age = age.to_i
puts name + '\'s next birthday will be ' + birthday.to_s
puts 'and they will be ' + age.to_s + ' years old'
end
PAGE 117 13.1 A Few Things to Try
# starting condition
list = [ ]
# ask the question
puts 'Enter a list of words, press \'enter\' to quit and they will be returned randomly shuffled.'
word = 'one'
# get the words in the first list
while word != ''
word = gets.chomp
list.push word
end
# defining the array method
class Array
# defining to_shuffle
def to_shuffle
# starting conditions of local variables
randomized = [ ]
count = -2
x = 0
y = 0
self.each do |word|
count = count + 1
end
while y <= count
x = rand(count+1)
if self[x] != 'used'
randomized.push self[x]
self[x] = 'used'
y = y + 1
end
end
puts randomized
end
end
# shuffling and array
list.to_shuffle
2. Factorial method as integer method.
puts 'Enter a number and the factorial of that number will be returned'
num = gets.chomp.to_i
class Integer
def factorial
if self < 0
return 'You can\'t take the factorial of a negative number!'
end
if self <= 1
1
else
self * (self-1).factorial
end
end
end
puts num.factorial
3. Roman numeral method as Integer method.
class Integer
def roman
m_length = 0
n900_length = 0
d_length = 0
n400_length = 0
c_length = 0
n90_length = 0
l_length = 0
n40_length = 0
x_length = 0
n9_length = 0
v_length = 0
n4_length = 0
i_length = 0
number = self
if number >= 1000
m_length = number/1000
number = number%1000
end
if number >= 900
n900_length = number/900
number = number%900
end
if number >= 500
d_length = number/500
number = number%500
end
if number >= 400
n400_length = number/400
number = number%400
end
if number >= 100
c_length = number/100
number = number%100
end
if number >= 90
n90_length = number/90
number = number%90
end
if number >= 50
l_length = number/50
number = number%50
end
if number >= 40
n40_length = number/40
number = number%40
end
if number >= 10
x_length = number/10
number = number%10
end
if number >= 9
n9_length = number/9
number = number%9
end
if number >= 5
v_length = number/5
number = number%5
end
if number >= 4
n4_length = number/4
number = number%4
end
if number < 4
i_length = number/1
number = number%10
end
puts 'M'*m_length + "CM"*n900_length + 'D'*d_length + 'CD'*n400_length + 'C'*c_length +
'XC'*n90_length + 'L'*l_length + 'XL'*n40_length + 'X'*x_length + 'IX'*n9_length +
'V'*v_length + 'IV'*n4_length + 'I'*i_length
end
end
x = ''
while x != 'exit'
puts 'Enter a number, and the equivalent roman numeral will be returned.'
puts 'Type exit to quit.'
x = gets.chomp
num = x.to_i
num.roman
end
PAGE 126 13.4 A Few More Things to Try
class OrangeTree
def initialize
@age = 0
@tall = 0
@fruit = 0
puts 'A new Orange Tree is planted.'
end
def height
puts 'The tree is ' + @tall.to_s + ' feet tall.'
end
def count_the_oranges
puts 'The tree has ' + @fruit.to_s + ' oranges.'
end
def pick_an_orange
if @fruit < 1
puts 'Sorry, there are no oranges to pick this year.'
else
puts 'You pick an orange from the tree. It\'s very delicious.'
@fruit = @fruit - 1
end
end
def one_year_passes
puts 'One year passes'
@age = @age + 1
@tall = @tall + 1
@fruit = 0
if dead?
puts 'The Orange Tree dies'
exit
end
if @age > 2
@fruit = @age*10
else
@fruit = 0
end
end
private
def dead?
@age > 5
end
end
puts ''
tree = OrangeTree.new
tree.height
tree.count_the_oranges
tree.pick_an_orange
puts ''
tree.one_year_passes
tree.height
tree.count_the_oranges
tree.pick_an_orange
puts ''
tree.one_year_passes
tree.one_year_passes
tree.height
tree.count_the_oranges
tree.pick_an_orange
tree.pick_an_orange
tree.pick_an_orange
tree.pick_an_orange
tree.pick_an_orange
tree.pick_an_orange
tree.count_the_oranges
puts ''
tree.one_year_passes
tree.height
tree.count_the_oranges
tree.pick_an_orange
tree.pick_an_orange
tree.pick_an_orange
tree.count_the_oranges
tree.pick_an_orange
tree.count_the_oranges
puts ''
tree.one_year_passes
tree.height
tree.count_the_oranges
puts ''
tree.one_year_passes
2. Interact with your baby dragon.
class Dragon
def initialize name
@name = name
@asleep = false
@stuff_in_belly = 10 # he's full
@stuff_in_intestine = 0 # doesn't need to go
puts @name + ' is born.'
end
# Feed
def feed
puts 'You feed ' + @name + '.'
@stuff_in_belly = 10
passage_of_time
end
# Walk
def walk
puts 'You walk ' + @name + '.'
@stuff_in_intestine = 0
passage_of_time
end
# Put to bed
def put_to_bed
puts 'You put ' + @name + ' to bed.'
@asleep = true
3. times do
if @asleep
passage_of_time
end
if @asleep
puts @name + ' snores, filling the room with smoke.'
end
end
if @asleep
@asleep = false
puts @name + ' wakes up slowly.'
end
end
# Toss
def toss
puts 'You toss ' + @name + ' up into the air.'
puts 'He giggles, which singes your eyebrows.'
passage_of_time
end
# Rock
def rock
puts 'You rock ' + @name + ' gently.'
@asleep = true
puts 'He briefly dozes off...'
passage_of_time
if @asleep
@asleep = false
puts '...but wakes when you stop'
end
end
private
# following methods are internal
# hungry?
def hungry?
@stuff_in_belly <= 2
end
# poopy?
def poopy?
@stuff_in_intestine >= 8
end
# passage of time, this is when things happen
def passage_of_time
if @stuff_in_belly > 0
# move food from belly to intestine
@stuff_in_belly = @stuff_in_belly - 1
@stuff_in_intestine = @stuff_in_intestine + 1
else
if @asleep
@asleep = false
puts 'He wakes up suddenly!'
end
puts @name + ' is starving! In desperation, he ate YOU!'
exit
end
if @stuff_in_intestine >= 10
@stuff_in_intestine = 0
puts 'Whoops! ' + @name + ' had an accident...'
end
if hungry?
if @asleep
@asleep = false
puts 'He wakes up suddenly!'
end
puts @name + '\'s stomach grumbles...'
end
if poopy?
if @asleep
@asleep = false
puts 'He wakes up suddenly!'
end
puts @name + ' does the potty dance...'
end
end
end
pet = Dragon.new 'Norbert'
command = ''
while command != 'exit'
puts 'Enter a command to control your dragon:'
command = gets.chomp
if command == 'feed'
pet.feed
elsif command == 'walk'
pet.walk
elsif command == 'put_to_bed'
pet.put_to_bed
elsif command == 'toss'
pet.toss
elsif command == 'rock'
pet.rock
elsif command == 'exit'
exit
else
puts 'Can\'t recognize your command, please re-enter.'
end
end
PAGE 136 14.4 A Few Things to Try
#Set @profile_toggle 'on' to turn profiling on
@profile_toggle = 'off'
def profile block_description, &block
if @profile_toggle == 'on'
start_time = Time.now
block.call
duration = Time.now - start_time
puts block_description+' : '+duration.to_s+' seconds'
else
block.call
end
end
# 25000 doublings block
profile '25000 doublings' do
number = 1
25000.times do
number = number + number
end
puts number.to_s.length.to_s+' digits'
end
# count to a million
profile 'count to a million' do
number = 0
1000000.times do
number = number + 1
end
end
2. Grandfather Clock
def clock some_proc
#convert hours to 12 hour format
current_hour = Time.new.hour
if current_hour == 0
current_hour = current_hour + 12
elsif current_hour > 12
current_hour = current_hour - 12
end
#call the proc the number of hours passed
current_hour.to_i.times do
some_proc.call
end
end
# Dong proc
dong_proc = Proc.new do
puts 'DONG!'
end
clock dong_proc
3. Program logger.
def log block_description, &block
puts 'Beginning "'+block_description+'" . . .'
value_returned = block.call
puts '. . . "'+block_description+'" finished, returning:'
puts value_returned
end
log 'outer block' do
log 'some little block' do
5
end
log 'yet another block' do
'I like Thai food!'
end
false
end
4.Better logger.
$nesting_depth = 0
$space = ' '
def log block_description, &block
puts $space*$nesting_depth + 'Beginning "'+block_description+'" ...'
$nesting_depth = $nesting_depth + 1
value_returned = block.call
$nesting_depth = $nesting_depth - 1
puts $space*$nesting_depth + '... "'+block_description+'" finished, returning:'
puts $space*$nesting_depth + value_returned.to_s
end
log 'outer block' do
log 'some little block' do
log 'teeny-tiny block' do
'lots of love'
end
42
end
log 'yet another block' do
'I love Indian food!'
end
true
end