Printing output results to one line in the console - ruby

Is there an easy way to have the results listed in a single line? For example,
"The numbers outputted were: 99, 85, 70, 50, 35, 20, -2"
def randomMethod()
rand1 = rand(2)
if rand1 == 1
rand2 = rand(1..25)
puts rand2
else
rand2 = 0
puts rand2
end
rand2
end
x = 99
#prints initial x
puts "x = " + "#{x}"
loop do
x -= randomMethod # decrement x by the value returned by randomMethod
puts "x = #{x}"
break if x <= 0
end

Don't use puts in a loop, it terminates with a newline. Instead, accumulate the values in an array and join them with commas once the set is complete:
x_vals = [99]
x_vals << x_vals.last - randomMethod while x_vals.last > 0
puts "The numbers were: #{x_vals.join(", ")}"
While you're at it, you could really tighten up your random method. I'm changing the name to be more conformant with Ruby norms:
def random_method
outcome = rand(1..25) * rand(2)
puts outcome
outcome
end
and if you don't actually need to print the value being generated each time you can completely lose the temporary variables:
def random_method
rand(1..25) * rand(2)
end

Related

Can you someone support me to use ordinal in while loop in Ruby?

I am having a difficult time figuring ordinal in the program below. I need to use the ordinal in the loop statement. When I print statement, It print out backward like 3rd, 2nd, 1st, and so on.
I tried changing my loop statment from (number -= 1) to (number += 1) but that would make infinite while loop. Can someone give me feedback on what I can do here? Thank you.
class Integer
def ordinal
case self % 10
when 1
return "#{self}st"
when 2
return "#{self}nd"
when 3
return "#{self}rd"
else
return "#{self}th"
end
end
end
puts "Let's play a numbers game."
print "How many numbers would you like to enter? >"
number = gets.chomp.to_i
while number >= 1
print "\n\nEnter the #{number.ordinal} positive integer:"
user_int = gets.chomp.to_i
number -= 1
if user_int % 3 == 0
print "#{user_int} is divisible by 3."
else
print "#{user_int} is not divisible by 3."
end
end
puts "\n\nEnd of the Game"
First I'd suggest you to patch Integer class in this way:
module MyIntegerPatch # <------ a custom module
def to_ordinal # <------ to_ordinal is better
case self % 10
when 1
return "#{self}st"
when 2
return "#{self}nd"
when 3
return "#{self}rd"
else
return "#{self}th"
end
end
end
Integer.include MyIntegerPatch # <------ "patch" the class
Then for your loop just use a Range:
(1..number).each do |n| # <---- a range here
puts "\n\nEnter the #{n.to_ordinal} positive integer:"
user_int = gets.chomp.to_i
if user_int % 3 == 0
puts "#{user_int} is divisible by 3."
else
puts "#{user_int} is not divisible by 3."
end
end
Maybe you can try below, use the ruby style times to control
class Integer
def ordinal
case self % 10
when 1
"#{self}st"
when 2
"#{self}nd"
when 3
"#{self}rd"
else
"#{self}th"
end
end
end
puts "Let's play a numbers game."
print 'How many numbers would you like to enter? >'
number = gets.chomp.to_i
number.times do |time|
print "\n\nEnter the #{(time + 1).ordinal} positive integer:"
user_int = gets.chomp.to_i
if user_int % 3 == 0
print "#{user_int} is divisible by 3."
else
print "#{user_int} is not divisible by 3."
end
end
puts "\n\nEnd of the Game"

How do I perform variable assignment with a loop, and break?

