Conversion to integer isn't executing? - ruby

i have this code :
#require_relative '../lib/hackex/net/typhoeus'
require_relative '../lib/hackex'
require 'rubygems'
require 'faker'
print "how many farms do you want : "
choice = gets.chomp
choice.to_i
check = choice.is_a?(Integer)
puts check
if choice > 250
puts "Error! you cannot make more than 250 farms at once"
elsif choice < 250
puts "Error! you have to make at least one farm..."
elsif choice.is_a?(Integer) == false
puts "Error, something went wrong !"
else
puts "making #{choice} acounts ! ! !"
cnt = 1
while choice>cnt
gen = Faker::Name.first_name + Faker::Name.last_name
path=("created1.txt")
email = gen+'#gmail.com'
password = Faker::Internet.password(8)
username = gen.to_s+'/>'
puts HackEx::Request.Do(http,HackEx::Request.CreateUser(username, email, password, facebook_id = nil))
cnt +=1
open(path, 'a') { |f|
f << "#{email};"
f << "#{password}"
f << "\n"
}
puts "Account created!"
puts "#{choice - cnt} accounts remaining!"
end
end
i am trying to determing if the choice is an integer... i did the .to_i on choice, but it returns false, meaning its not an integer, its a string, why isnt it switching ?
ps : i do not get any errors, and the rest of the code works fine, except for the if part

choice.to_i returns an integer, but does not change choice. If you want choice to be changed to the integral value of the old choice, you need to reassign it explicitly:
choice = choice.to_i

Quoting the doc of String::to_i, emphasis is mine
to_i(base=10) → integer
Returns the result of interpreting leading characters in str as an
integer base base (between 2 and 36).
So you have to assign the return to something, or itself:
choice = choice.to_i

Related

why is my input method for the hangman game failing to function properly?

