Filling individual cells in a grid

Hi guys,

can someone please lend me a hand in this. I have a piece of code that
generates a grid like structure. All the cells in this grid now have 2
properties namely a celltype and a cell distance (to cells with type 1).

For now the code can only define celltypes to rows and columns. I need
to add a piece of code that will let me define celltypes to individual
cells. Does anyone know how I can achieve this and what pieces of code I
need to add?

I could really use a hand of someone more experienced in Ruby as I am.
Thanks in advance!

Greets tillaart36...

Attachments:
http://www.ruby-forum.com/attachment/218/testgrid3.rb

···

--
Posted via http://www.ruby-forum.com/.

With your current code...

grid[1,1].type = 3
grid[1,1].distance_road = 5

Todd

···

On 9/3/07, Joop Van den tillaart <tillaart36@hotmail.com> wrote:

Hi guys,

can someone please lend me a hand in this. I have a piece of code that
generates a grid like structure. All the cells in this grid now have 2
properties namely a celltype and a cell distance (to cells with type 1).

For now the code can only define celltypes to rows and columns. I need
to add a piece of code that will let me define celltypes to individual
cells. Does anyone know how I can achieve this and what pieces of code I
need to add?

I could really use a hand of someone more experienced in Ruby as I am.
Thanks in advance!

Greets tillaart36...

Attachments:
http://www.ruby-forum.com/attachment/218/testgrid3.rb

With your current code...

grid[1,1].type = 3
grid[1,1].distance_road = 5

Todd

Hey,

thanks for your help. I was working the code myself and found another
way of individual filling but your way is much cleaner I think. Is there
also a way of filling a group of cells (which is not a full column or a
full row)?

All the cells with type 1 are are already defined and then I need to
fill like 60% of the remaining cells with type 3 and the other 40% with
type 4. I think I need to add a method to the code which lets me do that
but I'm don't have much experience with ruby so I don't know how to do
this...

Can anybody help me further on this?

···

--
Posted via http://www.ruby-forum.com/\.

Is there no one else who can help me out a bit?

Thanks...

···

--
Posted via http://www.ruby-forum.com/.

it's been less than three hours since you posted your original
question. Patience is a wonderful thing.

···

On 9/3/07, Joop Van den tillaart <tillaart36@hotmail.com> wrote:

Is there no one else who can help me out a bit?

Thanks...

--
Posted via http://www.ruby-forum.com/\.

it's been less than three hours since you posted your original
question. Patience is a wonderful thing.

···

On 9/3/07, Joop Van den tillaart <tillaart36@hotmail.com> wrote:

Is there no one else who can help me out a bit?

Thanks...

--
Posted via http://www.ruby-forum.com/\.

OK, I'll make some suggestions.
1. I think you could make your life a lot easier if you gave your cell objects more info about where they live.
2. I suggest you fill @grid with cells during initialization.
3. I suggest you include Enumerable in your Grid class. Then you only have to define Grid#each to get map, collect, and whole more for free.

<code>
class Cell
    attr_accessor :type, :distance_road
    attr_reader :i
    def initialize(grid, i)
       @my_grid = grid
       @i = i
    end
    def xy
       @i.divmod(@my_grid.width).reverse
    end
    def inspect
       "Cell[#{@i}, #{xy.inspect}, #{type}, #{distance_road}]"
    end
end
class Grid
    include Enumerable
    attr :width, :heigh
    def initialize(width, height)
       @grid = Array.new(width * height) { |i| Cell.new(self, i) }
       @width = width
       @height = height
    end
    def (x, y)
       raise IndexError.new("Index (#{x}, #{y}) out of range") \
          if x < 0 || y < 0 || x >= @width || y >= @width
       @grid[y * width + x]
    end
    def =(x, y, value)
       raise IndexError.new("Index (#{x}, #{y}) out of range") \
          if x < 0 || y < 0 || x >= @width || y >= @width
       @grid[y * width + x] = value
    end
    def each
       @grid.each { |cell| yield cell }
    end
