Creating sort visualiser in Ruby - ruby

I'm trying to make a sort visualiser using Ruby and Gosu. When the user left clicks it will sort the numbers out using a insertion sort. When the user right clicks it will sort the numbers out using a bubble sort. So far the only the insertion sort works but the bubble sort crashes after sorting out the first number. Does anyone know why? Thanks.
require 'gosu'
module ZOrder
BACKGROUND, MIDDLE, TOP = *0..2
end
SCREEN_WIDTH = 600 # needs to be COUNT * COLUMN_WIDTH
SCREEN_HEIGHT = 200 # Should be multiple of 100
MAX_VALUE = 100 # the range of the data 1 to 100
COUNT = 30 # Number of items
COL_WIDTH = 20 # suggested at least 10
class Column
# have a pointer to the neighbouring cells
attr_accessor :height, :value
def initialize(value)
#value = value
#height = (SCREEN_HEIGHT/MAX_VALUE) * value
end
end
class GameWindow < Gosu::Window
def initialize
super SCREEN_WIDTH, SCREEN_HEIGHT, false
self.caption = "Sort Visualiser"
#path = nil
#do_insert = false
#do_bubble = false
#columns = Array.new(COUNT)
column_index = 0
while (column_index < COUNT)
col = Column.new(rand(MAX_VALUE + 1))
#columns[column_index] = col
column_index += 1
end
#text_font = Gosu::Font.new(10)
end
def needs_cursor?
true
end
def insertion_sort(loop)
j = loop
done = false
while ((j > 0) and (!done))
if (#columns[j].value < #columns[j - 1].value)
temp = #columns[j - 1]
#columns[j - 1] = #columns[j]
#columns[j] = temp
else
done = true
end
j = j - 1
end
end
def bubble_sort(loop2)
j = loop2
i = loop2 + 1
done = false
while ((j > 0) and (!done))
if (#columns[j].value > #columns[i].value)
temp = #columns[j]
#columns[j] = #columns[i]
#columns[i] = temp
else
done = true
end
j = j - 1
end
end
def button_down(id)
case id
when Gosu::MsLeft
#do_insert = true
#loop = 0
#do_bubble = false
when Gosu::MsRight
#do_bubble = true
#loop2 = 0
#do_insert = false
end
end
def update
if (#do_insert)
puts "Doing insert #{#loop}"
if #loop < (COUNT)
insertion_sort(#loop)
#loop += 1
sleep(0.5)
else
#do_insert = false
end
end
if (#do_bubble)
puts "Doing bubble #{#loop2}"
if #loop2 < (COUNT)
bubble_sort(#loop2)
#loop2 += 1
sleep(0.5)
else
#do_bubble = false
end
end
end
def draw
column_index = 0
while (column_index < #columns.length)
color = Gosu::Color::GREEN
Gosu.draw_rect((column_index * COL_WIDTH), SCREEN_HEIGHT - #columns[column_index].height, COL_WIDTH, #columns[column_index].height, color, ZOrder::MIDDLE, mode=:default)
#text_font.draw("#{#columns[column_index].value}", (column_index * COL_WIDTH) + 5, SCREEN_HEIGHT - 10, ZOrder::TOP, 1.0, 1.0, Gosu::Color::RED)
column_index += 1
end
end
end
window = GameWindow.new
window.show
EDIT: Added in the rest of the code and removed some tags

Related

ruby packing variables and monkey patching

Okay so this is the code:
class Board
attr_reader :size
def initialize n
#grid = Array.new(n) {Array.new(n,:N)}
#size = n * n
end
def [] position
row, col = position
#grid[row][col]
end
def []= position, val
row, col = position
#grid[row][col] = val
end
def num_ships
#grid.flatten.count(:S)
end
def attack position
if self[position] == :S
self[position] = :H
puts "you sunk my battleship"
return true
else
self[position] = :X
return false
end
end
def place_random_ships
max_ships = #size * 0.25
while self.num_ships < max_ships
row = rand(0...#grid.length)
col = rand(0...#grid.length)
position = [row,col]
self[position] = :S
end
end
end
But,
def place_random_ships
max_ships = #size * 0.25
while self.num_ships < max_ships
row = rand(0...#grid.length)
col = rand(0...#grid.length)
position = [row,col]
self[position] = :S
end
end
this works, and does what it's suppose to, but when I avoid packing [row,col] and add it directly it does not work.
def place_random_ships
max_ships = #size * 0.25
while self.num_ships < max_ships
row = rand(0...#grid.length)
col = rand(0...#grid.length)
self[row,col] = :S
end
end
I'm still new to programming, so please try to explain the issue to where I can understand it, or tell me the problem, so I can google it to get a better understanding please.
The issue is that you defined []= to take 2 argument, and array and a value.
def []= position, val
row, col = position
#grid[row][col] = val
end
With your current implementation you would need to call it like this
foo[[row,col]] = :S
What you might want to to is define []= like this:
def []= row, col, val
#grid[row][col] = val
end
then when you want to pass the array position you can use the array spread operator. With this implementation both of these calls will work.
position = [1,2]
foo[1,2] = :S
foo[*position] = :S
if you do that you probably would want to define [] the same way.
def [] row,col
#grid[row][col]
end

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.

Ruby NoMethodError - Undefined method

The following is my code. I tried to only include the code where I think the problem may be.
Class Ship contains getStatus:
class Ship
def initialize(name, size, status, shipNumber, firedUpon)
#name = name
#size = size
#status = status
#shipNumber = shipNumber
#firedUpon = firedUpon
end
def setSize(nSize)
#size = nSize
end
def getSize
return #size
end
def setName(nName)
#name = nName
end
def getName()
return #name
end
def setStatus(nStatus)
#status = nStatus
end
def getStatus
return #status
end
def setFiredUpon(nFired)
#firedUpon = nFired
end
def getFiredUpon
return #firedUpon
end
def setShipNumber(nNum)
#shipNumber = nNum
end
def getShipNumber
return #shipNumber
end
def ==(rhs)
if (#name !=rhs.getName() || #size != rhs.getSize() || #status != rhs.getStatus() || #shipNumber != rhs.getShipNumber() || #firedUpon != rhs.getFiredUpon())
return false
end
return true
end
end
Class Board Calls upon getStatus and contains rangeIsOccupied:
load 'ship.rb'
class Board
def initialize()
#gameBoard = Array.new(100)
#Ships = Array.new(5)
#initialize all ships on board
r = 0
while(r < 100)
#gameBoard[r] = Ship.new('', -1, false, -1, false)
r = r + 1
end
#Ships[0] = Ship.new('Carrier', 5, true,0, false)
#Ships[1] = Ship.new('BattleShip', 4, true,1, false)
#Ships[2] = Ship.new('Cruiser', 3, true,2, false)
#Ships[3] = Ship.new('Submarine', 3, true,3, false)
#Ships[4] = Ship.new('Destroyer', 2, true,4, false)
end
def printBoard()
board_size = 10
alphabet = 'abcdefghijklmnopqrstuvwxyz'
puts 'x = hit ship' "\n" 'o = ship on board' "\n" 'm = empty space' "\n"
puts '---------------------------------------------------------' "\n"
puts ' |A| |B| |C| |D| |E| |F| |G| |H| |I| |J|'
s = 0
rownum = 0
printrow = true
while(s < 100)
if printrow
print rownum
print ' - '
print ' '
printrow = false
end
if #gameBoard[s].getShipNumber() != -1 && #gameBoard[s].getFiredUpon()
print 'x'
elsif(!#gameBoard[s].getStatus)
print 'm'
else
print 'o'
end
if s % 10 == 9
print "\n"
printrow = true
rownum = rownum + 1
else
print ' '
end
s = s + 1
end
end
def isValidDirection(x1, y1, x2, y2)
if x1 == x2 || y1 == y2
return true
end
return false
end
def rangeIsOccupied(x1, y1, x2, y2)
#if horizontal
if(y1 == y2)
while(x1 != x2)
if #gameBoard[(y1*10)+x1].
return true
end
if x1 > x2
x1 = x1 - 1
else
x1 = x1 + 1
end
end
if #gameBoard[(y1*10)+x1].getStatus
return true
end
else
while y1 != y2
if #gameBoard[(y1*10)+x1].getStatus
return true
end
if y1 > y2
y1 = y1 - 1
else
y1 = y1 + 1
end
end
if #gameBoard[(y1*10)+x1].getStatus
return true
end
end
return false
end
Class Game calls getBoard() and randomizeFleet, the start of the problem:
load 'player.rb'
class Game
def initialize()
#p1 = Player.new('', 1, true)
#p2 = Player.new('cpu', 2, false)
gamemode = 0
puts '---------------------------------------------------------'
print "Gamemodes:\n1. Player vs. CPU\n2. CPU vs. CPU\n"
puts '---------------------------------------------------------'
print "Please select a gamemode (1/2):\n: "
gamemode = gets.chomp
#p2.getBoard().randomizeFleet()
When I try to run my codeI get the error:
board:89:in rangeIsOccupied': undefined methodgetStatus' for nil:NilClass (NoMethodError)
I would like to overcome this issue.
if you are not sure that #gameBoard[(y1*10)+x1] will return a ship instance, then you can add another clause to your conditionals, like:
if #gameBoard[(y1*10)+x1] && #gameBoard[(y1*10)+x1].getStatus

How to improve time complexity of this code piece?

I am having a hard time trying to down down the time. If this can be done in O(n^2) thatd be awesome.
def printDistance(file)
line = file.gets
if line == nil then return end
sz, sx, sy, ex, ey = line.split(/\s/)
#counter = 0
while line = file.gets do
if line[0...4] == "path"
else
x, y, ds, w = line.split(/\s/,4)
x = x.to_i
y = y.to_i
matrix= Array.new
later = Array.new
tmp = Array.new
processing = Array.new
if matrix[y].class != Array
matrix[y] = Array.new
end
if ds == "" #this cell has NO way to get to
matrix[y][x] = nil
else
matrix[y][x] = ds
end
end
end
for y in 0...matrix.length
processing[y] = Array.new
tmp[y] = Array.new
later[y] = Array.new
end
printing = Array.new
counter = 0
sy = sy.to_i
sx = sx.to_i
processing[sy][sx] = matrix[sy][sx]
matrix[sy][sx] = nil
puts "#{counter},(#{sx},#{sy})" #first one
counter += 1
loop do
print "#{counter},"
counter += 1
for y in 0...processing.length
for x in 0...processing[y].length
if processing[y][x].class != nil
tmp[y][x] = processing[y][x]
dirArr = tmp[y][x].to_s.split(//)
dirArr.each { |c|
if c == "u"
newY = y - 1
newX = x
elsif c == "d"
newY = y + 1
newX = x
elsif c == "l"
newY = y
newX = x - 1
else #c == r
newY = y
newX = x + 1
end
if matrix[newY][newX] != nil
tmpStr = "(#{newX},#{newY})"
printing.unshift(tmpStr)
later[newY][newX] = matrix[newY][newX]
matrix[newY][newX] = nil
end
}
end
end
end
printing.sort!
for i in 0...printing.length
print printing[i]
if i < printing.length - 1
print ","
end
end
printing = [] #resetting
puts
for i in 0...later.length
for j in 0...later[i].length
if later[i][j] != nil
processing[i][j] = later[i][j]
end
end
end
break if NotEmpty(matrix) == false
end
end
def NotEmpty (a)
for i in 0...a.length
for j in 0...a[i].length
if a[i][j] != nil
return true
end
end
end
return false
end
Basically this code reads in a file and places it in a 2-d array representing a maze, then based on maze's starting point it will perform a BFS to put all cells in order from closest to the start to the farthest, then print everything out
This code is now O(n^3) but I am trying to shrink it to O(n^2), is there anyway I can traverse a 2-d array and keeping track of the x and y values without using two forloops?
Any help is appreciated!! Thanks!

ruby code stopping at run time, seemingly an infinite loop

if i run the code, it will stop and not do anything and i am unable to type. seems to be an infinite loop.
the problem seems to be the end until loop, however if i take that out, my condition will not be met.
can anyone find a solution? i have tried all the loops that i can think of.
/. 2d array board ./
board = Array.new(10) { Array.new(10, 0) }
/. printing board ./
if board.count(5) != 5 && board.count(4) != 4 && board.count(3) != 3
for i in 0..9
for j in 0..9
board[i][j] = 0
end
end
aircraftcoord1 = (rand*10).floor
aircraftcoord2 = (rand 6).floor
aircraftalign = rand
if aircraftalign < 0.5
for i in 0..4
board[aircraftcoord2+i][aircraftcoord1] = 5
end
else
for i in 0..4
board[aircraftcoord1][aircraftcoord2+i] = 5
end
end
cruisercoord1 = (rand*10).floor
cruisercoord2 = (rand 7).floor
cruiseralign = rand
if cruiseralign < 0.5
for i in 0..3
board[cruisercoord2+i][cruisercoord1] = 4
end
else
for i in 0..3
board[cruisercoord1][cruisercoord2+i] = 4
end
end
destroyercoord1 = (rand*10).floor
destroyercoord2 = (rand 8).floor
destroyeralign = rand
if destroyeralign < 0.5
for i in 0..2
board[destroyercoord2+i][destroyercoord1] = 3
end
else
for i in 0..2
board[destroyercoord1][destroyercoord2+i] = 3
end
end
end until board.count(5) == 5 && board.count(4) == 4 && board.count(3) == 3
print " "
for i in 0..9
print i
end
puts
for i in 0..9
print i
for j in 0..9
print board[i][j]
end
puts
end
The line board.count(5) == 5 ... will never be true because board is a two-dimensional array. I can't tell what the condition should be, but it could look something like:
board[5].count(5) == 5

Resources