Here is the logic:
y = 'var to check for'
some_var = some_loop.each do |x|
x if x == y
break if x
end
Is there a better way to write this?
Something like
x && break if x == y
Thank you in advance!
The correct answer is to use include?. eg:
found = (array_expression).include? {|x| x == search_value}
It's possible to also use each and break out on the first matched value, but the C implementation of include? is faster than a ruby script with each.
Here is a test program, comparing the performance of invoking include? on a very large array vs. invoking each on the same array with the same argument.
#!/usr/bin/env ruby
#
require 'benchmark'
def f_include a, b
b if a.include?(b)
end
def f_each_break a, b
a.each {|x| return b if x == b }
nil
end
# gen large array of random numbers
a = (1..100000).map{|x| rand 1000000}
# now select 1000 random numbers in the set
nums = (1..1000).map{|x| a[rand a.size]}
# now, check the time for f1 vs. f2
r1 = r2 = nil
Benchmark.bm do |bm|
bm.report('incl') { r1 = nums.map {|n| f_include a,n} }
bm.report('each') { r2 = nums.map {|n| f_each_break a,n} }
end
if r1.size != r2.size || r1 != r2
puts "results differ"
puts "r1.size = #{r1.size}"
puts "r2.size = #{r2.size}"
exceptions = (0..r1.size).select {|x| x if r1[x] != r2[x]}.compact
puts "There were #{exceptions.size} exceptions"
else
puts "results ok"
end
exit
Here is the output from the test:
$ ./test-find.rb
user system total real
incl 5.150000 0.090000 5.240000 ( 7.410580)
each 7.400000 0.140000 7.540000 ( 9.269962)
results ok
Why not:
some_var = (some_loop.include? y ? y : nil)

How do I calculate the factorial of a number in Ruby?

Alright, so I asked an earlier question on my syntax error. I got rid of the errors, but the program doesn't do what it was intended to do. My math is wrong and doesn't find the number of trailing zeros. Here is my code:
num = " "
a = 0
sumOfFact = 1
def factorial
num = gets.to_i
a = num
(1..num).each do |a|
if a != 1
sumOfFact *= a
a -= 1
else
break
end
end
end
for c in 1..sumOfFact
if sumOfFact / c == 10
zeros += 1
end
end
factorial()
puts sumOfFact
puts zeros
Well, first, you should do the gets outside your method. Your method should accept a param. Second, why do you need the condition?
You want the multiplication from 1 to n to get the factorial. You should get started with this:
def factorial(n)
total = 1
(1..n).each do |n|
total *= n
end
total
end
puts factorial(gets.to_i)
Next is factorial with inject in case you want to learn new syntax :-)
def factorial(n)
n == 0? 1 : (1..n).inject(1) { |total, i| total*= i; total }
end
puts factorial(gets.to_i)
As #pjs commented below, here's a beautiful way of doing factorial!
def factorial(n)
n == 0? 1 : (1..n).inject(:*)
end
And, a final enhancement:
def factorial(n)
(1..n).inject(1, :*)
end
Supposing that n is a non-negative integer number, you can define a method to calculate the factorial:
def factorial(n)
tot = 1
(1..n).each do |n|
tot *= x
end
tot
end
Examples of its usage:
puts factorial(0) # 1
puts factorial(1) # 1
puts factorial(2) # 2
puts factorial(3) # 6
puts factorial(4) # 24
puts factorial(5) # 120
If you wan't to read the user input, call it like this:
puts 'Type the non-negative integer:'
n = gets.to_i
puts factorial(n)
class Factorial
attr_reader :num
def initialize(num)
#num = num
end
def find_factorial
(1..num).inject(:*) || 1
end
end
number = Factorial.new(8).find_factorial
puts number
Or you could just simply write:
(1..num).inject(:*) || 1
Try this too. Hope this helps anyone having the same problem in some way.
Method for finding the factorial of any number:
def factorial(number)
for i in 1...number do
number *= i
end
number
end
puts factorial(5)

How to Find a Sequence of 4 in an Array with 5 Elements & Fixing Input Error