end

# Now you can do all kinds of neat things.

g = Grid.new(2, 2)
p g
g.map { |cell| cell.type = 0; cell.distance_road = cell.i % 2 }
p g
h = g.select { |cell| cell.distance_road == 1 }
h.each { |cell| cell.type = 42 }
p g
p g.any? { |cell| cell.type == 42 }
p g.all? { |cell| g[*cell.xy] == cell }
</code>

<result>
#<Grid:0x7b128 @width=2,
                @grid=[Cell[0, [0, 0], , ], Cell[1, [1, 0], , ],
                       Cell[2, [0, 1], , ], Cell[3, [1, 1], , ]],
                @height=2>
#<Grid:0x7b1a0 @width=2,
                @grid=[Cell[0, [0, 0], 0, 0], Cell[1, [1, 0], 0, 1],
                       Cell[2, [0, 1], 0, 0], Cell[3, [1, 1], 0, 1]],
                @height=2>
#<Grid:0x7b1a0 @width=2,
                @grid=[Cell[0, [0, 0], 0, 0], Cell[1, [1, 0], 42, 1],
                       Cell[2, [0, 1], 0, 0], Cell[3, [1, 1], 42, 1]],
                @height=2>
true
</result>

Regards, Morton

···

On Sep 3, 2007, at 8:40 AM, Joop Van den tillaart wrote:

Is there no one else who can help me out a bit?

Wow, thanks for your help...

Im trying it out right now...

···

--
Posted via http://www.ruby-forum.com/.

Joop Van den tillaart wrote:

Wow, thanks for your help...

Im trying it out right now...

Hey all you guys...

me and someone of my university have set up a new way of generating the
grid.

For now it generates a grid of 20x20 with 2 columns and 1 row filled
with celltype 1. The other cells are set to value 0.

I want the remaining cells with value 0 to be divided in say 60% type 2
and the remaining 40% (of the remaining 0 cells) to be valued as type 3.

Does anyone know how to do this in a neat way (from a programmers point
of view) and if so can anyone share some techniques with me?

See the attachment for the new generating of the grid.

Thanks in advance!

Attachments:
http://www.ruby-forum.com/attachment/233/testje.rb

···

--
Posted via http://www.ruby-forum.com/\.

Joop Van den tillaart wrote:

Wow, thanks for your help...

Im trying it out right now...

Hey all you guys...

me and someone of my university have set up a new way of generating the
grid.

For now it generates a grid of 20x20 with 2 columns and 1 row filled
with celltype 1. The other cells are set to value 0.

I want the remaining cells with value 0 to be divided in say 60% type 2
and the remaining 40% (of the remaining 0 cells) to be valued as type 3.

Does anyone know how to do this in a neat way (from a programmers point
of view) and if so can anyone share some techniques with me?

Are you asking for a random 40% of the cells to be assigned type 3 state while the remaining 60% is assigned type 2? Or is there some other criterion?

See the attachment for the new generating of the grid.

I looked at your code and here are some comments:

!. I think you got x and y interchanged. You won't see the problem as long you are using square grids. So try it with 20-wide by 15-high grid. The way you have set it up, it is impossible to traverse the grid from top to bottom, right-to-left, with Grid#each, which is something you are going to want to do. Compare print_field_values to print_grid in the code below.

2. Look at how I rewrote Grid# below.

3. Since you are using OpenStructs to model your cells, I can't see how you going to write a useful Grid#=, but the one you have now can't possibly work.

Regards, Morton

<code>
require 'ostruct'

class Grid
   include Enumerable

   # def initialize(width, height)
   # @grid = Array.new(width) do |x|
   # Array.new(height) do |y|
   # OpenStruct.new(:x => x, :y => y, :grid => self)
   # end
   # end
   # end

   def initialize(width, height)
     @grid = Array.new(height) do |row|
       Array.new(width) do |col|
         OpenStruct.new(:x => col, :y => row, :grid => self)
       end
     end
   end

   def width
     @grid.first.size
   end

   def height
     @grid.size
   end

   # def width
   # @grid.size
   # end

