Size Reading and Writing to File and conditional statements - ruby

Beginner learning Ruby. Was doing an exercise on reading and writing to file.
name_number = {
}
File.open("book.txt", 'a') do |file|
name_number.each do |name, number|
file.write ("- #{name} #{number}\n")
end
file.close
end
File.open("book.txt", "r") do |file|
if file.size < 1
puts "There are no people in the book."
end
File.open("book.txt", "r") do |file|
puts file.read
end
end
So it outputs "There are no people in the book." when the file is empty.
SO if we add some people...
name_number = {
"Bill" => 87987,
"Kevin" => 78912
}
File.open("book.txt", 'a') do |file|
name_number.each do |name, number|
file.write ("- #{name} #{number}\n")
end
file.close
end
I was trying to figure out how to get it to say
"There is one person" for 1
and "There are some people" for anything over 1.
I thinking I need an elsif statement something like this, (but obviously this isn't working, but maybe you can see what I'm thinking of trying to achieve?).
File.open("book.txt", "r") do |file|
if file.size < 1
puts "There are no people in the book."
elsif file.size == 1
puts "There is an entry in the book."
elsif file.size == 2
puts "There are two entries in the book"
end
File.open("book.txt", "r") do |file|
puts file.read
end
end
I'm definitely missing something. I was wondering if anyone could point me in the right direction?

file.size gives you the number of bytes. You probably want file.readlines.size

To obtain the number of lines in the file you need to read it. If possible, you want to avoid reading the file more than once.
Assuming the file is not excessively large, you could gulp it into an array, using IO::readlines:
arr = File.readlines("book.txt")
puts case arr.size
when 0
"There are no people in the book."
when 1
"There is one person in the book"
when 2
"There are two people in the book"
else
"There are some entries in the book"
end
puts arr
Alternatively, you could gulp it into a string, using IO::read:
str = File.read("book.txt")
puts case str.count("\n")
when 0
"There are no people in the book."
when 1
"There is one person in the book"
when 2
"There are two people in the book"
else
"There are some entries in the book"
end
puts str
If the file is so large that you need to read it one line at a time you can use IO::foreach. This does require two passes through the file, however.
puts case File.foreach("book.txt").count
when 0
"There are no people in the book."
when 1
"There is one person in the book"
when 2
"There are two people in the book"
else
"There are some entries in the book"
end
File.foreach("book.txt") { |line| puts line }

I found if I used .count with readlines I was able to solve my problem!
updated code
File.open("book.txt", "r") do |file|
number = file.readlines.count
if number < 1
puts "There are no people in the book."
elsif number == 1
puts "There is one person in the book"
File.open("book.txt", "r") do |file|
puts file.read
end
elsif number == 2
puts "There are two people in the book."
File.open("book.txt", "r") do |file|
puts file.read
end
elsif number >= 3
puts "There are some entries in the book."
File.open("book.txt", "r") do |file|
puts file.read
end
end
end

Related

How to sum variables values RUBY