I have this method where it gets an input from the user and it checks it against a while condition. if the user inputted anything that isnt a string or if the user inputted a character that was longer than 1 the method would prompt the user again for a valid input, basically adhering to the hangman rules. Heres the code
class Hangman
def initialize
dictionary = File.open('5desk.txt',"r")
line = dictionary.readlines
#word = line[rand(1..line.length)]
#length = #word.length
random = #word.length - rand(#word.length/2)
random.times do
#word[rand(#word.length)] = "_"
end
end
This method fails to function properly.
def get_input
puts #word
puts "Letter Please?"
#letter = gets.chomp
while !#letter.kind_of? String || #letter.length != 1
puts "Invalid input,try again!"
#letter = gets.chomp
end
end
end
Game = Hangman.new
Game.get_input
class Hangman
Stop right there! Why create a class considering that you would only create a single instance of it? There's no need for one. A few methods and one instance variable are sufficient.
Generate secret words randomly
I assume the file '5desk.txt' contains one secret words per line and you will be selecting one randomly. So begin by gulping the entire file into an array held by an instance variable (as opposed to reading the file line-by-line). I assume '5desk.txt1' contains the three words shown below.
#secret_words = File.readlines('5desk.txt', chomp: true)
#=> ["cat", "violin", "whoops"]
See the doc for the class method IO::readlines1,2. The option chomp: true removes the newline character from the end of each line.
This method closes the file after it has been read. (You used File::open. When doing so you need to close the file when you are finished with it: f = File.open(fname)...f.close.)
You need a method to randomly choose a secret_word.
def fetch_secret_word
#secret_words.sample
end
fetch_secret_word
#=> "violin"
See Array#sample. You could have instead used
#secret_words[rand(#secret_words.size)]
See Kernel#rand. The first and last words in #secret_words are #secret_words[0] and #secret_words[#secret_words.size-1]. Therefore, where you wrote
#word = line[rand(1..line.length)]
it should have been
#word = line[rand(0..line.length-1)]
which is the same as
#word = line[rand(line.length)]
Now let's create a method for playing the game, passing an argument that equals the maximum number of incorrect guesses the player has before losing.
def play_hangman(max_guesses)
First get a secret word:
secret_word = fetch_secret_word
Let us suppose that secret_word #=> "violin"
Initialize objects
Next, initialize the number of incorrect guesses and an image of the secret word:
incorrect_guesses = 0
secret_word_image = "-" * secret_word.size
#=> "------"
So we now have
def play_hangman(max_guesses)
secret_word = fetch_secret_word
incorrect_guesses = 0
secret_word_image = "-" * secret_word.size
Loop over guesses
Now we need to loop over the player's guesses. I suggest you use Kernel#loop, in conjuction with the keyword break for all your looping needs. (For now, forget about while and until, and never use for.) The first thing we will do in the loop is to obtain the guess of a letter from the player, which I'll do by calling a method:
loop do
guess = get_letter(secret_word_image)
...<to be completed>
end
def get_letter(secret_word_image)
loop do
puts secret_word_image
print "Gimme a letter: "
letter = gets.chomp.downcase
break letter if letter.match?(/[a-z]/)
puts "That's not a letter. Try again."
end
end
guess = secret_letter(secret_word_image)
#=> "b"
Here this method returns "b" (the guess) and displays:
------
Gimme a letter: &
That's not a letter. Try again.
------
Gimme a letter: 3
That's not a letter. Try again.
------
Gimme a letter: b
See if letter guessed is in secret word
Now we need to see which if any of the hidden letters equal letter. Again, let's make this a method3.
def hidden_letters(guess, secret_word, secret_word_image)
(0..secret_word.size-1).select do |i|
guess == secret_word[i] && secret_word_image[i] = '-'
end
end
Suppose guess #=> "i". Then:
idx = hidden_letters(guess, secret_word, secret_word_image)
#=> [1,4]
There are two "i"'s, at indices 1 and 4. Had there been no hidden letters "i" the method would have returned an empty array.
Before continuing let's look at our play_hangman is coming along.
def play_hangman(max_guesses)
secret_word = fetch_secret_word
incorrect_guesses = 0
secret_word_image = "-" * secret_word.size
loop do
unless secret_word_image.include?('-')
puts "You've won. The secret word is '#{secret_word}'!"
break
end
guess = get_letter(secret_word_image)
idx = hidden_letters(guess, secret_word, secret_word_image)
...<to be completed>
end
Process a guess
We now have to carry out one course of action if the array idx is empty and another if it is not.
case idx.size
when 0
puts "Sorry, no #{guess}'s"
incorrect_guesses += 1
if incorrect_guesses == max_guesses
puts "Oh, my, you've used up all your guesses, but"
puts "we'd like you take home a bar of soap"
break
else
puts idx.size == 1 ? "There is 1 #{guess}!" :
"There are #{idx} #{guess}'s!"
idx.each { |i| secret_word_image[i] = guess }
if secret_word_image == secret_word
puts "You've won!! The secret word is '#{secret_word}'!"
break
end
end
Complete method
So now let's look at the full method (which calls fetch_secret_word, get_letter and hidden_letters).
def play_hangman(max_guesses)
secret_word = fetch_secret_word
incorrect_guesses = 0
secret_word_image = "-" * secret_word.size
loop do
guess = get_letter(secret_word_image)
idx = hidden_letters(guess, secret_word, secret_word_image)
case idx.size
when 0
puts "Sorry, no #{guess}'s"
incorrect_guesses += 1
if incorrect_guesses == max_guesses
puts "Oh, my, you've used up all your guesses,\n" +
"but we'd like you take home a bar of soap"
return
end
else
puts idx.size == 1 ? "There is 1 #{guess}!" :
"There are #{idx.size} #{guess}'s!"
idx.each { |i| secret_word_image[i] = guess }
if secret_word_image == secret_word
puts "You've won!! The secret word is '#{secret_word}'!"
return
end
end
end
end
Play the game!
Here is a example play of the game.
play_hangman(4)
------
Gimme a letter: #
That's not a letter. Try again.
------
Gimme a letter: e
Sorry, no e's
------
Gimme a letter: o
There is 1 o!
--o---
Gimme a letter: i
There are 2 i's!
-io-i-
Gimme a letter: l
There is 1 l!
-ioli-
Gimme a letter: v
There is 1 v!
violi-
Gimme a letter: r
Sorry, no r's
violi-
Gimme a letter: s
Sorry, no s's
violi-
Gimme a letter: t
Sorry, no t's
Oh, my, you've used up all your guesses,
but we'd like you take home a bar of soap
1 The class File has no (class) method readlines. So how can we write File.readlines? It's because File is a subclass of IO (File.superclass #=> IO) and therefore inherits IO's methods. One commonly sees IO class methods invoked with File as the receiver.
2 Ruby's class methods are referenced mod::meth (e.g., Array::new), where mod is the name of a module (which may be a class) and meth is the method. Instance methods are referenced mod#meth (e.g., Array#join).
3 Some Rubyists prefer to write (0..secret_word.size-1) with three dots: (0...secret_word.size). I virtually never use three dots because I find it tends to create bugs. The one exception is when creating an infinite range that excludes the endpoint (e.g., 1.0...1.5).