···

On Sep 6, 2007, at 7:44 AM, Joop Van den tillaart wrote:
   #
   # def height
   # @grid.first.size
   # end

   def each
     @grid.each do |row|
       row.each do |cell|
         yield cell
       end
     end
   end

   def (x, y)
     @grid[y] if @grid[y]
   end

   # def (x, y)
   # return @grid[y] if @grid
   # nil
   # end

   # This can't work -- super[y] means (self.(Object#(x))).(y)
   # which can't possibly be what is wanted.
   # def =(x, y, value)
   # if @grid && @grid[y]
   # super[y] = value
   # else
   # raise IndexError.new
   # end
   # end

   def print_field_values(field_name = :cell_type)
      each_with_index do |cell, i|
         print "%02d " % cell.send(field_name)
         puts if i % width == width - 1
      end
   end

end

def print_grid(grid, field_name = :cell_type)
   grid.height.times do |y|
     grid.width.times do |x|
       print "%02d " % grid[x,y].send(field_name)
     end
     puts
   end
end

def calculate_distance(grid, field_name)
   updated = true
   while updated do
     updated = false
     grid.each do |cell|
       for x in (cell.x - 1)..(cell.x + 1)
         for y in (cell.y - 1)..(cell.y + 1)
           neighbour = grid[x, y]
           next if neighbour.nil? || cell == neighbour || x<0 || y< 0
           if neighbour.send(field_name) && (cell.send(field_name).nil? || neighbour.send(field_name) + 1 < cell.send(field_name))
             cell.send(field_name.to_s + "=", neighbour.send(field_name) + 1)
             updated = true
           end
         end
       end
     end
   end
end

grid = Grid.new(20, 15)
grid.each { |cell| cell.cell_type = 0 }
grid.height.times { |y| grid[19,y].cell_type = 1 }
grid.height.times { |y| grid[9,y].cell_type = 1 }
grid.width.times { |x| grid[x,9].cell_type = 1 }
grid.each do |cell|
   if cell.cell_type == 1
     cell.distance_road = 0
     cell.locked = true
   end
end

grid.each do |cell|
   if cell.cell_type == 0
     cell.cell_type = 2
   end
end

print_grid(grid, :cell_type)
puts
grid.print_field_values(:cell_type)
</code>

hi thanks for your help,

im not sure what you meant with your comments but i will look into
them...again thanks...

And my goal for filling the cells is as you say...the remaining cells
just have to be filled with say 60% type 2 en the remaining 40% of cells
with type 3. This can be done random or just first 60% type2 and the
other type 3.

When this is completed i need to make an algorithm that starts swapping
celltypes depending on neighbour cells and distances to other cells...i
won't go to deep into this but it doesn't matter how the cells in the
first stage are filled...just the types 1 are on a own place because
they characterize a road which is laid in before the algorithm starts
swapping...

So can anyone tell how to define the first 60% as type 2 and the
remaining cells with type 0 to type 3??

thanks!

···

--
Posted via http://www.ruby-forum.com/.

hi thanks for your help,

You're welcome.

im not sure what you meant with your comments but i will look into
them...again thanks.

I'm trying to keep you from shooting yourself in the foot :slight_smile:

And my goal for filling the cells is as you say...the remaining cells
just have to be filled with say 60% type 2 en the remaining 40% of cells
with type 3. This can be done random or just first 60% type2 and the
other type 3.

When this is completed i need to make an algorithm that starts swapping
celltypes depending on neighbour cells and distances to other cells...i
won't go to deep into this but it doesn't matter how the cells in the
first stage are filled...just the types 1 are on a own place because
they characterize a road which is laid in before the algorithm starts
swapping...

So can anyone tell how to define the first 60% as type 2 and the
remaining cells with type 0 to type 3??

<code>
require 'ostruct'

