diff --git a/ch09-writing-your-own-methods/ask.rb b/ch09-writing-your-own-methods/ask.rb index 01716eb35..71eecf5d4 100644 --- a/ch09-writing-your-own-methods/ask.rb +++ b/ch09-writing-your-own-methods/ask.rb @@ -1,3 +1,16 @@ def ask question - # your code here + while true + puts question + reply = gets.chomp.downcase + if (reply == 'yes' || reply == 'no') + if reply == 'yes' + return true + else + return false + end + break + else + puts 'Please answer "yes" or "no".' + end + end end \ No newline at end of file diff --git a/ch09-writing-your-own-methods/old_school_roman_numerals.rb b/ch09-writing-your-own-methods/old_school_roman_numerals.rb index ca6589f2d..fc64a1704 100644 --- a/ch09-writing-your-own-methods/old_school_roman_numerals.rb +++ b/ch09-writing-your-own-methods/old_school_roman_numerals.rb @@ -1,3 +1,13 @@ def old_roman_numeral num - # your code here + puts "Oops! Try using a positive integer!" if num <= 0 + roman = '' + roman << 'M' * (num / 1000) + roman << 'D' * (num % 1000 / 500) + roman << 'C' * (num % 500 / 100) + roman << 'L' * (num % 100 / 50) + roman << 'X' * (num % 50 / 10) + roman << 'V' * (num % 10 / 5) + roman << 'I' * (num % 5 / 1) + + return roman end \ No newline at end of file diff --git a/ch09-writing-your-own-methods/roman_numerals.rb b/ch09-writing-your-own-methods/roman_numerals.rb index 5c93b59ac..cf2ec51ab 100644 --- a/ch09-writing-your-own-methods/roman_numerals.rb +++ b/ch09-writing-your-own-methods/roman_numerals.rb @@ -1,3 +1,38 @@ def roman_numeral num - # your code here + puts "Oops! Try using a positive integer!" if num <= 0 + + thous = (num / 1000) + hunds = (num % 1000 / 100) + tens = (num % 100 / 10) + ones = (num % 10) + + roman = 'M' * thous + + if hunds == 9 + roman = roman + 'CM' + elsif hunds == 4 + roman = roman + 'CD' + else + roman = roman + 'D' * (num % 1000 / 500) + roman = roman + 'C' * (num % 500 / 100) + end + + if tens == 9 + roman = roman + 'XC' + elsif tens == 4 + roman = romann + 'XL' + else + roman = roman + 'L' * (num % 100 / 50) + roman = roman + 'X' * (num % 50 / 10) + end + + if ones == 9 + roman = roman + 'IX' + elsif ones == 4 + roman = roman + 'IV' + else + roman = roman + 'V' * (num % 10 / 5) + roman = roman + 'I' * (num % 5 / 1) + end + return roman end \ No newline at end of file diff --git a/ch10-nothing-new/dictionary_sort.rb b/ch10-nothing-new/dictionary_sort.rb index c9893d0fd..5ca6aafff 100644 --- a/ch10-nothing-new/dictionary_sort.rb +++ b/ch10-nothing-new/dictionary_sort.rb @@ -1,3 +1,9 @@ def dictionary_sort arr - # your code here + return arr if arr.length <= 1 + + middle = arr.pop + less = arr.select{|x| x.downcase < middle.downcase} + more = arr.select{|x| x.downcase >= middle.downcase} + + dictionary_sort(less) + [middle] + dictionary_sort(more) end \ No newline at end of file diff --git a/ch10-nothing-new/english_number.rb b/ch10-nothing-new/english_number.rb index c0129bc4e..6bce88086 100644 --- a/ch10-nothing-new/english_number.rb +++ b/ch10-nothing-new/english_number.rb @@ -1,3 +1,86 @@ def english_number number - # your code here -end + if number < 0 + return "Oops! Please use a positive integer!" + end + if number == 0 + return "zero" + end + + num_string = '' + + ones_place = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'] + + tens_place = ['ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'] + + teenagers = ['eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'] + + zillions = [['hundred', 2], + ['thousand', 3], + ['million', 6], + ['billion', 9], + ['trillion', 12], + ['quadrillion', 15], + ['quintillion', 18], + ['sextillion', 21], + ['septillion', 24], + ['octillion', 27], + ['nonillion', 30], + ['decillion', 33], + ['undecillion', 36], + ['duodecillion', 39], + ['tredecillion', 42], + ['quattuordecillion', 45], + ['quindecillion', 48], + ['sexdecillion', 51], + ['septendecillion', 54], + ['octodecillion', 57], + ['novemdecillion', 60], + ['vigintillion', 63], + ['googol', 100]] + + left = number + + while zillions.length > 0 + zil_pair = zillions.pop + zil_name = zil_pair[0] + zil_base = 10 ** zil_pair[1] + write = left/zil_base + left = left - write*zil_base + + if write > 0 + # Now here's the recursion: + prefix = english_number write + num_string = num_string + prefix + ' ' + zil_name + + if left > 0 + num_string = num_string + ' ' + end + end + end + + write = left/10 + left = left - write*10 + + if write > 0 + if ((write == 1) and (left > 0)) + num_string = num_string + teenagers[left-1] + left = 0 + else + num_string = num_string + tens_place[write-1] + + end + + if left > 0 + num_string = num_string + '-' + end + end + + write = left + left = 0 + + if write > 0 + num_string = num_string + ones_place[write-1] + end + + num_string +end \ No newline at end of file diff --git a/ch10-nothing-new/ninety_nine_bottles_of_beer.rb b/ch10-nothing-new/ninety_nine_bottles_of_beer.rb index 801de24bd..e17325bfc 100644 --- a/ch10-nothing-new/ninety_nine_bottles_of_beer.rb +++ b/ch10-nothing-new/ninety_nine_bottles_of_beer.rb @@ -1 +1,15 @@ -# your code here \ No newline at end of file +require './ch10-nothing-new/english_number.rb' + + def pluralize(num, word) + num == "one" ? num + " " + word : num + " " + word + "s" + end + + count = 9999 + while count > 0 + number_bottles = english_number(count) + bottles = pluralize(number_bottles, "bottle") + puts "#{bottles.capitalize} of beer on the wall, #{bottles} of beer." + count -= 1 + bottles = pluralize(english_number(count), "bottle") + puts "Take one down and pass it around, #{bottles} of beer on the wall." + end \ No newline at end of file diff --git a/ch10-nothing-new/shuffle.rb b/ch10-nothing-new/shuffle.rb index a486ad94c..383f0cdd7 100644 --- a/ch10-nothing-new/shuffle.rb +++ b/ch10-nothing-new/shuffle.rb @@ -1,3 +1,3 @@ def shuffle arr - # your code here + arr.shuffle end \ No newline at end of file diff --git a/ch10-nothing-new/sort.rb b/ch10-nothing-new/sort.rb index 44c6deb58..0374daff5 100644 --- a/ch10-nothing-new/sort.rb +++ b/ch10-nothing-new/sort.rb @@ -1,3 +1,9 @@ def sort arr - # your code here + return arr if arr.length <= 1 + + middle = arr.pop + less = arr.select{|x| x < middle} + more = arr.select{|x| x >= middle} + + sort(less) + [middle] + sort(more) end \ No newline at end of file diff --git a/ch11-reading-and-writing/build_a_better_playlist.rb b/ch11-reading-and-writing/build_a_better_playlist.rb index 3b31bd241..71f15f9ea 100644 --- a/ch11-reading-and-writing/build_a_better_playlist.rb +++ b/ch11-reading-and-writing/build_a_better_playlist.rb @@ -1,3 +1,54 @@ def music_shuffle filenames - # your code here -end + songs_and_paths = filenames.map do |s| + [s, s.split('/')] # [song, path] + end + + tree = {:root => []} + + # put each song into the tree + insert_into_tree = proc do |branch, song, path| + if path.length == 0 # add to current branch + branch[:root] << song + else # delve deeper + sub_branch = path[0] + path.shift # like "pop", but pops off the front + + if !branch[sub_branch] + branch[sub_branch] = {:root => []} + end + + insert_into_tree[branch[sub_branch], song, path] + end + end + + songs_and_paths.each{|sp| insert_into_tree[tree, *sp]} + + # recursively: + # - shuffle sub-branches (and root) + # - weight each sub-branch (and root) + # - merge (shuffle) these groups together + shuffle_branch = proc do |branch| + shuffled_subs = [] + + branch.each do |key, unshuffled| + shuffled_subs << if key == :root + unshuffled # At this level, these are all duplicates. + else + shuffle_branch[unshuffled] + end + end + + weighted_songs = [] + + shuffled_subs.each do |shuffled_songs| + shuffled_songs.each_with_index do |song, idx| + num = shuffled_songs.length.to_f + weight = (idx + rand) / num + weighted_songs << [song, weight] + end + end + + weighted_songs.sort_by{|s,v| v}.map{|s,v| s} + end + shuffle_branch[tree] +end \ No newline at end of file diff --git a/ch11-reading-and-writing/build_your_own_playlist.rb b/ch11-reading-and-writing/build_your_own_playlist.rb index 801de24bd..f0776f208 100644 --- a/ch11-reading-and-writing/build_your_own_playlist.rb +++ b/ch11-reading-and-writing/build_your_own_playlist.rb @@ -1 +1,7 @@ -# your code here \ No newline at end of file +music = Dir['**/*.mp3'] + +File.open('playlist.m3u', 'w') do |f| + music.each { |song| f.write(song + "\n") } +end + +puts "Finished!" \ No newline at end of file diff --git a/ch11-reading-and-writing/safer_picture_downloading.rb b/ch11-reading-and-writing/safer_picture_downloading.rb index 801de24bd..87f9ffe8c 100644 --- a/ch11-reading-and-writing/safer_picture_downloading.rb +++ b/ch11-reading-and-writing/safer_picture_downloading.rb @@ -1 +1,29 @@ -# your code here \ No newline at end of file +Dir.chdir '/This_PC/Users/Joe/Pictures' + +pic_names = Dir['This_PC/F:/*.jpg'] + +puts 'What are we calling this group of snaps?' +batch_name = gets.chomp +puts +print "Downloading #{pic_names.length} files: " + +pic_number = 1 +pic_names.each do |name| + + print '.' + new_name = if pic_number < 0 + "#{batch_name}0#{pic_number}.jpg" + else + "#{batch_name}#{pic_number}.jpg" + end + + if File.exist?(new_name) + puts 'File name conflict. Aborting renaming process.' + exit + else + File.rename name, new_name + pic_number = pic_number + 1 + end +end + puts + puts 'Done and dusted!' \ No newline at end of file diff --git a/ch12-new-classes-of-objects/happy_birthday.rb b/ch12-new-classes-of-objects/happy_birthday.rb index 801de24bd..d26f70b04 100644 --- a/ch12-new-classes-of-objects/happy_birthday.rb +++ b/ch12-new-classes-of-objects/happy_birthday.rb @@ -1 +1,18 @@ -# your code here \ No newline at end of file +puts 'What year were you born?' +b_year = gets.chomp.to_i + +puts 'What month were you born? (1-12)' +b_month = gets.chomp.to_i + +puts 'What day of the month were you born?' +b_day = gets.chomp.to_i + +b = Time.local(b_year, b_month, b_day) +t = Time.new + +age = 1 + +while Time.local(b_year + age, b_month, b_day) <= t + puts 'SPANK!' + age = age + 1 +end \ No newline at end of file diff --git a/ch12-new-classes-of-objects/one_billion_seconds.rb b/ch12-new-classes-of-objects/one_billion_seconds.rb index 801de24bd..1afda2a53 100644 --- a/ch12-new-classes-of-objects/one_billion_seconds.rb +++ b/ch12-new-classes-of-objects/one_billion_seconds.rb @@ -1 +1 @@ -# your code here \ No newline at end of file +puts(Time.gm(1993, 6, 4, 10, 31) + 10**9) \ No newline at end of file diff --git a/ch12-new-classes-of-objects/party_like_its_roman_to_integer_mcmxcix.rb b/ch12-new-classes-of-objects/party_like_its_roman_to_integer_mcmxcix.rb index 037b6cb09..565729272 100644 --- a/ch12-new-classes-of-objects/party_like_its_roman_to_integer_mcmxcix.rb +++ b/ch12-new-classes-of-objects/party_like_its_roman_to_integer_mcmxcix.rb @@ -1,3 +1,30 @@ -def roman_to_integer roman - # your code here +def roman_to_integer(roman) + + roman = roman.upcase + + return 0 if roman == "NULLA" + numerals = { M: 1000, + D: 500, + C: 100, + L: 50, + X: 10, + V: 5, + I: 1 } + +number = 0 +previous_value = 0 + +i = roman.length - 1 + while i >= 0 + value = numerals[roman[i].to_sym] + return "Not a valid roman numeral" if value.nil? + if value >= previous_value + number += value + else + number -= value + end + previous_value = value + i -= 1 + end + number end \ No newline at end of file diff --git a/ch13-creating-new-classes/extend_built_in_classes.rb b/ch13-creating-new-classes/extend_built_in_classes.rb index c3e793933..b26f4f140 100644 --- a/ch13-creating-new-classes/extend_built_in_classes.rb +++ b/ch13-creating-new-classes/extend_built_in_classes.rb @@ -1,3 +1,27 @@ class Integer - # your code here + + def factorial + + raise 'Must not use negative integer' if self < 0 + + (self <= 1) ? 1 : self * (self-1).factorial + end + + + def to_roman + + raise 'Must use positive integer' if self <= 0 + + roman = '' + + roman << 'M' * (self / 1000) + roman << 'D' * (self % 1000 / 500) + roman << 'C' * (self % 500 / 100) + roman << 'L' * (self % 100 / 50) + roman << 'X' * (self % 50 / 10) + roman << 'V' * (self % 10 / 5) + roman << 'I' * (self % 5 / 1) + + roman + end end \ No newline at end of file diff --git a/ch13-creating-new-classes/interactive_baby_dragon.rb b/ch13-creating-new-classes/interactive_baby_dragon.rb index 801de24bd..6524ce810 100644 --- a/ch13-creating-new-classes/interactive_baby_dragon.rb +++ b/ch13-creating-new-classes/interactive_baby_dragon.rb @@ -1 +1,20 @@ -# your code here \ No newline at end of file +puts 'What would you like to name your baby dragon?' +name = gets.chomp +pet = Dragon.new name +obj = Object.new + +while true + + puts + puts 'commands: feed, toss, walk, rock, put_to_bed, exit' + command = gets.chomp + + if command == 'exit' + exit + elsif pet.respond_to?(command) && !obj.respond_to?(command) + pet.send command + else + puts 'This dragon isn\'t fully trained yet! Please choose a command.' + end + +end \ No newline at end of file diff --git a/ch13-creating-new-classes/orange_tree.rb b/ch13-creating-new-classes/orange_tree.rb index 025d08907..e39c8e13e 100644 --- a/ch13-creating-new-classes/orange_tree.rb +++ b/ch13-creating-new-classes/orange_tree.rb @@ -1,11 +1,49 @@ -# in order to pass the rspec please follow the below rates of growth, orange production and age of death. -# have your OrangeTree grow by 0.4 per year. -# have it produce no oranges in its first 5 years -# starting in its sixth year have it produce oranges at a rate of (height * 15 - 25) per year. -# have the tree die after 25 years. -# check out the rspec spec/ch13/orange_tree_spec.rb to see what strings we're looking for in the responses. - - class OrangeTree - # your code here -end + def initialize + @age = 0 + @height = 0 + @orange_count = 0 + @alive = true + end + + def height + @alive ? @height : "A dead tree is not very tall. :(" + end + + def count_the_oranges + @alive ? @orange_count : "A dead tree has no oranges. :(" + end + + def pick_an_orange + if @alive + if @orange_count > 0 + @orange_count -= 1 + "Delicious!" + else + "There are no oranges on the tree this year" + end + else + "A dead tree has nothing to pick. :(" + end + end + + def one_year_passes + @orange_count = 0 + @age += 1 + @height = (@height + 0.4).round(1) + if @alive + + if @age > 25 + @alive = false + "Oh, no! The tree is too old, and has died. :(" + elsif @age > 5 + @orange_count += (@height * 15 - 25).round + "This year your tree grew to #{@height}m tall, and produced #{@orange_count} oranges." + end + + else + "A year later, the tree is still dead. :(" + end + end + +end \ No newline at end of file diff --git a/ch14-blocks-and-procs/better_program_logger.rb b/ch14-blocks-and-procs/better_program_logger.rb index 0e2e18d57..7d0c9cc42 100644 --- a/ch14-blocks-and-procs/better_program_logger.rb +++ b/ch14-blocks-and-procs/better_program_logger.rb @@ -1,3 +1,10 @@ -def log desc, &block - # your code here +$nesting_depth = 0 + +def better_log desc, &block + indent = " " * $nesting_depth + puts "#{indent}Beginning \"#{desc}\"..." + $nesting_depth += 1 + result = block.call + puts "#{indent}...\"#{desc}\" finished, returning: #{result}" + $nesting_depth -= 1 end \ No newline at end of file diff --git a/ch14-blocks-and-procs/even_better_profiling.rb b/ch14-blocks-and-procs/even_better_profiling.rb index b01b78fd8..676550da4 100644 --- a/ch14-blocks-and-procs/even_better_profiling.rb +++ b/ch14-blocks-and-procs/even_better_profiling.rb @@ -1,3 +1,12 @@ +$OPT_PROFILING_ON = false + def profile block_description, &block - # your code here + if $OPT_PROFILING_ON + start_time = Time.new + block[] + duration = Time.new - start_time + puts "#{block_description}: #{duration} seconds" + else + block[] + end end \ No newline at end of file diff --git a/ch14-blocks-and-procs/grandfather_clock.rb b/ch14-blocks-and-procs/grandfather_clock.rb index 916f6d354..c423edf20 100644 --- a/ch14-blocks-and-procs/grandfather_clock.rb +++ b/ch14-blocks-and-procs/grandfather_clock.rb @@ -1,3 +1,7 @@ def grandfather_clock &block - # your code here -end \ No newline at end of file + hour = (Time.new.hour + 11)%12 + 1 + + hour.times(&block) +end + +grandfather_clock { puts 'DONG!' } \ No newline at end of file diff --git a/ch14-blocks-and-procs/program_logger.rb b/ch14-blocks-and-procs/program_logger.rb index 0e2e18d57..05c840f0b 100644 --- a/ch14-blocks-and-procs/program_logger.rb +++ b/ch14-blocks-and-procs/program_logger.rb @@ -1,3 +1,17 @@ -def log desc, &block - # your code here +def program_log desc, &block + puts "Beginning #{desc.inspect}..." + result = block[] + puts "...#{desc.inspect} finished, returning: #{result}" +end + +program_log 'outer block' do + program_log 'some little block' do + 1**1 + 2**2 + end + + program_log 'yet another block' do + '!doof iahT ekil I'.reverse + end + + '0' == 0 end \ No newline at end of file