assigning a method result to a variable in ruby

I'm sure it would be hard to find an easier question, but I'm a complete newbie. I have searched extensively and for some reason can't find the answer to this. Here's my code:
puts "Enter F for Fahrenheit and C for Celsius."
x = gets.chomp.downcase
def ftoc(fahrenheit)
(fahrenheit.to_f - 32.0) * (5.0 / 9.0)
end
if x == "f"
puts "Enter your temp:"
temp = gets.chomp.to_i
ftoc temp
elsif x == "c"
puts "Enter your temp:"
temp = gets.chomp.to_i
ctof temp
else
puts "That does not compute."
end
I'm just trying to get the returned result of the method into a variable so I can use it elsewhere....
Remember that calls like ctof temp just initiate a method and then, as you're not putting the result anywhere, discard it immediately.
To clean up this code let's organize it better:
# Temperature conversion method
def ftoc(fahrenheit)
(fahrenheit.to_f - 32.0) * (5.0 / 9.0)
end
# User input method
def temperature_prompt!
puts "Enter F for Fahrenheit and C for Celsius."
x = gets.chomp.downcase
case (x)
when "f"
puts "Enter your temp:"
temp = gets.chomp.to_i
ftoc temp
when "c"
puts "Enter your temp:"
temp = gets.chomp.to_i
ctof temp
else
puts "That does not compute."
end
end
Now you can make use of the fact that in Ruby things like if and case actually return values. In this case it's the value of the last thing to execute in each block, so that result isn't discarded, it's just passed along:
temp = temperature_prompt!
If you enter an invalid value you get the result of puts which is conveniently nil.
Here's something to consider: Ruby is very good at parsing arbitrary text if you can describe the patterns. Here's a simple input routine:
def temperature_prompt!
puts "Enter degrees (e.g. 8F, 2C)"
case (input = gets.chomp.downcase)
when /(\d+)f/
ftoc $1
when /(\d+)c/
ctof $1
else
puts "That does not compute."
end
end
You could add to those patterns to allow things like -2C and 3.4°F if you wanted.

Can this be optimized without using a global variable?

I've recently begun learning ruby and I'm trying to avoid using global variables where possible. I wrote the below program which accepts user input and outputs math tables of the users choice (currently just +, * but to be expanded upon). I'm following suggestions from https://adriann.github.io/programming_problems.html to get me learning.
class User_input
.
# multiply
def User_input.mult1_to_12
by = (0..12).each do | range |
result = $choice_int * range
puts "#{$choice_int} x #{range} = #{result}"
end
end
# add
def User_input.add1_to_12
add = (0..12).each do | range |
result = $choice_int + range
puts "#{$choice_int} + #{range} = #{result}"
end
end
# accepts user input
puts "Please enter the tables you require (1-12): "
$choice_int = gets.to_i
puts "You have selected #{$choice_int}"
puts "Which tables do you require (+ - * /): "
choice_method = gets.chomp
puts "the method you have chosen is #{choice_method}"
if choice_method == "*"
User_input.mult1_to_12
elsif
choice_method == "+"
add1_to_12
end
end
You will note that I am currently using a global variable for $choice. Can someone with more experience suggest a more optimal solution. Please feel free to tear my code apart : ) Thanks.
Methods can accept parameters, for example:
# add numbers
def add(a,b)
a+b
end
puts add(1,2)
# will output 3
Here's a simple modification to your code using parameters:
class UserInput
# multiply
def self.mult1_to_12(choice_int)
(0..12).each do | range |
result = choice_int * range
puts "#{choice_int} x #{range} = #{result}"
end
end
# add
def self.add1_to_12(choice_int)
(0..12).each do | range |
result = choice_int + range
puts "#{choice_int} + #{range} = #{result}"
end
end
end
# accepts user input
puts "Please enter the tables you require (1-12): "
choice_int = gets.to_i
puts "You have selected #{choice_int}"
puts "Which tables do you require (+ - * /): "
choice_method = gets.chomp
puts "the method you have chosen is #{choice_method}"
if choice_method == "*"
UserInput.mult1_to_12(choice_int)
elsif choice_method == "+"
UserInput.add1_to_12(choice_int)
end
And here's a bit prettier solution that can also handle - and / (and a bunch of other operations provided by Ruby's Fixnum):
class UserInputProcessor
# define accessors to instance variables
attr_accessor :choice_int, :choice_method
def process
(0..12).map do |range|
if choice_method.eql?('/')
next if range.eql?(0) # need to skip X/0 to avoid division by zero
range = range.to_f # need to convert range to float to get float results
end
"#{choice_int} #{choice_method} #{range.to_i} = #{choice_int.send(choice_method, range)}"
end
end
end
handler = UserInputProcessor.new
print "Please enter the tables you require (1-12): "
handler.choice_int = gets.chomp.to_i
puts "You have selected #{handler.choice_int}"
print "Which tables do you require (+ - * /): "
handler.choice_method = gets.chomp
puts "the method you have chosen is #{handler.choice_method}"
puts "And here are the results:"
puts handler.process.join("\n")