class Grid
   include Enumerable

   def initialize(width, height)
     @grid = Array.new(height) do |row|
       Array.new(width) do |col|
         OpenStruct.new(:x => col, :y => row, :grid => self)
       end
     end
   end

   def width
     @grid.first.size
   end

   def height
     @grid.size
   end

   def each
     @grid.each do |row|
       row.each do |cell|
         yield cell
       end
     end
   end

   def (x, y)
     @grid[y] if @grid[y]
   end

   def print_field_values(field_name = :cell_type)
      each_with_index do |cell, i|
         print "%02d " % cell.send(field_name)
         puts if i % width == width - 1
      end
   end

end

grid = Grid.new(20, 15)
grid.each { |cell| cell.cell_type = 0 }
grid.height.times { |y| grid[19,y].cell_type = 1 }
grid.height.times { |y| grid[9,y].cell_type = 1 }
grid.width.times { |x| grid[x,9].cell_type = 1 }
grid.each do |cell|
   if cell.cell_type == 1
     cell.distance_road = 0
     cell.locked = true
   end
end

zero_cells = grid.select { |cell| cell.cell_type == 0 }
n = (0.6 * zero_cells.size).round
zero_cells[0..n-1].each { |cell| cell.cell_type = 2 }
zero_cells[n..-1].each { |cell| cell.cell_type = 3 }
grid.print_field_values
</code>

Regards, Morton

···

On Sep 6, 2007, at 11:38 AM, Joop Van den tillaart wrote:

I've thought of a more efficient way.

<code>
zero_cells = grid.select { |cell| cell.cell_type == 0 }
n = zero_cells.size
k = (0.6 * n).round
(0...k).each { |i| zero_cells[i].cell_type = 2 }
(k...n).each { |i| zero_cells[i].cell_type = 3 }
</code>

Regards, Morton

···

On Sep 6, 2007, at 4:47 PM, Morton Goldberg wrote:

<code>
zero_cells = grid.select { |cell| cell.cell_type == 0 }
n = (0.6 * zero_cells.size).round
zero_cells[0..n-1].each { |cell| cell.cell_type = 2 }
zero_cells[n..-1].each { |cell| cell.cell_type = 3 }
grid.print_field_values
</code>

Morton Goldberg wrote:

···

On Sep 6, 2007, at 4:47 PM, Morton Goldberg wrote:

I've thought of a more efficient way.

Hey man,

again thanks for your help...as you will have noticed I'm not an expert
at ruby but I'm sure appreciating the help I get from you people...

Let me have a go with this code and see where it gets me...

Thanks again!

--
Posted via http://www.ruby-forum.com/\.

Hi guys,

i'm back with a new problem with my grid:

I have three celltypes:

1 = road
2 = housing
3 = green

Each type has a table where preference scores are stored regarding the
adjacency of other celltypes...these are stored in the hash ATable...

Now i have to code an algorithm that iterates over all cells and which
calculates adjacency scores...I have made a word document where i try to
explain what the algorithm needs to do. Me and a teacher have coded two
things for this:

···

----------------------------
def scoreA(cell)
  # here the algorithm has to be placed
end
----------------------------

The adjacency score of one cell needs to be calculated within this
method...

----------------------------
for cell1 in grid
  for cell2 in grid
# # compare cell1 with cell2
    next if cell1 == cell2
    next if cell1.locked || cell2.locked

    # calculate score for two cells together
    a_before = scoreA(cell1) + scoreA(cell2)

    # swap cells
    cell1.cell_type, cell2.cell_type = cell2.cell_type, cell1.cell_type

    # calculate score for two cells together
    a_after = scoreA(cell1) + scoreA(cell2)

    # if last score is lower or even as the score before swap, then swap
cells back to first situation
    if a_after <= a_before
    cell1.cell_type, cell2.cell_type = cell2.cell_type, cell1.cell_type
    end
  end
end
----------------------------

the whole swapping procedure should be in this code above...

