On Sep 11, 2007, at 4:34 PM, Morton Goldberg wrote:

> As is not unusual for me, I've had second thoughts. Here is a  
> better version.
>
> <code>
>    def each_with_neighbor
>       each do |cell|
>          next if cell.locked
>          neighbors(cell).each { |other| yield cell, other }
>       end
>    end
>
>    DELTAS = [[1, 0], [-1, 1], [0, 1], [1, 1]]
>    def neighbors(cell)
>       result = []
>       x, y = cell.x, cell.y
>       DELTAS.each do |dx, dy|
>          begin
>             _cell = cell.grid[x+dx, y+dy]
>             result << _cell unless _cell.locked
>          rescue IndexError
>             next
>          end
>       end
>       result
>    end
> </code>

Third thoughts. I solved the wrong problem. On further consideration,  
I think this is want you are looking for:

<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][x] 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_remaining
       each do |cell|
          next if cell.locked
          x, y = cell.x, cell.y
          (x+1...width).each do |col|
             _cell = cell.grid[col, y]
             yield cell, _cell unless _cell.locked
          end
          (y+1...height).each do |row|
             (0...width).each do |col|
                _cell = cell.grid[col, row]
                yield cell, _cell unless _cell.locked
             end
          end
       end
    end

    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_remaining. Shows where your code
# would go. Also prints outs what cell pairs get processed.
grid.each_with_remaining 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>

Regards, Morton