I've built a Yahtzee game for Ruby Quiz #19. I have the game up and running, however, there are 2 bugs.
When a player chooses to use a roll of >=3 of a kind as a "small straight" (sequence of 4 dice) to "scratch" (score it as zero) that section an error occurs. Here is the code for the small straight:
def sm_straight
#roll = #roll.sort.uniq
if (0..1).any? {|x| (#roll[x+3] - #roll[x+2] == 1) && (#roll[x+2] - #roll[x+1] == 1) && (#roll[x+1] - #roll[x] == 1)}
#scorecard["sm. straight"] = 30
else
puts "Your roll is not a sm. straight! Please select another section or type scratch to score 0 for this section."
scratch = gets.chomp
if scratch == "scratch"
#scorecard["sm. straight"] = "scratch"
elsif #scorecard.has_key?(scratch)
#turn -= 1
section_to_score(scratch)
else
sm_straight
end
end
end
This is the error:
NoMethodError: undefined method -' for nil:NilClass
from Yahtzee_test.rb:209:inblock in sm_straight'
Line 209 is the "if statement" line
When a player incorrectly enters which dice to keep. I am trying to figure out a better way to ask the player how to enter the dice to keep or catch the error and have them re-enter the numbers with the current system. Here is the code"
def roll_again
puts "Which dice would you like to keep from this roll? (1, 2, 3, 4, 5)"
dice_to_keep = gets.chomp.split(',').map {|x| (x.to_i) - 1}.map {|x| #roll[x]}
new_roll = Array.new(5 - dice_to_keep.size) {rand(6) + 1}
#roll = new_roll + dice_to_keep
p #roll
#roll_count += 1
puts "That was roll number #{#roll_count}, you have #{3-#roll_count} remaining."
if #roll_count < 3
more_rolls?
else
section(#roll)
end
end
Any advice on how to write this code better and make it bug free would be greatly appreciated!
To check for a straight of at least 4 out of 5 dice, you could replace:
#roll = #roll.sort.uniq
if (0..1).any? {|x| (#roll[x+3] - #roll[x+2] == 1) && (#roll[x+2] - #roll[x+1] == 1) && (#roll[x+1] - #roll[x] == 1)}
with this:
if has_straight(roll, 4)
And define has_straight:
def has_straight( roll, need )
num = 1
roll = roll.sort.uniq
roll.each_with_index do |e, i|
if i < roll.length-1 then
if (roll[i+1] - roll[i]) > 1 then
break if num >= need
num = 1
end
num += 1
end
end
num >= need
end
There may be a slightly more clever Ruby-ism that will do this, but it fixes your array out-of-bounds issue.

Times Table - Fizzbuzz Type Question in Ruby

I'm brand new to programming and Ruby is my first language. One exercise I'm working on is to create a multiplication table that does the following:
1x1 = 1
1x2 = 2
(etc)
2x1 = 2
2x2 = 4
I figured I'd do this by creating a nested while loop:
a = 1
b = 1
while a <= 5
while b <= 5
puts "#{a} * #{b} = #{a * b}"
b += 1
end
a += 1
end
When I run the script it prints the first set of times table (1x1 - 1x5) then stops. It doesn't iterate the parent loop. What am I doing wrong?
You state that you're a novice so a while loop is ok for now. But when you improve both your programming and Ruby skills you should be able to write more idiomatic code. Something along those lines:
puts [*1..5].product([*1..5]).map { |x, y| "#{x} * #{y} = #{x*y}" }.join("\n")
You never reset your b to 1. Look at the second while loop:
while b <= 5:
...
b += 1
At the end of this loop, b = 6, and the loop exits. Then a += 1 is executed, and our outer loop begins. On all the next inner loop iterations, b = 6 however, and therefore isn't executed. Thus you need:
...
end
a += 1
b = 1
The "bookkeeping error" explained in the accepted answer is an easy one to make. It is one of the reasons the each method is generally preferred to a while loop:
(1..5).each do |a|
(1..5).each do |b|
puts "#{a} * #{b} = #{a * b}"
end
end
No bookkeeping!
class MultiplicationTable
i=1
j=5
while i <= j
(1..12).each do |x|
puts "#{i} * #{x} = #{i*x}"
end
i+=1
end
end

Resources