Now I think i have to design the code which calculates the score of one
cell regarding its neighbouring cells with the help of the ATable hash.
This piece of code has to be in the method scoreA(cell)...

but I'm really stuck in how to do this. Besides that I realize that it
is a long story / question I ask so maybe it won't get much reply, but
on the other hand if someone is interested in helping me out a bit I
would be very grateful...

Anyways I have attached my ruby file and a word document in which i
tried to explain the procedure of the algorithm...

Thanks in advance!

Attachments:
http://www.ruby-forum.com/attachment/265/testje.rb

--
Posted via http://www.ruby-forum.com/.

and the word document...

Attachments:
http://www.ruby-forum.com/attachment/266/procedure_algorithm_adjacency.doc

···

--
Posted via http://www.ruby-forum.com/.

Hi guys,

i'm back with a new problem with my grid:

I have three celltypes:

1 = road
2 = housing
3 = green

Each type has a table where preference scores are stored regarding the
adjacency of other celltypes...these are stored in the hash ATable...

Now i have to code an algorithm that iterates over all cells and which
calculates adjacency scores...I have made a word document where i try to
explain what the algorithm needs to do. Me and a teacher have coded two
things for this:

----------------------------
def scoreA(cell)
  # here the algorithm has to be placed
end
----------------------------

The adjacency score of one cell needs to be calculated within this
method...

----------------------------
for cell1 in grid
  for cell2 in grid
# # compare cell1 with cell2
    next if cell1 == cell2
    next if cell1.locked || cell2.locked

    # calculate score for two cells together
    a_before = scoreA(cell1) + scoreA(cell2)

    # swap cells
    cell1.cell_type, cell2.cell_type = cell2.cell_type, cell1.cell_type

    # calculate score for two cells together
    a_after = scoreA(cell1) + scoreA(cell2)

    # if last score is lower or even as the score before swap, then swap
cells back to first situation
    if a_after <= a_before
    cell1.cell_type, cell2.cell_type = cell2.cell_type, cell1.cell_type
    end
  end
end
----------------------------

I see one problem with the above code -- it walks the entire adjacency matrix. It would be better to redesign it to walk only on either the upper or the lower triangular sub-matrix. Then you only need to deal with each distinct cell pairing once.

Attachments:

Sorry. There is no way that I'm going to open a Word document of unknown content on my computer.

Regards, Morton

···

On Sep 11, 2007, at 4:57 AM, Joop Van den tillaart wrote:

part b

Attachments:
http://www.ruby-forum.com/attachment/267/procedure_algorithm_adjacency_b.doc

···

--
Posted via http://www.ruby-forum.com/.

Morton Goldberg wrote:

Each type has a table where preference scores are stored regarding the
def scoreA(cell)
# # compare cell1 with cell2
    # calculate score for two cells together
end
----------------------------

I see one problem with the above code -- it walks the entire
adjacency matrix. It would be better to redesign it to walk only on
either the upper or the lower triangular sub-matrix. Then you only
need to deal with each distinct cell pairing once.

Attachments:

Sorry. There is no way that I'm going to open a Word document of
unknown content on my computer.

Regards, Morton

I noticed that too...it doesnt look to the surrounding cells on a
distance of 1 cell...it walks through all the cells...how do i change
the code so it will only take into account surrounding cells on distance
1?