Calculator program in ruby, taking "2+3" and giving output 6, issues with more than 2 digit numbers

First post, excuse if I break any etiquette. I am beginning, so this might be simple.
Trying to code in ruby, a calculator, where user inputs arithmetic sentence (only binary, PEMDAS/BIDMAS will do later) and the answer comes out.
Here is my code, by only works for single digit numbers.
class Calculator
def initializer (a,b)
#a = a,
#b = b
end
def add(a, b)
a+b
end
def subtract(a, b)
a-b
end
def multiply(a,b)
a*b
end
def divide (a,b)
a/b
end
def powers (a,b)
a**b
end
end
puts "Enter an expression to be evaluated"
a = gets.chomp.gsub(/\s+/, "")
puts case a[1]
when "+"
"#{a[0]} + #{a[2]} = #{Calculator.new.add(a[0].to_f,a[2].to_f)}"
when "-"
"#{a[0]} - #{a[2]} = #{Calculator.new.subtract(a[0].to_f,a[2].to_f)}"
when "*" || "x" || "X"
"#{a[0]} x #{a[2]} = #{Calculator.new.multiply(a[0].to_f,a[2].to_f)}"
when "/"
"#{a[0]} / #{a[2]} = #{Calculator.new.divide(a[0].to_f,a[2].to_f)}"
when "^"
"#{a[0]} to the power #{a[2]} = #Calculator.new.powers(a[0].to_f,a[2].to_f)}"
else
"Not valid"
end
I was thinking of trying to split a string like "234+342" (234 and 342 can be any sized length numbers) into an array such as ["234","+","342"].
But I am stuck on how to do this??? Or is there another way??
Help will be appreciated, just a personal challenge.
Thanks
As you already realized the issue is with the way you are carrying operations over input string.
The simplest way to proceed can be to ask users for two numbers and then ask them to enter the operation needed. Something like:
puts "Enter first number"
a = gets.chomp
puts "Enter second number"
b = gets.chomp
puts "Enter required operation [+, -, *, /]"
c = gets.chomp
You can do this all in one shot too, the way you are already trying, however I would advice against it as you never know what user will enter. Eg:
puts "Enter an expression to be evaluated"
a = gets.chomp # user enters: 123 + 457
# => "123 + 457"
Now extracting number:
numbers = a.scan(/\d+/)
#=> ["123", "457"]
operator = a[/\W+/]
#=> " + "
You can then proceed with your switch case.

Ruby code efficiency

Is there a way to make this code shorter and simpler?
loop do
if possibleSet.split(" ").map(&:to_i).any? {|e| (e<0 || e>12)}
print "Please enter valid numbers (between 1 and 12): "
possibleSet = gets
errorinput = false
else
errorinput = true
end
break if errorinput
end
Refactored a bit :)
loop do
print "Please enter valid numbers (between 1 and 12): "
possibleSet = gets.chomp
break unless possibleSet.split(" ").map(&:to_i).any? {|e| (e<0 || e>12)}
end
The code below will check input for correctness:
input = loop do
print "Please enter valid numbers (between 1 and 12): "
# ⇓⇓⇓ as many spaces as user wants
input = gets.chomp.split(/\s+/).map(&:to_i) rescue []
break input unless input.empty? || input.any? { |i| !(0..12).include? i }
end
This parses the user input in an array (not exactly the same behavior, but I hope it is cleaner and you can work from there)
set = []
until set.all? {|i| (1..11).include?(i) } && !set.empty? do
set = gets.split(' ').map(&:to_i)
end

Resources