very simple ruby programing, getting into infinite loop - ruby

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.

Related

How do I fix a problem to call a function in Ruby?

I'm trying to use some ruby code that I've found in Github. I've downloaded the code and did the necessary imports the "requires" and tried to run it as it is described in the readme file on github repository. The code is the following:
In the file pcset_test.rb the code is the following:
require './pcset.rb'
require 'test/unit'
#
# When possible, test cases are adapted from
# Introduction to Post-Tonal Theory by Joseph N. Straus,
# unless obvious or otherwise noted.
#
class PCSetTest < Test::Unit::TestCase
def test_init
#assert_raise(ArgumentError) {PCSet.new []}
assert_raise(ArgumentError) {PCSet.new [1, 2, 3, 'string']}
assert_raise(ArgumentError) {PCSet.new "string"}
assert_raise(ArgumentError) {PCSet.new [1, 2, 3.6, 4]}
assert_equal([0, 1, 2, 9], PCSet.new([0, 1, 2, 33, 13]).pitches)
assert_equal([3, 2, 1, 11, 10, 0], PCSet.new_from_string('321bac').pitches)
assert_equal([0,2,4,5,7,11,9], PCSet.new([12,2,4,5,7,11,9]).pitches)
assert_nothing_raised() {PCSet.new []}
end
def test_inversion
end
def test_transposition
end
def test_multiplication
end
#
# set normal prime forte #
# 0,2,4,7,8,11 7,8,11,0,2,4 0,1,4,5,7,9 6-31
# 0,1,2,4,5,7,11 11,0,1,2,4,5,7 0,1,2,3,5,6,8 7-Z36
# 0,1,3,5,6,7,9,10,11 5,6,7,9,10,11,0,1,3 0,1,2,3,4,6,7,8,10 9-8
#
def test_normal_form
testPC = PCSet.new [0,4,8,9,11]
assert_kind_of(PCSet, testPC.normal_form)
assert_equal([8,9,11,0,4], testPC.normal_form.pitches)
assert_equal([10,1,4,6], PCSet.new([1,6,4,10]).normal_form.pitches)
assert_equal([2,4,8,10], PCSet.new([10,8,4,2]).normal_form.pitches)
assert_equal([7,8,11,0,2,4], PCSet.new([0,2,4,7,8,11]).normal_form.pitches)
assert_equal([11,0,1,2,4,5,7], PCSet.new([0,1,2,4,5,7,11]).normal_form.pitches)
assert_equal([5,6,7,9,10,11,0,1,3], PCSet.new([0,1,3,5,6,7,9,10,11]).normal_form.pitches)
end
def test_prime_form
assert_equal([0,1,2,6], PCSet.new([5,6,1,7]).prime.pitches)
assert_equal([0,1,4], PCSet.new([2,5,6]).prime.pitches)
assert_equal([0,1,4,5,7,9], PCSet.new([0,2,4,7,8,11]).prime.pitches)
assert_equal([0,1,2,3,5,6,8], PCSet.new([0,1,2,4,5,7,11]).prime.pitches)
assert_equal([0,1,2,3,4,6,7,8,10], PCSet.new([0,1,3,5,6,7,9,10,11]).prime.pitches)
end
def test_set_class
testPcs = PCSet.new([2,5,6])
testPrime = testPcs.prime
assert_equal([
[2,5,6], [3,6,7], [4,7,8], [5,8,9], [6,9,10], [7,10,11],
[8,11,0],[9,0,1], [10,1,2],[11,2,3],[0,3,4], [1,4,5],
[6,7,10],[7,8,11],[8,9,0], [9,10,1],[10,11,2],[11,0,3],
[0,1,4], [1,2,5], [2,3,6], [3,4,7], [4,5,8], [5,6,9]
].sort, PCSet.new([2,5,6]).set_class.map{|x| x.pitches})
assert_equal(testPcs.set_class.map{|x| x.pitches}, testPrime.set_class.map{|x| x.pitches})
end
def test_interval_vector
assert_equal([2,1,2,1,0,0], PCSet.new([0,1,3,4]).interval_vector)
assert_equal([2,5,4,3,6,1], PCSet.new([0,1,3,5,6,8,10]).interval_vector)
assert_equal([0,6,0,6,0,3], PCSet.new([0,2,4,6,8,10]).interval_vector)
end
def test_complement
assert_equal([6,7,8,9,10,11], PCSet.new([0,1,2,3,4,5]).complement.pitches)
assert_equal([3,4,5], PCSet.new([0,1,2], 6).complement.pitches)
end
#
# Test values from (Morris 1991), pages 105-111
# Citation:
# Morris. Class Notes for Atonal Music Theory
# Lebanon, NH. Frog Peak Music, 1991.
#
def test_invariance_vector
assert_equal([1,0,0,0,5,6,5,5],PCSet.new([0,2,5]).invariance_vector)
assert_equal([2,2,2,2,6,6,6,6],PCSet.new([0,1,6,7]).invariance_vector)
assert_equal([6,6,6,6,6,6,6,6],PCSet.new([0,2,4,6,8,10]).invariance_vector)
assert_equal([1,0,0,0,0,0,0,0],PCSet.new([0,1,2,3,4,5,8]).invariance_vector)
assert_equal([1,0,0,1,0,0,0,0],PCSet.new([0,1,2,3,5,6,8]).invariance_vector)
assert_equal([12,12,12,12,0,0,0,0],PCSet.new([0,1,2,3,4,5,6,7,8,9,10,11]).invariance_vector)
end
#
# Test values from (Huron 1994). Huron rounds, thus the 0.01 margin of error.
# Citation:
# Huron. Interval-Class Content in Equally Tempered Pitch-Class Sets:
# Common Scales Exhibit Optimum Tonal Consonance.
# Music Perception (1994) vol. 11 (3) pp. 289-305
#
def test_huron
h1 = PCSet.new([0,1,2,3,4,5,6,7,8,9,10,11]).huron
assert_in_delta(-0.2, h1[0], 0.01)
assert_in_delta(0.21, h1[1], 0.01)
h2 = PCSet.new([0,2,4,5,7,9,11]).huron
assert_in_delta(4.76, h2[0], 0.01)
assert_in_delta(0.62, h2[1], 0.01)
end
def test_coherence
end
end
And in the file pcset.rb the folloing code:
#
# => PCSet Class for Ruby
# => Beau Sievers
# => Hanover, Fall 2008.
#
#
# TODO: Make this a module to avoid namespace collisions.
# Lilypond and MusicXML output
#
include Math
def choose(n, k)
return [[]] if n.nil? || n.empty? && k == 0
return [] if n.nil? || n.empty? && k > 0
return [[]] if n.size > 0 && k == 0
c2 = n.clone
c2.pop
new_element = n.clone.pop
choose(c2, k) + append_all(choose(c2, k-1), new_element)
end
def append_all(lists, element)
lists.map { |l| l << element }
end
def array_to_binary(array)
array.inject(0) {|sum, n| sum + 2**n}
end
# the following method is horrifically inelegant
# but avoids monkey-patching.
# TODO: do this right, incl. error checking
def pearsons(x, y)
if !x.is_a?(Array) || !y.is_a?(Array) then raise StandardError, "x and y must be arrays", caller end
if x.size != y.size then raise StandardError, "x and y must be same size", caller end
sum_x = x.inject(0) {|sum, n| sum + n}
sum_y = y.inject(0) {|sum, n| sum + n}
sum_square_x = x.inject(0) {|sum, n| sum + n * n}
sum_square_y = y.inject(0) {|sum, n| sum + n * n}
xy = []
x.zip(y) {|a, b| xy.push(a * b)}
sum_xy = xy.inject(0) {|sum, n| sum + n}
num = sum_xy - ((sum_x * sum_y)/x.size)
den = Math.sqrt((sum_square_x - ((sum_x*sum_x)/x.size)) * (sum_square_y - ((sum_y*sum_y)/x.size)))
(num/den)
end
class PCSet
include Comparable
attr_reader :pitches, :base, :input
def initialize(pcarray, base = 12)
if pcarray.instance_of?(Array) && pcarray.all?{|pc| pc.instance_of?(Fixnum)}
#base, #input = base, pcarray
#pitches = pcarray.map{ |x| x % #base }.uniq
else
raise ArgumentError, "Improperly formatted PC array", caller
end
end
def PCSet.new_from_string(pcstring, base = 12)
if base > 36 then raise StandardError, "Use PCSet.new to create pcsets with a base larger than 36", caller end
pcarray = []
pcstring.downcase.split(//).each do |c|
if c <= 'z' and c >= '0' then pcarray.push(c.to_i(36)) end
end
PCSet.new pcarray, base
end
def <=>(pcs)
#pitches <=> pcs.pitches
end
def [](index)
#pitches[index]
end
# Intersection
def &(other)
PCSet.new #pitches & other.pitches
end
# Union
def |(other)
PCSet.new #pitches | other.pitches
end
def inspect
#pitches.inspect
end
def length
#pitches.length
end
def invert(axis = 0)
PCSet.new #pitches.map {|x| (axis-x) % #base}
end
def invert!(axis = 0)
#pitches.map! {|x| (axis-x) % #base}
end
def transpose(interval)
PCSet.new #pitches.map {|x| (x + interval) % #base}
end
def transpose!(interval)
#pitches.map! {|x| (x + interval) % #base}
end
def multiply(m = 5)
PCSet.new #pitches.map {|x| (x * m) % #base}
end
def multiply!(m = 5)
#pitches.map! {|x| (x * m) % #base}
end
def zero
transpose(-1 * #pitches[0])
end
def zero!
transpose!(-1 * #pitches[0])
end
def transpositions
(0..(#base-1)).to_a.map{|x| #pitches.map {|y| (y + x) % #base}}.sort.map {|x| PCSet.new x}
end
def transpositions_and_inversions(axis = 0)
transpositions + invert(axis).transpositions
end
#
# Normal form after Straus. Morris and AthenaCL do this differently.
#
def normal_form
tempar = #pitches.sort
arar = [] # [[1,4,7,8,10],[4,7,8,10,1], etc.] get each cyclic variation
tempar.each {arar.push PCSet.new(tempar.unshift(tempar.pop))}
most_left_compact(arar)
end
def normal_form!
#pitches = normal_form.pitches
end
def is_normal_form?
self.pitches == self.normal_form.pitches
end
def set_class
transpositions_and_inversions.map{|pcs| pcs.normal_form}.sort
end
def prime
most_left_compact([normal_form.zero, invert.normal_form.zero])
end
def prime!
self.pitches = self.prime.pitches
end
def is_prime?
self.pitches == self.prime.pitches
end
def complement
new_pitches = []
#base.times do |p|
if !#pitches.include? p then
new_pitches.push p
end
end
PCSet.new new_pitches
end
def full_interval_vector
pairs = choose(#pitches, 2) # choose every pc pair
intervals = pairs.map {|x| (x[1] - x[0]) % #base} # calculate every interval
i_vector = Array.new(#base-1).fill(0)
intervals.each {|x| i_vector[x-1] += 1} # count the intervals
i_vector
end
def interval_vector
i_vector = full_interval_vector
(0..((#base-1)/2)-1).each {|x| i_vector[x] += i_vector.pop}
i_vector
end
#
# Morris's invariance vector
#
def invariance_vector(m = 5)
t = transpositions.map!{|pcs| self & pcs}
ti = invert.transpositions.map!{|pcs| self & pcs}
tm = multiply(m).transpositions.map!{|pcs| self & pcs}
tmi = invert.multiply(m).transpositions.map!{|pcs| self & pcs}
tc = complement.transpositions.map!{|pcs| self & pcs}
tic = complement.invert.transpositions.map!{|pcs| self & pcs}
tmc = complement.multiply(m).transpositions.map!{|pcs| self & pcs}
tmic = complement.invert.multiply(m).transpositions.map!{|pcs| self & pcs}
[t, ti, tm, tmi, tc, tic, tmc, tmic].map{|x| x.reject{|pcs| pcs.pitches != #pitches}.length}
end
# Huron's aggregate dyadic consonance measure.
# Huron. Interval-Class Content in Equally Tempered Pitch-Class Sets:
# Common Scales Exhibit Optimum Tonal Consonance.
# Music Perception (1994) vol. 11 (3) pp. 289-305
def huron
if #base != 12 then raise StandardError, "PCSet.huron only makes sense for mod 12 pcsets", caller end
# m2/M7 M2/m7 m3/M6 M3/m6 P4/P5 A4/d5
huron_table = [-1.428, -0.582, 0.594, 0.386, 1.240, -0.453]
interval_consonance = []
interval_vector.zip(huron_table) {|x, y| interval_consonance.push(x * y) }
aggregate_dyadic_consonance = interval_consonance.inject {|sum, n| sum + n}
[aggregate_dyadic_consonance, pearsons(interval_vector, huron_table)]
end
#
# Balzano's vector of relations. Citation for all Balzano methods:
#
# Balzano. "The Pitch Set as a Level of Description for Studying Musical
# Pitch Perception" in Music, Mind, and Brain ed. Clynes. Plenum Press. 1982.
#
def vector_of_relations
(0..length-1).to_a.map do |i|
(0..length-1).to_a.map do |j|
(#pitches[(i + j) % length] - #pitches[i]) % #base
end
end
end
#
# Checks if the set satisfies Balzano's uniqueness.
#
def is_unique?
vector_of_relations.uniq.size == vector_of_relations.size
end
#
# Checks if the set satisfies Balzano's scalestep-semitone coherence.
# For all s[i] and s[i1]:
# j < k => v[i][j] < v[i1][k]
# Where j and k are scalestep-counting indices.
# And unless v[i][j] == 6 (a tritone), in which case the strict inequality is relaxed.
#
def is_coherent?
v = vector_of_relations
truth_array = []
all_pair_indices = choose((0..length-1).to_a, 2)
all_pair_indices.each do |i, i1|
all_pair_indices.each do |j, k|
if v[i][j] == 6
truth_array.push(v[i][j] <= v[i1][k])
else
truth_array.push(v[i][j] < v[i1][k])
end
if v[i1][j] == 6
truth_array.push(v[i1][j] <= v[i][k])
else
truth_array.push(v[i1][j] < v[i][k])
end
end
end
!truth_array.include?(false)
end
#
# Strict Balzano coherence, no inequality relaxation for tritones.
#
def is_strictly_coherent?
v = vector_of_relations
truth_array = []
all_pair_indices = choose((0..length-1).to_a, 2)
all_pair_indices.each do |i, i1|
all_pair_indices.each do |j, k|
truth_array.push(v[i][j] < v[i1][k])
truth_array.push(v[i1][j] < v[i][k])
end
end
!truth_array.include?(false)
end
def notes(middle_c = 0)
noteArray = ['C','C#','D','D#','E','F','F#','G','G#','A','A#','B']
if #base != 12 then raise StandardError, "PCSet.notes only makes sense for mod 12 pcsets", caller end
out_string = String.new
transpose(-middle_c).pitches.each do |p|
out_string += noteArray[p] + ", "
end
out_string.chop.chop
end
def info
print "modulo: #{#base}\n"
print "raw input: #{#input.inspect}\n"
print "pitch set: #{#pitches.inspect}\n"
print "notes: #{notes}\n"
print "normal: #{normal_form.inspect}\n"
print "prime: #{prime.inspect}\n"
print "interval vector: #{interval_vector.inspect}\n"
print "invariance vector: #{invariance_vector.inspect}\n"
print "huron ADC: #{huron[0]} pearsons: #{huron[1]}\n"
print "balzano coherence: "
if is_strictly_coherent?
print "strictly coherent\n"
elsif is_coherent?
print "coherent\n"
else
print "false\n"
end
end
# def lilypond
#
# end
#
# def musicXML
#
# end
###############################################################################
private
#
# Convert every pitch array to a binary representation, e.g.:
# [0,2,4,8,10] -> 010100010101
# 2^n: BA9876543210
# The smallest binary number is the most left-compact.
#
def most_left_compact(pcset_array)
if !pcset_array.all? {|pcs| pcs.length == pcset_array[0].length}
raise ArgumentError, "PCSet.most_left_compact: All PCSets must be of same cardinality", caller
end
zeroed_pitch_arrays = pcset_array.map {|pcs| pcs.zero.pitches}
binaries = zeroed_pitch_arrays.map {|array| array_to_binary(array)}
winners = []
binaries.each_with_index do |num, i|
if num == binaries.min then winners.push(pcset_array[i]) end
end
winners.sort[0]
end
end
I'm calling them as follows:
> my_pcset = PCSet.new([0,2,4,6,8,10])
> my_pcset2 = PCSet.new([1,5,9])
It shoud return:
> my_pcset = PCSet.new([0,2,4,6,8,10])
=> [0, 2, 4, 6, 8, 10]
> my_pcset2 = PCSet.new([1,5,9])
=> [1, 5, 9]
But is returning nothing.
The code is available on github
Thanks
Try this in terminal: irb -r ./path_to_directory/pcset.rb and then initialize the objects.
I think the documentation for the repo is bad as it does not explain how you should be running this.
The result of
my_pcset = PCSet.new([0,2,4,6,8,10])
should set my_pcset to an instance of a PCSet not an array, so these lines from the README file are confusing at best.
3. How to use it
Make new PCSets:
my_pcset = PCSet.new([0,2,4,6,8,10])
=> [0, 2, 4, 6, 8, 10]
my_pcset2 = PCSet.new([1,5,9])
=> [1, 5, 9]
Looking at the code, I see inspect has been delegated to #pitches
def inspect
#pitches.inspect
end
I think if you inspect my_pcset you will get the expected result.
my_pcset = PCSet.new([0,2,4,6,8,10])
p my_pcset # will print [0, 2, 4, 6, 8, 10]
or `my_pcset.inspect` will return what you are expecting.

recursion method inside ruby minesweeper game stack level too deep

I am triggering endless recursion when trying to make a method that pulls up tiles when they are a zero. I have been testing by entering the following in irb:
class Board
attr_accessor :size, :board
def initialize(size = gets.chomp.to_i)
#size = size
#board = (1..#size).map { |x| ["L"] * #size }
end
def print_board
#board.map { |row| puts row.join }
end
end
class Mine
attr_accessor :proxi, :row, :col
def initialize(proxi)
#proxi = proxi
#row = 0
#col = 0
#random = Random.new
check_position
end
def check_position
if #proxi.board[#row - 1][#col - 1] != "L"
#row = #random.rand(1..#proxi.board.length)
#col = #random.rand(1..#proxi.board[0].length)
check_position
else
map_position
end
end
def map_position
#proxi.board[#row - 1][#col - 1] = "*"
end
end
b = Board.new(20)
m = (1..b.size * 2).map { |i| i = Mine.new(b) }
class Detector
attr_accessor :board, :proxi, :row, :col, :value
def initialize(board, proxi)
#board = board
#proxi = proxi
#row = 0
#col = 0
#value = 0
end
def mine?
if #proxi.board[#row - 1][#col - 1] == "*"
true
else
false
end
end
def detect
(#row - 1..#row + 1).each do |r|
(#col - 1..#col + 1).each do |c|
unless (r - 1 < 0 || r - 1 > #proxi.size - 1) || (c - 1 < 0 || c - 1 > #proxi.size - 1)
#value += 1 if #proxi.board[r - 1][c - 1] == "*"
end
end
end
end
def map_position
#proxi.board[#row - 1][#col - 1] = #value
#board.board[#row - 1][#col - 1] = #value
end
def recursion
if #proxi.board[#row - 1][#col - 1] == 0
(#row - 1..#row + 1).each do |r|
(#col - 1..#col + 1).each do |c|
unless (r - 1 < 0 || r - 1 > #proxi.size - 1) || (c - 1 < 0 || c - 1 > #proxi.size - 1)
#row, #col = r, c
detect
map_position
recursion
end
end
end
end
end
def reset
#row, #col, #value = 0, 0, 0
end
end
d = Detector.new(b, b)
b.print_board
If the output has plenty of free space in the upper right corner proceed to pasting the next part, else repaste.
d.row = 1
d.col = 1
d.mine?
d.detect
d.map_position
d.recursion
b.print_board
It will error out with a stack level too deep error at the recursion method. I know this is because it is having issues ending the recursive pattern. I thought my two unless statements deterring it from searching off the board would limit it to the area in the board. Plus the mines would force it to be limited in zeros it can expose. Maybe it is somehow writing spaces off the board or overwriting things on the board?
You don’t need a recursion here. Simply check each position for mines around:
Please always use 0-based arrays to eliminate lots of #blah - 1.
In detect you need to return immediately if there is a mine and set the #value otherwise:
def detect
return if #proxi.board[#row][#col] == '*'
value = 0 # no need to be global anymore
(#row - 1..#row + 1).each do |r|
(#col - 1..#col + 1).each do |c|
unless r < 0 || r >= #proxi.size || c < 0 || c >= #proxi.size
value += 1 if #proxi.board[r][c] == "*"
end
end
end
#proxi.board[#row][#col] = value
end
Now you don’t need map_position method at all. Simply check all the cells:
def check
(0..#proxi.size - 1).each do |r|
(0..#proxi.size - 1).each do |c|
#row, #col = r, c
detect
end
end
end
Hope it helps.
Exceeding the stack size is usually an indication that your recursion does not have the correct terminating condition. In your case, what mechanism is in place to prevent recursion from being called multiple times with the same #row #col pair? Note that of the 9 pairs that (#row - 1..#row + 1) (#col - 1..#col + 1) produce, one of those pairs is #row #col itself. The function will call itself infinitely many times!
A simple way to solve this would be to have something like a revealed array that keeps track of visited cells. Then recursion would mark each cell it visits as visited and return immediately if it is called on an already visited cell.
Additionally, your use of instance variables is extremely fragile here. Recursion relies on the fact that each function call has its own scope, but every call of recursion shares the same instance variables - which you're using to pass arguments! You should be using method arguments to keep the scopes distinct.

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

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

more ruby way of doing project euler #2

I'm trying to learn Ruby, and am going through some of the Project Euler problems. I solved problem number two as such:
def fib(n)
return n if n < 2
vals = [0, 1]
n.times do
vals.push(vals[-1]+vals[-2])
end
return vals.last
end
i = 1
s = 0
while((v = fib(i)) < 4_000_000)
s+=v if v%2==0
i+=1
end
puts s
While that works, it seems not very ruby-ish—I couldn't come up with any good purely Ruby answer like I could with the first one ( puts (0..999).inject{ |sum, n| n%3==0||n%5==0 ? sum : sum+n }).
For a nice solution, why don't you create a Fibonacci number generator, like Prime or the Triangular example I gave here.
From this, you can use the nice Enumerable methods to handle the problem. You might want to wonder if there is any pattern to the even Fibonacci numbers too.
Edit your question to post your solution...
Note: there are more efficient ways than enumerating them, but they require more math, won't be as clear as this and would only shine if the 4 million was much higher.
As demas' has posted a solution, here's a cleaned up version:
class Fibo
class << self
include Enumerable
def each
return to_enum unless block_given?
a = 0; b = 1
loop do
a, b = b, a + b
yield a
end
end
end
end
puts Fibo.take_while { |i| i < 4000000 }.
select(&:even?).
inject(:+)
My version based on Marc-André Lafortune's answer:
class Some
#a = 1
#b = 2
class << self
include Enumerable
def each
1.upto(Float::INFINITY) do |i|
#a, #b = #b, #a + #b
yield #b
end
end
end
end
puts Some.take_while { |i| i < 4000000 }.select { |n| n%2 ==0 }
.inject(0) { |sum, item| sum + item } + 2
def fib
first, second, sum = 1,2,0
while second < 4000000
sum += second if second.even?
first, second = second, first + second
end
puts sum
end
You don't need return vals.last. You can just do vals.last, because Ruby will return the last expression (I think that's the correct term) by default.
fibs = [0,1]
begin
fibs.push(fibs[-1]+fibs[-2])
end while not fibs[-1]+fibs[-2]>4000000
puts fibs.inject{ |sum, n| n%2==0 ? sum+n : sum }
Here's what I got. I really don't see a need to wrap this in a class. You could in a larger program surely, but in a single small script I find that to just create additional instructions for the interpreter. You could select even, instead of rejecting odd but its pretty much the same thing.
fib = Enumerator.new do |y|
a = b = 1
loop do
y << a
a, b = b, a + b
end
end
puts fib.take_while{|i| i < 4000000}
.reject{|x| x.odd?}
.inject(:+)
That's my approach. I know it can be less lines of code, but maybe you can take something from it.
class Fib
def first
#p0 = 0
#p1 = 1
1
end
def next
r =
if #p1 == 1
2
else
#p0 + #p1
end
#p0 = #p1
#p1 = r
r
end
end
c = Fib.new
f = c.first
r = 0
while (f=c.next) < 4_000_000
r += f if f%2==0
end
puts r
I am new to Ruby, but here is the answer I came up with.
x=1
y=2
array = [1,2]
dar = []
begin
z = x + y
if z % 2 == 0
a = z
dar << a
end
x = y
y = z
array << z
end while z < 4000000
dar.inject {:+}
puts "#{dar.sum}"
def fib_nums(num)
array = [1, 2]
sum = 0
until array[-2] > num
array.push(array[-1] + array[-2])
end
array.each{|x| sum += x if x.even?}
sum
end

Resources