First, I am new to ruby so please be gentle hehe.
I have a school project where the assignment is to calculate the total cost of a project. In my code, the user is giving the variables some input. Later on, I want to show the total of all these inputs. (the inputs is number)
So basically I need to add them up and it needs to give me a sum of them.
How do I do that?
Hope you amazing people can help me:)
Here is my code:
file = File.new("testing.txt", "a")
class Project
def call_acc
prompt = "> "
puts
puts "What is the salary for an accountant?"
print prompt
while #accountant = gets.chomp
if !/\A\d+\z/.match(#accountant)
puts
puts "Error: Only use numbers, please try again"
print prompt
else
break
end
end
end
def call_dev
prompt = "> "
puts
puts "What is the salary for an developer?"
print prompt
while #developer = gets.chomp
if !/\A\d+\z/.match(#developer)
puts
puts "Error: Only use numbers, please try again"
print prompt
else
break
end
end
end
def call_mana
prompt = "> "
puts
puts "What is the salary for the top management?"
print prompt
while #management = gets.chomp
if !/\A\d+\z/.match(#management)
puts
puts "Error: Only use numbers, please try again"
print prompt
else
break
end
end
end
def call_office
prompt = "> "
puts
puts "What is the total office rent for the project?"
print prompt
while #office = gets.chomp
if !/\A\d+\z/.match(#office)
puts
puts "Error: Only use numbers, please try again"
print prompt
else
break
end
end
end
def call_lunch
prompt = "> "
puts
puts "What is the daily cost for lunch per person?"
print prompt
while #lunch = gets.chomp
if !/\A\d+\z/.match(#lunch)
puts
puts "Error: Only use numbers, please try again"
print prompt
else
break
end
end
end
def call_utilites
prompt = "> "
puts
puts "What is the total cost for utilites (internet, subscriptions etc)?"
print prompt
while #utilites = gets.chomp
if !/\A\d+\z/.match(#utilites)
puts
puts "Error: Only use numbers, please try again"
print prompt
else
break
end
end
end
def call_show
prompt = "> "
puts "____________________________________"
puts
puts "Is this information correct?"
puts
puts "Accountant salary (per hour): #{#accountant}kr\nDevelepor salary (per hour): #{#developer}kr\nTop management salary (per hour): #{#management}kr"
puts
puts "Total rent cost of office space: #{#office}kr\nLunch per person per day: #{#lunch}kr\nTotal cost of utilites #{#utilites}kr"
puts
puts "____________________________________"
puts "Yes or No"
print prompt
while user_imput = gets.chomp.upcase
case user_imput
when "YES"
file = File.new("testing.txt", "a")
file.puts("Account salary: #{#accountant}kr\nDeveloper selary: #{#developer}kr\nTop management salary #{#management}kr\nTotal rent cost: #{#office}kr\nLunch per person #{#lunch}kr\nUtilites cost #{#utilites}kr")
file.close
puts
puts "The information has now been stored"
puts "____________________________________"
break
when "NO"
puts
puts "The information has not been stored. Exiting application"
puts "____________________________________"
abort
else
puts
puts "Please either write Yes or No"
print prompt
end
end
end
def call_total
prompt = "> "
puts
puts "________Your information_______"
puts
puts "Accountant salary (per hour): #{#accountant}kr\nDevelepor salary (per hour): #{#developer}kr\nTop management salary (per hour): #{#management}kr"
puts
puts "Total rent cost of office space: #{#office}kr\nLunch per person per day: #{#lunch}kr\nTotal cost of utilites #{#utilites}kr"
puts
puts "________Total cost of project________"
puts
puts ?????????#accountant + #developer??????????????+
puts
end
project = Project.new
require 'io/console'
select = 0
prompt = "> "
puts
puts
puts "Welcome to KEA"
puts "____________________________________"
loop do(select != 7)
puts
puts "Press 1 to calculate"
puts "____________________________________"
select = STDIN.getch.to_i
if (select == 1)
project.call_acc
project.call_dev
project.call_mana
project.call_office
project.call_lunch
project.call_utilites
project.call_show
project.call_total
break
else
puts
puts "Invalid input. Please try again"
puts "____________________________________"
end
end
end
Answering the question stated in title:
numbers =
loop.inject([]) do |acc, _|
val = gets.to_i
break acc unless val > 0
acc << val
end
numbers.reduce(:+)

Handling Ruby Case Statement

I tried to rewrite the "if/else statement" in the following piece of code by replacing it with a "case" statement, and I am deadly stuck with it for a few hours - what am I missing?
puts "Welcome to 'Guess My Number!'"
print "What is your name?"
input = gets
name = input.chomp
puts "Welcome, #{name.upcase!}!"
puts "I've got a random number between 1 and 100!"
puts "Can you guess it?"
target = rand(100) + 1
num_guesses = 0
guessed_it = false
until num_guesses == 10 || guessed_it
remaining_guesses = 10 - num_guesses
puts "You've got #{remaining_guesses.to_s} guesses left!"
print "Make a guess, put down a number: "
guess = gets.chomp.to_i
num_guesses = num_guesses + 1
end
puts case verification
when guess < target
then "Ooops. Your guess was LOW."
when guess > target
then "Ooops. Your guess was HIGH."
when guess < -1
then puts "Oooops. You have entered a number lower that 1!"
when guess > 100
then puts "Oooops. You have entered a number higher than 100!"
when guess =~ /^([w])/
then puts "Ooops. Looks like you have entered a non numeric
value!"
when guess == String
then puts "Oooops! Looks like you have entered a non numeric
value"
when guess == target
then puts "Good job, #{name}!"
puts "You guessed my number in #{num_guesses} guesses!"
guessed_it = true
end
unless guessed_it
puts "Sorry, you didn't get my number. My number was #{target}."
end
The "case statement" was used to replace and enhance the logic of the following if else statement:
if guess < target
puts "Ooops. Your guess was LOW."
elsif guess > target
puts "Ooops. Your guess was HIGH."
elsif guess == target
puts "Good job, #{name}!"
puts "You guessed my number in #{num_guesses} guesses!"
guessed_it = true
end
Your problem is that you're using the form of case with the optional condition, but you're using when clauses as if you were using the condition-less case.
puts case
when guess < target
"Ooops. Your guess was LOW."
should work.
Further explanation:
using case without a condition, the earliest when branch with a truthy expression is executed. This is what you want here.
But you were using case with verification. In this case, all branches are compared to verification, and the first branch where verification === branch condition is true is executed.
Since in your example I'm guessing verification is always nil, and all your branches' conditions are always true or false, no branch will ever get executed.
You can use a case statement like so:
class String
def green;"\e[32m#{self}\e[0m";end
def yellow;"\e[33m#{self}\e[0m";end
def cyan;"\e[36m#{self}\e[0m";end
def bg_blue;"\e[44m#{self}\e[0m";end
def bold;"\e[1m#{self}\e[22m";end
def underline;"\e[4m#{self}\e[24m";end
def border(num);"\n#{'-' * num}\n#{self}\n#{'-' * num}\n";end
end
puts;puts "Welcome to 'Guess My Number!'".bold.bg_blue;puts
print 'What is your name? '.green
name = gets.chomp
puts "\nWelcome, #{name.upcase!}!\n".cyan.underline
puts "I've got a random number between 1 and 100!\nCan you guess it?".border(44)
target = rand(100) + 1
num_guesses = 0
guessed_it = false
until num_guesses == 10 || guessed_it
remaining_guesses = 10 - num_guesses
puts "\nYou've got #{remaining_guesses} guesses left!\n"
puts;print 'Make a guess, put down a number: '
guess = gets.chomp
case guess.to_i
when (1...target)
puts 'Ooops. Your guess was LOW'.yellow.border(26)
when (target + 1..100)
puts 'Ooops. Your guess was HIGH'.yellow.border(26)
when target
puts; puts; puts
puts "Good job, #{name}!".bold.green
puts 'You guessed my number in ' + "#{num_guesses} guesses!".cyan
puts; puts; puts
guessed_it = true
else
puts "Oooops. You didn't enter a number from 1 to 100".yellow.border(47); puts
end
num_guesses += 1
end
unless guessed_it
puts;puts;puts "Sorry, you didn't get my number. My number was #{target}.".yellow;puts
end
Thanks a lot to everybody! With your invaluable help I managed to regain patience in my soul and satisfaction from this small task :) My mistake is that I violated the rules of common sense by trying to run several pieces of code in a wrong sequence. I moved the case statement inside the until loop and now all I have to do is correct the mistakes in particular when/then statements. It works :)
until num_guesses == 10 || guessed_it
remaining_guesses = 10 - num_guesses
puts "You've got #{remaining_guesses.to_s} guesses left!"
print "Make a guess, put down a number: "
guess = gets.chomp.to_i
num_guesses = num_guesses + 1
puts case
when guess < target
then "Ooops. Your guess was LOW."
when guess > target
then "Ooops. Your guess was HIGH."
when guess < -1
then puts "Oooops. You have entered a number lower that 1!"
when guess > 100
then puts "Oooops. You have entered a number higher than 100!"
when guess =~ /^([w])/
then puts "Ooops. Looks like you have entered a non numeric value!"
when guess == String
then puts "Oooops! Looks like you have entered a non numeric value"
when guess == target
then puts "Good job, #{name}!"
puts "You guessed my number in #{num_guesses} guesses!"
guessed_it = true
end
end
unless guessed_it
puts "Sorry, you didn't get my number. My number was #{target}."
end

Program won't output what it's supposed to

I am following tutorial and I can't figure out what I am doing wrong. It's outputting everything up to if down
puts "we are going down the cave" I can't get it to output the else statement or anything afterwards. I am just learning and the answer is probably really simple.
puts("Would you like to go up or down?")
user_input = gets()
down = "cave"
up = "mountain"
if down
puts "we are going down the cave"
else up
puts "we are going up the mountain"
puts("Pick a number between 1 and 100")
LOCATION = "cave"
NUMBER = gets()
if NUMBER == 100
puts "You've achieved enlightment in the #{LOCATION}! Spread joy around the world!"
elsif NUMBER >= 50 > 100
puts "There are #{NUMBER} goblins in the #{LOCATION}. WE MUST FIGHT!"
elsif NUMBER > 20 > 50
puts "There is still hope that we will make it to the #{LOCATION}. before the #{NUMBER} Snufflebums get us!"
else NUMBER <= 20
puts "We have conquered the Goon Squad of the #{LOCATION}.. It only took us #{NUMBER} years!!!"
end
end
down is "cave" and is always 'truthy' so if down is always, always true. You want to be testing the user_input, not the variable down
What I think you want is...
user_input = gets.chomp
# you need the chomp to remove the return character
down = "cave"
up = "mountain"
if user_input == down
puts "we are going down the cave"
elsif user_input == up
puts "we are going up the mountain"
end
# you need the end statement, otherwise everything that follows is part of the "else"
And remove the last end

Two Parts, If I read in a file that's formatted like an array, can it be treated as such? And another about searching strings

I have two questions with this sample of code i'm about to drop in. The first deals with
person = gets.chomp
puts "Good choice! Here are #{person}'s tags!"
person = "#{person}.txt"
file = File.open(person)
while line = file.gets do
puts line
end
If the file that's opened is formatted exactly like an array (in this case its actually an array ruby has previously written to a txt file lets say, ["Funny", "Clever", "Tall", "Playboy"] ) Is there an easy way just make that an array again? Nothing I tried seemed to work.
The second deals with this
puts "Which tag would you like to vote on?"
tag = gets.chomp
if File.open(person).grep(/tag/) == true
puts "Found it!"
else
puts "Sorry Nope"
end
#f = File.new("#{person}")
#text = f.read
#if text =~ /tag/ then
#puts "Alright, I found that!"
#else
#puts "Can't find that sorry."
#exit
#end
This section just doesn't seem to be working. It never finds the string, also the commented out attempt didn't work either. I wasn't sure if the grep line actually returned a true or false value, but the commented out part avoids that and still doesn't return the string. I tried formatting the input with "" around it and every possible configuration ruby might be looking for but it always passes to the negative result.
and for the sake of completeness here is all the code.
puts "This is where you get to vote on a Tag!"
puts "Whose Tags would you like to alter?"
Dir.glob('*.txt').each do|f|
puts f[0..-5]
end
puts ".........."
person = gets.chomp
puts "Good choice! Here are #{person}'s tags!"
person = "#{person}.txt"
file = File.open(person)
while line = file.gets do
puts line
end
puts "Which tag would you like to vote on?"
tag = gets.chomp
if File.open(person).grep(tag) == true
puts "Found it!"
else
puts "Sorry Nope"
end
#f = File.new("#{person}")
#text = f.read
#if text =~ /tag/ then
#puts "Alright, I found that!"
#else
#puts "Can't find that sorry."
#exit
#end
Part 1 - Parse a string into an array
Use JSON.parse:
require 'json'
JSON.parse('["Funny", "Clever", "Tall", "Playboy"]')
# => ["Funny", "Clever", "Tall", "Playboy"]
Part 2 - Find a string in a file
As bjhaid recommended, use File.read and include?:
File.read(person).include?(tag)
This returns either true or false.
change:
if File.open(person).grep(tag) == true
puts "Found it!"
else
puts "Sorry Nope"
end
to
if File.read(person).include?(tag)
puts "Found it!"
else
puts "Sorry Nope"
end
File#open returns an IO object so you can't call grep on it like you would have done on an array, so I would suggest File.read which returns a String object that you can now call include? on

Ruby script need fix

I'm having a problem with my ruby script. If anyone could help, I'd really appreciate it. The problem is that the number is stuck between 1-2; where 2 is too high and 1 is too low. The guesses should be integers only.
#!/usr/bin/ruby
def highLow(max)
again = "yes"
while again == "yes"
puts "Welcome to the High Low game"
playGame(max)
print "Would you like to play again? (yes/no): "
again = STDIN.gets.chomp
if again == 'no'
puts "Have a nice day, Goodbye"
end
end
end
#This method contains the logic for a single game and call the feedback method.
def playGame(max)
puts "The game gets played now"
puts "I am thinking of a number between 1 and #{max}." #It show what chosen by user
randomNumber = rand(max)+ 1
print "Make your guess: "
guess = STDIN.gets.chomp
feedback(guess, randomNumber)
end
#Start while loop
#Logic for feedback method. It's ganna check the guess if it's high or low.
def feedback(guess, randomNumber)
count = 1
while guess.to_i != randomNumber
count = count + 1
if guess.to_i < randomNumber
print "That's too low. Guess again: "
else
print "That's too high. Guess again: "
end
guess = STDIN.gets.chomp
end
puts "Correct! You guessed the answer in #{count} tries!"
end
highLow(ARGV[0])
Change your last line to this:
highLow(ARGV[0].to_i)
The ARGV array contains all the passed in arguments as strings, so you have to cast it to integer.

Resources