Ruby output formats differently on dynamic v. static input - ruby

FYI: Fist time I've written Ruby.
We have to write an Address Book program. I have many parts working at this point but have run into something I don't get.
I add contacts to the address book statically before the program runs. Then I try to have a user add a contact dynamically. When I print this address book the contacts added statically are printed according to formatting I expect, but the ones added dynamically are all over the place.
I've added all my code here. It's sort of a big chunk but not too bad...
# Address class
class Address
attr_accessor :street, :city, :state, :zip
# default constructor
def initialize(*args)
if (args.size == 0 )
#street = #city = #state = #zip = ""
elsif (args.size == 4)
#street = args[0]
#city = args[1]
#state = args[2]
#zip = args[3]
else
puts('Constructor takes 0 or 4 arguments. No address information has been set.')
end
end
# string representation of address
def to_s
" " + #street + "\n" + \
" " + #city + " " + #state + ", " + #zip
end
end
# Person class which holds full name, phone, and
# address as an object
class Person
attr_accessor :fname, :lname, :phone, :address
def initialize(*args)
if (args.size == 0 )
#fname = #lname = #phone = ""
#address = Address.new
elsif (args.size == 4)
#fname = args[0]
#lname = args[1]
#phone = args[2]
#address = args[3]
else
puts('Incorrect number of arguments.')
end
end
# returns full name
def full_name
#lname + ", " + #fname
end
def to_s
" " + full_name + "\n" + \
#address.to_s + "\n" + \
" " + #phone
end
end
# AddressBook class to hold addresses
class AddressBook
def initialize
# empty array
#persons = []
end
# adds a person to the address book
def add(person)
#persons += [person]
#persons = #persons.sort{|a,b| by_name(a,b)}
end
def by_name(a,b)
if a.lname == b.lname
a.fname <=> b.fname
else
a.lname <=> b.lname
end
end
# removes a person from the address book
def remove(person)
# Use Array#delete
#persons.delete(person)
end
def to_s
add_book = ""
for p in #persons do
add_book += p.to_s + "\n\n"
end
return add_book
end
end
#
# Here I add three contacts in two different ways
#
#
# FIRST ONE
#
sandy_addr = Address.new
sandy_addr.street = "324 Campus Dr."
sandy_addr.city = "College Park"
sandy_addr.state = "OH"
sandy_addr.zip = "55555"
sandy = Person.new
sandy.fname = "Sandy"
sandy.lname = "Koh"
sandy.phone = "651-442-5710"
sandy.address = sandy_addr
#
# SECOND ONE
#
bill_addr = Address.new('536 Green Rd.', "Saint Paul", "MN", "56545")
bill = Person.new('William', 'Perry', '675-778-6754', bill_addr)
#
# THIRD ONE
#
angela_addr = Address.new('3390 Crookston Rd.', "Miami", "FL", "78654")
angela = Person.new('Angela', 'Anderson', '345-748-1754', angela_addr)
# Contacts added to the Address Book
#addressBook = AddressBook.new
#addressBook.add(sandy)
#addressBook.add(angela)
#addressBook.add(bill)
# Main method loop that runs the program
# Allows you to enter a contact, print a list of
# contacts and exit the program
def loop(addBook)
selection = 0
until(selection == 5)
puts("Wlecome to the Address Book\n")
puts("1. Add a Contact\n")
puts("2. Delete a Contact\n")
puts("3. Retrieve a Contact\n")
puts("4. Print all Contacts\n")
puts("5. Exit Address Book\n")
selection = gets().to_i
if(selection == 1)
addContact(addBook)
elsif(selection == 2)
#delete_contact
elsif(selection == 3)
#retrieve_contact
elsif(selection == 4)
puts(addBook)
end
end
end
def addContact(addBook)
print("Enter First Name: ")
fname = gets()
print("Enter Last Name: ")
lname = gets()
print("Enter Phone Number: ")
phone = gets()
print("Enter Street Address: ")
street = gets()
print("Enter City: ")
city = gets()
print("Enter State: ")
state = gets()
print("Enter Zip Code ")
zip = gets()1
newAddress = Address.new(street, city, state, zip)
newPerson = Person.new(fname, lname, phone, newAddress)
addBook.add(newPerson)
out = %q/#{fname} #{lname} has been added to the Address Book./
puts(out)
end
loop(#addressBook)

The gets method includes the newline so your fname in addContact will be, for example, "Bob\n" rather than the "Bob" that you're expecting. Have a look at chomp.

You problem is probably caused because gets() returns the entire line including the newline character at the end. Try replacing every gets() with gets.chomp.

Related

How to add underscores and remove them when the user inputs the correct letter?

I'm having difficulty in adding underscores in my program. Also what is troubling me is that I can't seem to figure out how to remove the underscores when the user inputs the correct letter.
class Game
attr_reader :guess_count, :is_over, :word_length
def initialize (secret_word)
#secret_word = secret_word
#guess_count = 0
#is_over = false
#word_length = secret_word.length
end
def check_word(guess)
#guess_count += 1
if #secret_word == guess
puts "Congratulations!"
#is_over = true
else
#is_over = false
puts "Sorry, try again!"
end
end
def subtract_guess_count
counter = #word_length - #guess_count
end
end
puts "User 1, What is your secret word?"
secret_word = gets.chomp
anything = Game.new(secret_word)
while !anything.is_over
puts "User 2, Guess the secret word"
guess = gets.chomp
anything.check_word(guess)
if anything.subtract_guess_count == 0
puts "You lose! the correct word was #{secret_word}"
exit!
end
if anything.is_over == false
puts "You have #{anything.subtract_guess_count} left!"
end
end
Major Edit
To create a string of underscores you can do this:
word = ""
1.upto(#secret_word.length) do
word << "_"
end
To replace a character with an underscore (and vice versa) in a ruby string you can use the syntax:
word[i] = "_"
To print a word with spaces between each letter you can use the following:
array = word.split(//)
array.join(" ")
For your code a check_letter function could be useful:
def check_letter (guess)
if (#secret_word[guess])
for i in 0..((#secret_word.length) -1 )
if #secret_word[i] == guess
#progress[i] = guess
end
end
end
show_progress
check_word(#progress)
end
Working code
#! /usr/bin/env ruby
#
class Game
attr_reader :guess_count, :is_over, :word_length, :progress
def initialize (secret_word)
#secret_word = secret_word
#guess_count = 0
#is_over = false
#word_length = secret_word.length
#progress = ""
1.upto(secret_word.length) do
#progress << "_"
end
end
def check_word(guess)
if #secret_word == guess
puts "Congratulations!"
#is_over = true
else
#is_over = false
puts "Sorry, try again!"
end
end
def check_letter (guess)
if (#secret_word[guess])
for i in 0..((#secret_word.length) -1 )
if #secret_word[i] == guess
#progress[i] = guess
end
end
end
show_progress
check_word(#progress)
end
def show_progress
array = #progress.split(//)
word = ""
array.each do |letter|
word << letter + " "
end
puts word
end
def one_less_guess
#guess_count += 1
end
def subtract_guess_count
counter = #word_length - #guess_count
end
end
puts "User 1, What is your secret word?"
secret_word = gets.chomp
anything = Game.new(secret_word)
while !anything.is_over
puts "User 2, Guess the secret word"
guess = gets.chomp
anything.one_less_guess
if guess.length == 1
anything.check_letter(guess)
else
anything.check_word(guess)
end
if anything.subtract_guess_count == 0
puts "You lose! the correct word was #{secret_word}"
exit!
end
if anything.is_over == false
puts "You have #{anything.subtract_guess_count} left!"
end
end

How to make a program that allows the user to label what type of input is provided?

I have a program in Ruby that takes a phone number and is able to pull information from that number. It can tell me the area code, the root, and prefix of the number.
I now want to add another parameter where the user can input that this particular phone number is their cell, work number, etc.
For example:
MyContact1 = Info.new ('(555) 555-5555', :home)
=>(555) 555-5555 (home)
MyContact1.label
=>"home"
MyContact2. = Info.new (' 555-555-5555, "work")
=>(555) 555-5555 (work)
Here is my code:
class PhoneNumber
def initialize (ph)
#ph = ph
#ph.insert(0, '(')
#ph.insert(4, ')')
#ph.insert(5, ' ')
#ph.insert(9, "-")
end
def to_s
#ph
end
def area_code
#ph.slice(0..5)
end
def prefix
#ph.slice(6..8)
end
def root
#ph.slice(10..13)
end
end
print "Please enter a phone number: "
puts a = PhoneNumber.new(gets.strip)
puts a.area_code
puts a.prefix
puts a.root
Just extend your initialize method to accept more arguments:
class PhoneNumber
attr_reader :label
def initialize(ph, label)
#ph = ph
#label = label
# ...
end
# ...
end
Now you can pass a number and a label, and you have a method defined to retrieve this label:
a = PhoneNumber.new('555-555-5555', :home)
#=> #<PhoneNumber:0x007fd7cb149fb0 #label=:home, #ph="(555) -55-5-5555">
[8] pry(main)> a.label
#=> :home

Comparing strings on Ruby

I'm new to programming in Ruby and I decided to learn to build a hangman game, but I have a problem when comparing two strings, one that comes from a gets (If I do it for me code works normal) and one that is defined.
this is my codes:
this is my 'main':
require_relative("Ahorcado")
juego = Ahorcado.new()
juego.decirPalabra
while juego.hayVidas?
juego.imprimir
lectura = gets
lectura = lectura.to_s;
juego.preguntar lectura
end
puts juego.resultado
And the Ahorcado.rb
class Ahorcado
def loadVariables
#palabras = ["java","ruby","python","go"]
#adivinados = []
#gano = false
#vidas = 7
end
def initialize
loadVariables();
#palabra = #palabras[rand(#palabras.length)].split("")
puts "Se ha iniciado un juego"
#tamano = #palabra.length
puts "Existen #{#tamano} letras"
iniciar
end
def decirPalabra
puts #palabra
end
def preguntar letra
#vidas -= 1
letra = letra.to_s
temp = #palabra.join
puts temp.eql?(letra) # -> Allways false
if letra == #palabra.join then
#gano = true
puts "gano"
else
for i in 0...#tamano
if letra.eql?(#palabra[i]) then #Allways false
#adivinados[i] = true
#vidas += 1
else
puts "Incorrecto intente otra vez"
end
end
end
end
def comparar letra
#temp = letra;
puts #temp == #palabra[0]
end
def iniciar
for i in (0...#tamano)
#adivinados[i] = false;
end
end
def hayVidas?
return #vidas > 0
end
def resultado
#gano;
end
def imprimir
for i in (0...#tamano)
if #adivinados[i] then
print #palabra[i]+" "
else
print "_ "
end
end
puts
end
end
Thanks for yours answers, and sorry if i wrote bad some sentences, i don't speak english
When you do a "gets", lectura contains newline character in the end. Trying doing a "chomp" on lectura :-
lectura = lectura.chomp
and try again. So that all the newline characters are removed. You can also use "bytes" to see the exact characters in your string for debugging purposes.
puts lectura.bytes
Refer:- http://ruby-doc.org/core-2.0/String.html#method-i-chomp

Limitation on number of result in search engine scraping

I am scraping bing search engine using Mechanize. But I get only max 200 results programmatically if I execute same search query on bing.com it returns 1400 results. What is gotcha here?
def generate_profiles_from_group(options={})
raise "TypeError", "Invalid Arguments" unless options.is_a? Hash
group = options[:group] if options.has_key? :group
query = build_query(options)
page = bing_search(query)
contacts_stack = extract_contacts_from_bing_page page: page
bing_links_stack = bing_links page
return contacts_stack, bing_links_stack
end
def extract_contacts_from_bing_page(options)
page = options[:page]
company = options[:company] || nil
title = options[:title] || nil
stack = []
while true
page.parser.search('h3 a').each do |cite|
text = cite.text
unless text == ""
name_array = text.split(' ')
if name_array.size >= 2
name = name_array[0]+' '+name_array[1]
unless name=~/[^a-zA-Z',\s]/i
stack << {name: name, company: company, title: title}
end
end
end
end
keyw = page.parser.xpath('//*[contains(concat( " ", #class, " " ), concat( " ", "sb_pagN", " " ))]').text
break if keyw == ""
page = #agent.click page.link_with(text: keyw )
end
stack
end
def bing_links page
stack = []
while true
page.parser.xpath('//cite').each do |cite|
stack << cite.text unless cite.text == ""
end
keyw = page.parser.xpath('//*[contains(concat( " ", #class, " " ), concat( " ", "sb_pagN", " " ))]').text
break if keyw == ""
sleep(10+rand(40))
page = #agent.click page.link_with(text: keyw )
end
stack
end
def build_query(options)
name = options[:name] if options.has_key? :name
title = options[:title] if options.has_key? :title
company = options[:company] if options.has_key? :company
group = options[:group] if options.has_key? :group
if name && company
return "site:linkedin.com \"#{name}\" \"at #{company}\""
elsif name && title
return "site:linkedin.com \"#{name}\" \"#{title}\""
elsif title && company
return "site:linkedin.com/ \"#{title}\" \"at #{company}\""
elsif group
return "site:linkedin.com \"groups and association\" + \"#{group}\""
end
end

Help! check_in': undefined method `push' for nil:NilClass (NoMethodError)

Hi Im getting an core error which is really standard I suppose in Ruby but dont know what to make of it. I have a program that I have written. Its purpose is to register guests at a camping. You have a menu with 5 different options. 1. Checkin. When i do this I get a undefined method generateParkingLot' for #<Camping:0x10030a768> (NoMethodError)
When I choose Checkout I get a undefined local variable or methoddeparture' for Menu:Class (NameError).
So please i someone has a clue to my problem it would be great. I will here paste all my code. The code is separated in different files and I have used require for the different files. Here though I will paste all the code in one trace. Thankful for all help.
-Sebastien
require 'guest'
require 'parking_lot'
class Camping
attr_accessor :current_guests, :parking_lots, :all_guests, :staticGuests
def initialize(current_guests, parking_lots, all_guests, staticGuests)
#current_guests = Array.new()
# initiera husvagnsplatserna
#parking_lots = Array.new(32)
32.times do |nr|
#parking_lots[nr] = Parking_Lot.new(nr)
#staticGuests = Array[
Guest.new("Logan Howlett", "Tokyo", "07484822",1, #parking_lots[0]),
Guest.new("Scott Summers", "Chicago", "8908332", 2, #parking_lots[1]),
Guest.new("Hank Moody", "Boston", "908490590", 3, #parking_lots[2]),
Guest.new("Jean Grey", "Detroit", "48058221", 4, #parking_lots[3]),
Guest.new("Charles Xavier","Washington DC", "019204822",5, #parking_lots[4])
]
end
#all_guests = []
#staticGuests.each do |guest|
#current_guests[guest.plot.nr] = guest
#all_guests.push(guest)
end
end
def to_s
# creates an empty string
list = " "
# loop from 1 to 32
(1..32).each do |n|
if (!#current_guests[n-1].nil?)
list += #current_guests[n-1].to_s
else
# else adds the text "Vacant"
list += n.to_s + ": Vacant!\n"
end
return list
end
def generateParkingLot
randomNr = 1+rand(32)
# exists a guest at the (0-based) position?
if (!#current_guests[randomNr-1].nil?)
# if so generate a new figure
generateEmpty(array)
else
# returns the generated number
return randomNr
end
end
end
end
class Guest
attr_accessor :firstname, :lastname, :address, :phone, :departure
attr_reader :arrived, :plot
def initialize (firstName, lastName, address, phone, plot)
#firstName = firstName
#lastName = lastName
#address = address
#phone = phone
#arrived = arrived
#plot = plot
end
def to_s
"Personal information:
(#{#firstName}, #{#lastName}, #{#address}, #{#phone}, #{#arrived}, #{#departure}, #{#plot})"
end
end
require 'ruby_camping'
require 'camping_guests'
class Main
if __FILE__ == $0
$camping = Camping.new(#current_guests, #all_guests, #parking_lots,#staticGuests)
puts "\n"
puts "Welcome to Ruby Camping!"
while (true)
Menu.menu
end
end
end
require 'date'
require 'camping_guests'
require 'guest'
class Menu
def initialize(guests = [])
#camping = Camping.new(guests)
end
def self.menu
puts "---------------------------"
puts " Menu"
puts " 1. Checkin"
puts " 2. Checkout"
puts " 3. List current guests"
puts " 4. List all guests"
puts " 5. Exit\n"
puts ""
puts " What do you want to do?"
puts "---------------------------"
print ": "
action = get_input
do_action(action)
end
# fetches menu choice and returns chosen alternativ
def self.get_input
input = gets.chomp.to_i
while (input > 5 || input < 1) do
puts "Ooups, please try again."
input = gets.chomp.to_i
end
return input
end
def self.do_action(action)
case action
when 1:
check_in
when 2:
check_out
when 3:
puts $camping.current_guests
when 4:
puts $camping.all_guests
when 5:
puts "You are now leaving the camping, welcome back!"
exit
end
end
def self.check_in
puts "Welcome to the checkin"
puts "Please state your first name: "
firstName = gets.chomp
puts "Please state your last name:"
lastName = gets.chomp
puts "Write your address: "
address = gets.chomp
puts "and your phone number: "
phone = gets.chomp
puts "finally, your arrival date!"
arrived = gets.chomp
newPLot = $camping.generateParkingLot
newGuest = Guest.new(firstName, lastName, address, phone,arrived,$camping.parking_lots[newPLot-1])
$camping.current_guests[newPLot-1] = newGuest
#all_guests.push(newGuest)
puts "The registration was a success!! You have received the " + newPLot.to_s + "."
end
def self.check_out
puts "Welcome to checkout!"
puts $camping.all_guests
puts "State plot of the person to checkout!"
plot = gets.chomp.to_i
puts "Ange utcheckningsdatum: "
departureDate = gets.chomp.to_i
guest = $camping.current_guests[plot-1]
#departure = departure
guest.departure = departureDate
guestStayedDays = departureDate - guest.arrived
guest.plot.increase(guestStayedDays)
puts guest
$camping.current_guests[plot-1] = nil
end
end
class Parking_Lot
attr_accessor :nr
attr_reader :electricity_meter
def initialize (nr)
#nr = nr
#electricity_meter = 4000-rand(2000)
end
def increase_meter(days)
generatedUse = (10+rand(70))*days
puts "Increases the meter with " + generatedUse.to_s + " kWh."
#electricity_meter += generatedUse
end
def to_s
"Plot #{#nr+1} Electricity meter: #{#electricity_meter} kWh"
end
end
It looks (although I haven't tried this out) like some of your your 'end's are wrong.
The one which is causing your first error (generateParkingLot undefined) is that generateParkingLot is actually defined inside to_s, so you need an extra 'end' at the end of your to_s method.
As for the second error (departure not recognised), the folowing line in self.check_out is at fault:
#departure = departure
because there is no 'departure' variable. (Perhaps you meant DepartureDate?). I suspect there may be a few other issues with this code, but I'm afraid I don't really have time to check now.
One I noticed was that when you have
32.times do |nr|
#parking_lots[nr] = Parking_Lot.new(nr)
I think you might want to end that, either with an 'end' or curly brackets, e.g.
32.times do |nr|
#parking_lots[nr] = Parking_Lot.new(nr)
end
Although that would make your other blocks not match.. In general, just try and make sure your blocks are all defined properly (e.g. everything has a matching end).

Resources