How to bypass scope convention in ruby if else statements - ruby

This shows an error because ruby scope rules prevent me from accessing outer variables inside an if else block.
puts "Enter Line 1 m and c:"
m1 = gets.to_f
c1 = gets.to_f
puts "Enter Line 2 m and c:"
m2 = gets.to_f
c2 = gets.to_f
if ((m1==m2) and (c1==c2))
puts "infinite solutions"
elsif ((m1==m2) and (c1!=c2))
puts "no solution"
else
x = (c1 - c2)/(m2 - m1)
y = m1*x + c1
puts "(x,y) = (" + x + "," + y+")"
end
Can you please tell me a way to get around this error ?
Update:
actually the error i get is:
undefined local variable or method 'c1'
for main:Object from :7
from C;/Ruby200-x64/bin/irb:12;in ''

Use interpolation to get rid of this.
puts "(x,y) = (#{x}, #{y})"
You were trying to concatenate String object with Float object. That's not possible, so you have to convert those Float to String objects before concatenation.
modified code:
puts "Enter Line 1 m and c:"
m1 = gets.to_f
c1 = gets.to_f
puts "Enter Line 2 m and c:"
m2 = gets.to_f
c2 = gets.to_f
if m1 == m2 and c1 == c2
puts "infinite solutions"
elsif m1 == m2 and c1 != c2
puts "no solution"
else
x = (c1 - c2)/(m2 - m1)
y = m1*x + c1
puts "(x,y) = (#{x}, #{y})"
end
output
[arup#Ruby]$ ruby a.rb
Enter Line 1 m and c:
14
21
Enter Line 2 m and c:
12
44
(x,y) = (11.5, 182.0)
[arup#Ruby]$

It doesn't prevent you from accessing outer variables, the error you see is:
`+': no implicit conversion of Float into String (TypeError)
which is completely different and has nothing to do with variables visibility scopes. What error says is that you can't sum up String and Float(try 'a' + 1.0 in console).
To fix it you should convert variables to strings by yourself with:
puts "(x,y) = (" + x.to_s + "," + y.to_s + ")"
or by using interpolation(which is preferable):
puts "(x,y) = (#{x}, #{y})"

Related

Ruby Number Guessing Game

I have tried to make a number guessing game using ruby but it seems to be looping all over again after the user gets the correct answer, here's my code and thanks in advance!
require './input_functions'
def check (rno,input)
x = 1
while (x == 1)
y = 0
if (rno > input)
puts("Try a bigger number")
input = gets.chomp.to_i
y = y + 1
x = 1
else
if (rno < input)
puts("Try a smaller number")
input = gets.chomp.to_i
y = y + 1
x = 1
else
if(rno == input)
puts("Bingo!")
x = 0
end
end
end
end
return
end
def main
rno = rand(100)
input = read_integer("Enter an integer between 0 and 100: ")
check(rno,input,y)
times = check(rno,input,y)
puts ("You have tried " + times.to_s + " times.")
end
main
The main problems are:
You call check method two times within main method, you need to remove the first one.
You need to move y = 0 out of while loop to be able to return it.
Tried to simplify your code a bit, and you could try to improve it even more.
def check(rno, input)
x = 1
y = 0
while x == 1
if rno == input
puts "Bingo!"
x = 0
else
if rno > input
puts "Try a bigger number"
else
puts "Try a smaller number"
end
input = gets.chomp.to_i
y = y + 1
end
end
return y
end
def main
rno = rand(100)
input = read_integer("Enter an integer between 0 and 100: ")
times = check(rno, input)
puts ("You have tried " + times.to_s + " times.")
end

Reading word into an array [ruby]

Trying to create a ceaser cipher in Ruby.
The problem I'm facing is that when the program reaches the while loop, it only performs the desired operation on the very last letter of the inputted word. Before I delve further into what I've tried, please find the code:
#!/usr/bin/ruby
#print 65.chr ASCII code for A
#print 97.chr ASCII code for a
a = 0
b = 97
d = []
e = 0
# Just to print the alphabet alongside the ASCII value
# (For sanity checking)
while a <= 25
print b.chr + " "
print b.to_s + "\n"
a = a + 1
b = b + 1
end
puts "\n Please enter a word to translate"
word = gets.strip
# The desired effect is to move the letter along by key value
puts "Please enter a key"
k = gets.chomp.to_i
# In its current state, what happens is only the last char
# is moved along by the key value.
while e <= word.length
word.each_byte do |c|
d[e] = c + k
end
e = e + 1
end
puts d
I'm thinking that the problem lies with the logic for the while loop. The way I am going to attack this is by reading the pre-converted word into an array, as opposed to using the .each_byte object.
I don't know how to do that and the guides/questions I've found don't quite answer the question. If anyone knows how to do this, or knows a better way of solving this- I'd be much appreciative.
you don't need the last while loop
word.each_byte do |c|
d[e] = c + k
e = e + 1
end
Something a bit more verbose:
alphabet = ('a'..'z').to_a
new_word = ''
puts "\n Please enter a word to translate"
word = gets.strip
puts "Please enter a key"
k = gets.chomp.to_i
word.split('').each_with_index do |letter, index|
alphabet_index = alphabet.index(letter)
new_index = alphabet_index + key
new_word[index] = alphabet[new_index]
end
puts "Your translated word is #{new_word}"
Caesar cipher is a simple shift cipher
word.each_byte do |c|
p c + k
end
Managed to get it working, thanks for all the help... Code for anyone interested:
#!/usr/bin/ruby
#print 65.chr A
#print 97.chr a
a = 0
b = 65
y = 97
d = []
e = 0
while a <= 25
print y.chr + " = " + y.to_s + " "
print b.chr + " = " + b.to_s + " " + "\n"
a = a + 1
b = b + 1
y = y + 1
end
puts "\n Please enter a word to translate"
word = gets.strip
puts "Please enter a key"
k = gets.chomp.to_i
word.each_byte do |c|
d[e] = c + k
e = e + 1
end
print "\n"
a = 0
arlen = d.count
while a != arlen
print d[a].chr
a = a + 1
end
print k

very simple ruby programing, getting into infinite loop

I'm asked to write the ruby program that generate the output based the given command,
The full description
I'm really new in ruby (maybe few hours that I have started ruby)
When I run the program I get into infinite loop, I don't understand why.
Thank you.
What I have done so far:
# MyVector Class
class MyVector
def initialize (a)
if !(a.instance_of? Array)
raise "ARGUMENT OF INITIALIZER MUST BE AN ARRAY"
else
#array = a
end
end
def array
#array
end
def to_s
#array.to_s
end
def length
#array.length
end
def [](i)
#array[i]
end
def each2(a)
raise Error, "INTEGER IS NOT LIKE VECTOR" if a.kind_of?(Integer)
Vector.Raise Error if length != a.length
return to_enum(:each2, a) unless block_given?
length.times do |i|
yield #array[i], a[i]
end
self
end
def * (a)
Vector.Raise Error if length != a.length
p = 0
each2(a) {|a1, a2|p += a1 * a2}
p
end
end
# MyMatrix Class
class MyMatrix
def initialize a
#array=Array.new(a.length)
i=0
while(i<a.length)
#array[i]=MyVector.new(a[i])
end
end
def to_s
#array.to_s
end
def transpose
size=vectors[0].length
arr= Array.new(size)
i=0
while i<size
a=Array.new(vector.length)
j=0
while j<a.length
a[j]=vectors[j].arr[i]
j+=1
end
arr[i]=a
i+=1
end
arr[i]=a
i+=1
end
def *m
if !(m instance_of? MyMatrix)
raise Error
a=Array.new(#array.length)
i=0
while (i<#array.length)
a[i]=#array[i]*m
i=i+1
end
end
end
end
Input:
Test code
v = MyVector.new([1,2,3])
puts "v = " + v.to_s
v1 = MyVector.new([2,3,4])
puts "v1 = " + v1.to_s
puts "v * v1 = " + (v * v1).to_s
m = MyMatrix.new([[1,2], [1, 2], [1, 2]])
puts "m = " + m.to_s + "\n"
puts "v * m = " + (v * m).to_s
m1 = MyMatrix.new([[1, 2, 3], [2, 3, 4]])
puts "m1 = " + m1.to_s + "\n"
puts "m * m1 = " + (m * m1).to_s
puts "m1 * m = " + (m1 * m).to_s
Desired Output:
v = 1 2 3
v1 = 2 3 4
v * v1 = 20
m =
1 2
1 2
1 2
v * m = 6 12
m1 =
1 2 3
2 3 4
m * m1 =
5 8 11
5 8 11
5 8 11
m1 * m =
6 12
9 18
To answer the infinite loop issue, it looks like you forgot to add a i += 1 in the #initialize method of Matrix class.
However, you will encounter more errors further in the code since, for example, you're checking length of the Matrix object which is undefined, and iterating over the Matrix object in each2 defined inside of the Vector class which needs the object to be an Enumerable (Array/Hash etc). These will throw an error as the Matrix class is not an Enumerator. These are some good resources to help you learn how the powerful Enumerator module works.
Once you get familiar with the syntax and structure, be sure to use the Pry tool. It will be your best friend for debugging Ruby code.

very simple ruby programing, getting error and don't understand it

I'm asked to write the ruby program that generate the output based the given command,
The full description
I'm really new in ruby (maybe few hours that I have started ruby)
I'm getting this error, please check my code for other possible errors:
Thank you.
n `block in each2': undefined method `[]' for #<MyVector:0x00000002c4ad90 #array=[2, 3, 4]> (NoMethodError)
What I have done so far:
# MyVector Class
class MyVector
def initialize (a)
if !(a.instance_of? Array)
raise "ARGUMENT OF INITIALIZER MUST BE AN ARRAY"
else
#array = a
end
end
def array
#array
end
def to_s
#array.to_s
end
def length
#array.length
end
def each2(a)
raise Error, "INTEGER IS NOT LIKE VECTOR" if a.kind_of?(Integer)
Vector.Raise Error if length != a.length
return to_enum(:each2, a) unless block_given?
length.times do |i|
yield #array[i], a[i]
end
self
end
def * (a)
Vector.Raise Error if length != a.length
p = 0
each2(a) {|a1, a2|p += a1 * a2}
p
end
end
# MyMatrix Class
class MyMatrix
def initialize a
#array=Array.new(a.length)
i=0
while(i<a.length)
#array[i]=MyVector.new(a[i])
end
end
def to_s
#array.to_s
end
def transpose
size=vectors[0].length
arr= Array.new(size)
i=0
while i<size
a=Array.new(vector.length)
j=0
while j<a.length
a[j]=vectors[j].arr[i]
j+=1
end
arr[i]=a
i+=1
end
arr[i]=a
i+=1
end
def *m
if !(m instance_of? MyMatrix)
raise Error
a=Array.new(#array.length)
i=0
while (i<#array.length)
a[i]=#array[i]*m
i=i+1
end
end
end
end
Input:
Test code
v = MyVector.new([1,2,3])
puts "v = " + v.to_s
v1 = MyVector.new([2,3,4])
puts "v1 = " + v1.to_s
puts "v * v1 = " + (v * v1).to_s
m = MyMatrix.new([[1,2], [1, 2], [1, 2]])
puts "m = " + m.to_s + "\n"
puts "v * m = " + (v * m).to_s
m1 = MyMatrix.new([[1, 2, 3], [2, 3, 4]])
puts "m1 = " + m1.to_s + "\n"
puts "m * m1 = " + (m * m1).to_s
puts "m1 * m = " + (m1 * m).to_s
Desired Output:
v = 1 2 3
v1 = 2 3 4
v * v1 = 20
m =
1 2
1 2
1 2
v * m = 6 12
m1 =
1 2 3
2 3 4
m * m1 =
5 8 11
5 8 11
5 8 11
m1 * m =
6 12
9 18
length.times do |i|
yield #array[i], a[i]
end
In the above block, a is an instance of MyVector. You need to define the [] operator on it, probably something like:
def [](i)
#array[i]
end

Public key encryption demo in Ruby

I wrote up the ruby script below to help my students understand public key encryption. I followed the "pencil and paper" method shown here: http://sergematovic.tripod.com/rsa1.html
This works fine as long as 29 isn't chosen as either p or q. If 29 is picked, it hangs on calculating the secret key. Can anyone tell me why that is?
#!/usr/bin/env ruby -wKU
#initialize
primes, p, q, n, z, k, j, m,e,d = nil
def prime
primes = [2,3,5,7,11,13,17,19,23,29,31]
primes.sample
end
#pick p
p= prime
puts "p: " + p.to_s
#pick q
q=p
while p==q
q = prime
end
puts "q: " + q.to_s
#find n
n=p*q
puts "n: " + n.to_s
#find z
z=(p-1)*(q-1)
puts "z: " + z.to_s
#pick a relative prime of the totient
k=7
puts "k: " + k.to_s
#calculate secret key
j=0
while j*k % z != 1
j+=1
end
puts "j: " + j.to_s
#message
m=16
puts "Message: " + m.to_s
#encrypt
e = m**k % n
puts "Encrypted: " + e.to_s
#decrypt
d = e**j % n
puts "Decrypted: " + d.to_s
When 29 is chosen as p or q, z has 28 as a factor, and thus k = 7 is not a relative prime of the totient as your comment claims!
(This means j*k % z is always a multiple of 7, so your loop never terminates.)

Resources