Skip to content

Chapter 4

jhonndabi edited this page Sep 6, 2018 · 12 revisions

Section 4.2.1

1) Assign variables city and state to your current city and state of residence. (If residing outside the U.S., substitute the analogous quantities.)
2.5.1 :001 > city = "Guarapuava"
 => "Guarapuava" 
2.5.1 :002 > state = "Paraná"
 => "Paraná"
2) Using interpolation, print (using puts) a string consisting of the city and state separated by a comma and a space, as in “Los Angeles, CA”.
2.5.1 :003 > puts "#{city}, #{state}"
Guarapuava, Paraná
 => nil 
3) Repeat the previous exercise but with the city and state separated by a tab character.
2.5.1 :004 > puts "#{city}\t#{state}"
Guarapuava	Paraná
 => nil 
4) What is the result if you replace double quotes with single quotes in the previous exercise?

The interpolation doesn't work, and the 'backslashe t' is considered as literal.

2.5.1 :005 > puts '#{city}\t#{state}'
#{city}\t#{state}
 => nil

Section 4.2.3

1) What is the length of the string “racecar”?
2.5.1 :001 > "racecar".length
 => 7 
2) Confirm using the reverse method that the string in the previous exercise is the same when its letters are reversed.
2.5.1 :002 > "racecar".reverse
 => "racecar"
3) Assign the string “racecar” to the variable s. Confirm using the comparison operator == that s and s.reverse are equal.
2.5.1 :003 > s = "racecar"
 => "racecar"
2.5.1 :004 > s == s.reverse
 => true
4) What is the result of running the code shown in Listing 4.9? How does it change if you reassign the variable s to the string “onomatopoeia”? Hint: Use up-arrow to retrieve and edit previous commands
2.5.1 :005 > puts "It's a palindrome!" if s == s.reverse
It's a palindrome!
 => nil
2.5.1 :006 > s = "onomatopoeia"
 => "onomatopoeia" 
2.5.1 :007 > puts "It's a palindrome!" if s == s.reverse
 => nil

Section 4.2.4

1) By replacing FILL_IN with the appropriate comparison test shown in Listing 4.10, define a method for testing palindromes. Hint: Use the comparison shown in Listing 4.9.
2.5.1 :001 > def palindrome_tester(s)
2.5.1 :002?>   if s == s.reverse
2.5.1 :003?>     puts "It's a palindrome!"
2.5.1 :004?>     else
2.5.1 :005?>     puts "It's not a palindrome."
2.5.1 :006?>     end
2.5.1 :007?>   end
 => :palindrome_tester
2) By running your palindrome tester on “racecar” and “onomatopoeia”, confirm that the first is a palindrome and the second isn’t.
2.5.1 :008 > palindrome_tester "racecar"
It's a palindrome!
 => nil 
2.5.1 :009 > palindrome_tester "onomatopoeia"
It's not a palindrome.
 => nil 
3) By calling the nil? method on palindrome_tester("racecar"), confirm that its return value is nil (i.e., calling nil? on the result of the method should return true). This is because the code in Listing 4.10 prints its responses instead of returning them.
2.5.1 :010 > palindrome_tester("racecar").nil?
It's a palindrome!
 => true 

Section 4.3.1

1) Assign a to be to the result of splitting the string “A man, a plan, a canal, Panama” on comma-space.
2.5.1 :001 > a = "A man, a plan, a canal, Panama".split(", ")
 => ["A man", "a plan", "a canal", "Panama"] 
2) Assign s to the string resulting from joining a on nothing.
2.5.1 :002 > s = a.join
 => "A mana plana canalPanama"
3) Split s on whitespace and rejoin on nothing. Use the palindrome test from Listing 4.10 to confirm that the resulting string s is not a palindrome by the current definition. Using the downcase method, show that s.downcase is a palindrome.
2.5.1 :003 > s = s.split(" ").join
 => "AmanaplanacanalPanama" 
2.5.1 :004 > def palindrome_tester(s)
2.5.1 :005?>   puts "It's a palindrome!" if s == s.reverse
2.5.1 :006?>   puts "It's not a palindrome." if s != s.reverse
2.5.1 :007?>   end
 => :palindrome_tester 
2.5.1 :008 > palindrome_tester s
It's not a palindrome.
 => nil 
2.5.1 :009 > palindrome_tester s.downcase
It's a palindrome!
 => nil
4) What is the result of selecting element 7 from the range of letters a through z? What about the same range reversed? Hint: In both cases you will have to convert the range to an array.
2.5.1 :001 > ("a".."z").to_a[7]
 => "h" 
2.5.1 :002 > ("a".."z").to_a.reverse[7]
 => "s" 

Section 4.3.2

1) Using the range 0..16, print out the first 17 powers of 2.
2.5.1 :001 > (0..16).map { |i| 2**i }
 => [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536
2) Define a method called yeller that takes in an array of characters and returns a string with an ALLCAPS version of the input. Verify that yeller(['o', 'l', 'd']) returns "OLD". Hint: Combine map, upcase, and join.
2.5.1 :002 > def yeller(items)
2.5.1 :003?>   itemsUp = items.map { |item| item.upcase }
2.5.1 :004?>   itemsUp.join
2.5.1 :005?>   end
 => :yeller 
2.5.1 :006 > yeller ['o', 'l', 'd']
 => "OLD"
3) Define a method called random_subdomain that returns a randomly generated string of eight letters.
2.5.1 :001 > def random_subdomain
2.5.1 :002?>   ('a'..'z').to_a.shuffle[0..7].join
2.5.1 :003?>   end
 => :random_subdomain 
2.5.1 :004 > random_subdomain
 => "muiqoate" 
2.5.1 :005 > random_subdomain
 => "agvsryho"
4) By replacing the question marks in Listing 4.12 with the appropriate methods, combine split, shuffle, and join to write a function that shuffles the letters in a given string.
2.5.1 :001 > def string_shuffle(s)
2.5.1 :002?>   s.split('').shuffle.join
2.5.1 :003?>   end
 => :string_shuffle 
2.5.1 :004 > string_shuffle("foobar")
 => "boofar" 
2.5.1 :005 > string_shuffle("foobar")
 => "orabof"

Section 4.3.3

1) Define a hash with the keys 'one', 'two', and 'three', and the values 'uno', 'dos', and 'tres'. Iterate over the hash, and for each key/value pair print out "'#{key}' in Spanish is '#{value}'".
2.5.1 :001 > numbers = { :one => 'uno', :two => 'dos', :three => 'tres' }
 => {:one=>"uno", :two=>"dos", :three=>"tres"} 
2.5.1 :002 > numbers.each do |key, value|
2.5.1 :003 >     puts "'#{key}' in Spanish is '#{value}'"
2.5.1 :004?>   end
'one' in Spanish is 'uno'
'two' in Spanish is 'dos'
'three' in Spanish is 'tres'
 => {:one=>"uno", :two=>"dos", :three=>"tres"} 
2) Create three hashes called person1, person2, and person3, with first and last names under the keys :first and :last. Then create a params hash so that params[:father] is person1, params[:mother] is person2, and params[:child] is person3. Verify that, for example, params[:father][:first] has the right value.
2.5.1 :001 > person1 = { :first => 'José', :last => 'Silva' }
 => {:first=>"José", :last=>"Silva"} 
2.5.1 :002 > person2 = { :first => 'Maria', :last => 'Silva' }
 => {:first=>"Maria", :last=>"Silva"} 
2.5.1 :003 > person3 = { :first => 'João', :last => 'Silva' }
 => {:first=>"João", :last=>"Silva"} 
2.5.1 :004 > params = { :father => person1, :mother => person2, :child => person3 }
 => {:father=>{:first=>"José", :last=>"Silva"}, :mother=>{:first=>"Maria", :last=>"Silva"}, :child=>{:first=>"João", :last=>"Silva"}} 
2.5.1 :005 > params[:father][:first]
 => "José"
3) Define a hash with symbol keys corresponding to name, email, and a “password digest”, and values equal to your name, your email address, and a random string of 16 lower-case letters.
2.5.1 :001 > def random_password
2.5.1 :002?>   ('a'..'z').to_a.shuffle[0..15].join
2.5.1 :003?>   end
 => :random_password 
2.5.1 :004 > user = { :name => "Jonadabe", :email => "[email protected]", :password => random_password }
 => {:name=>"Jonadabe", :email=>"[email protected]", :password=>"mgijhxqksyuncorl"}
4) Find an online version of the Ruby API and read about the Hash method merge. What is the value of the following expression?
2.5.1 :001 > { "a" => 100, "b" => 200 }.merge({ "b" => 300 })
 => {"a"=>100, "b"=>300}

Section 4.4.1

1) What is the literal constructor for the range of integers from 1 to 10?
2.5.1 :001 > 1..10
 => 1..10
2) What is the constructor using the Range class and the new method? Hint: new takes two arguments in this context.
2.5.1 :001 > Range.new(1, 10)
 => 1..10
3) Confirm using the == operator that the literal and named constructors from the previous two exercises are identical.
2.5.1 :001 > literal = 1..10
 => 1..10 
2.5.1 :002 > constructor = Range.new(1, 10)
 => 1..10 
2.5.1 :003 > literal == constructor
 => true

Section 4.4.2

1) What is the class hierarchy for a range? For a hash? For a symbol?
2.5.1 :001 > Range.superclass
 => Object 
2.5.1 :002 > Range.superclass.superclass
 => BasicObject 
2.5.1 :001 > Hash.superclass
 => Object 
2.5.1 :002 > Hash.superclass.superclass
 => BasicObject
2.5.1 :001 > Symbol.superclass
 => Object 
2.5.1 :002 > Symbol.superclass.superclass
 => BasicObject 
2) Confirm that the method shown in Listing 4.15 works even if we replace self.reverse with just reverse.
2.5.1 :001 > class Word < String
2.5.1 :002?>   def palindrome?
2.5.1 :003?>     self == reverse
2.5.1 :004?>     end
2.5.1 :005?>   end
 => :palindrome? 
2.5.1 :006 > s = Word.new("level")
 => "level" 
2.5.1 :007 > s.palindrome?
 => true 

Section 4.4.3

1) Verify that “racecar” is a palindrome and “onomatopoeia” is not. What about the name of the South Indian language “Malayalam”? Hint: Downcase it first.
2.5.1 :001 > class String
2.5.1 :002?>   def palindrome?
2.5.1 :003?>     self.downcase == reverse.downcase
2.5.1 :004?>     end
2.5.1 :005?>   end
 => :palindrome? 
2.5.1 :006 > "racecar".palindrome?
 => true 
2.5.1 :007 > "onomatopoeia".palindrome?
 => false 
2.5.1 :008 > "Malayalam".palindrome?
 => true 
2) Using Listing 4.16 as a guide, add a shuffle method to the String class. Hint: Refer to Listing 4.12.
2.5.1 :001 > class String
2.5.1 :002?>   def shuffle
2.5.1 :003?>     self.split('').shuffle.join
2.5.1 :004?>     end
2.5.1 :005?>   end
 => :shuffle 
2.5.1 :006 > "foobar".shuffle
 => "raoofb" 
2.5.1 :007 > "foobar".shuffle
 => "bfroao" 
3) Verify that Listing 4.16 works even if you remove self..
2.5.1 :001 > class String
2.5.1 :002?>   def shuffle
2.5.1 :003?>     split('').shuffle.join
2.5.1 :004?>     end
2.5.1 :005?>   end
 => :shuffle 
2.5.1 :006 > "foobar".shuffle
 => "oroafb" 
2.5.1 :007 > "foobar".shuffle
 => "oabofr"

Section 4.4.4

1) By running the Rails console in the toy app’s directory from Chapter 2, confirm that you can create a user object using User.new.
2.5.1 :001 > user = User.new
 => #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil> 
2) Determine the class hierarchy of the user object.
2.5.1 :002 > user.class
 => User(id: integer, name: string, email: string, created_at: datetime, updated_at: datetime) 
2.5.1 :003 > user.class.superclass
 => ApplicationRecord(abstract) 
2.5.1 :004 > user.class.superclass.superclass
 => ActiveRecord::Base 
2.5.1 :005 > user.class.superclass.superclass.superclass
 => Object 
2.5.1 :006 > user.class.superclass.superclass.superclass.superclass
 => BasicObject 

Section 4.4.5

1) In the example User class, change from name to separate first and last name attributes, and then add a method called full_name that returns the first and last names separated by a space. Use it to replace the use of name in the formatted email method.
class User
  attr_accessor :first_name, :last_name, :email

  def initialize(attributes = {})
    @first_name = attributes[:first_name]
    @last_name = attributes[:last_name]
    @email = attributes[:email]
  end

  def full_name
    "#{@first_name} #{@last_name}"
  end

  def formatted_email
    "#{full_name} <#{@email}>"
  end
end
2.5.1 :001 > require './example_user'
2.5.1 :002 > user = User.new(first_name: "João", last_name: "Silva", email: "[email protected]")
 => #<User:0x000055a0db8734b8 @first_name="João", @last_name="Silva", @email="[email protected]"> 
2.5.1 :003 > user.full_name
 => "João Silva" 
2.5.1 :004 > user.formatted_email
 => "João Silva <[email protected]>"
2) Add a method called alphabetical_name that returns the last name and first name separated by comma-space.
class User
  attr_accessor :first_name, :last_name, :email

  def initialize(attributes = {})
    @first_name = attributes[:first_name]
    @last_name = attributes[:last_name]
    @email = attributes[:email]
  end

  def full_name
    "#{@first_name} #{@last_name}"
  end

  def alphabetical_name
    "#{@last_name}, #{@first_name}"
  end

  def formatted_email
    "#{full_name} <#{@email}>"
  end
end
2.5.1 :001 > require './example_user'
 => true 
2.5.1 :002 > user = User.new(first_name: "João", last_name: "Silva", email: "[email protected]")
 => #<User:0x000055a0db746928 @first_name="João", @last_name="Silva", @email="[email protected]"> 
2.5.1 :003 > user.alphabetical_name
 => "Silva, João"
3) Verify that full_name.split is the same as alphabetical_name.split(', ').reverse.
2.5.1 :004 > user.full_name.split == user.alphabetical_name.split(', ').reverse
 => true
Clone this wiki locally