And euhm...why do you worry about the word document? It's just a brief
explanation of what the algorithm should do...I'm sure you have your
reasons for not opening it (but I don't see them :D)...anyways thanks
for your help so far...

···

On Sep 11, 2007, at 4:57 AM, Joop Van den tillaart wrote:

--
Posted via http://www.ruby-forum.com/\.

Morton Goldberg wrote:

Each type has a table where preference scores are stored regarding the
def scoreA(cell)
# # compare cell1 with cell2
    # calculate score for two cells together
end
----------------------------

I see one problem with the above code -- it walks the entire
adjacency matrix. It would be better to redesign it to walk only on
either the upper or the lower triangular sub-matrix. Then you only
need to deal with each distinct cell pairing once.

Attachments:

Sorry. There is no way that I'm going to open a Word document of
unknown content on my computer.

Regards, Morton

I noticed that too...it doesnt look to the surrounding cells on a
distance of 1 cell...it walks through all the cells...how do i change
the code so it will only take into account surrounding cells on distance
1?

<code>
require 'ostruct'

class Grid
    include Enumerable

    def initialize(width, height)
       @grid = Array.new(height) do |row|
          Array.new(width) do |col|
             OpenStruct.new(:x => col, :y => row, :grid => self)
          end
       end
    end

    def width
       @grid.first.size
    end

    def height
       @grid.size
    end

    def each
       @grid.each do |row|
          row.each do |cell|
             yield cell
          end
       end
    end

    def (x, y)
       @grid[y] if @grid[y]
    end

    def print_field_values(field_name = :cell_type)
       each_with_index do |cell, i|
          print "%02d " % cell.send(field_name)
          puts if i % width == width - 1
       end
    end

    def each_with_neighbor
       each { |cell| cell.visited = false }
       each do |cell|
          next if cell.locked
          neighbors(cell).each { |other| yield cell, other }
          cell.visited = true
       end
    end

    def neighbors(cell)
       result =
       x, y = cell.x, cell.y
       (-1..1).each do |dx|
          (-1..1).each do |dy|
             begin
                next if dx == 0 && dy == 0
                _cell = cell.grid[x+dx, y+dy]
                result << _cell unless _cell.locked || _cell.visited
             rescue IndexError
                next
             end
          end
       end
       result
    end

end

# I'm setting up a small grid here to reduce the amount of output.
grid = Grid.new(5, 4)
grid.each { |cell| cell.cell_type = 0 }
grid.height.times { |y| grid[4, y].cell_type = 1 }
grid.height.times { |y| grid[2, y].cell_type = 1 }
grid.width.times { |x| grid[x, 3].cell_type = 1 }
grid.each do |cell|
    if cell.cell_type == 1
       cell.distance_road = 0
       cell.locked = true
    end
end

zero_cells = grid.select { |cell| cell.cell_type == 0 }
n = zero_cells.size
k = (0.6 * n).round
(0...k).each { |i| zero_cells[i].cell_type = 2 }
(k...n).each { |i| zero_cells[i].cell_type = 3 }
grid.print_field_values

puts

# Example showing how to use each_with_neighbor. Shows where your code
# would go. Also prints outs what cell pairs get processed.
grid.each_with_neighbor do |cell, other|
    # # calculate score for two cells together
    # a_before = scoreA(cell) + scoreA(other)
    # # swap cells
    # cell.cell_type, other.cell_type = other.cell_type, cell.cell_type
    # # calculate score for two cells together
    # a_after = scoreA(cell) + scoreA(other)
    # # if last score is lower or even as the score before swap,
    # # then swap cells back to first situation
    # if a_after <= a_before
    # cell.cell_type, other.cell_type = other.cell_type, cell.cell_type
    # end
    p [[cell.x, cell.y, cell.cell_type],
       [other.x, other.y, other.cell_type]]
end
</code>

And euhm...why do you worry about the word document? It's just a brief
explanation of what the algorithm should do...I'm sure you have your
reasons for not opening it (but I don't see them :D)...anyways thanks
for your help so far...

There are viruses that attach themselves to Word documents and which spread when someone downloads the document and opens it on uninfected computer.

If your explanation is brief, why not post it as part of a message (not an attachment)? If you do, I'm not sure I'll implement it for you. I'm beginning to think that I've been doing too much of your school work for you, and it would be better you did more of it yourself. But then again I might or at least give some pointers or someone else may be willing to help you.

Regards, Morton

···

On Sep 11, 2007, at 7:57 AM, Joop Van den tillaart wrote:

On Sep 11, 2007, at 4:57 AM, Joop Van den tillaart wrote: