Ka Mok - 4 months ago 7
Ruby Question

# How to refactor consecutive, independent, if statements in this algorithm?

The following method generates 81

`Cell`
objects that each have their distinct
`row`
,
`column`
, and
`blocks`
. It uses an algorithm that changes those attributes based on the
`Cell`
that's currently be generated.

The
`1.times do`
portion is implemented to skip that block of
`if`
statements on the first loop inside the
`until`
loop, when the
`cell_counter`
is 0. How do I make this more elegant?

``````def initialize_default_cells
cell_counter, row, column = 0,0,0
block = 1

until cell_counter == 81
1.times do
break if cell_counter == 0
if cell_counter % 1 == 0
column += 1
end
if cell_counter % 3 == 0
block += 1
end
if cell_counter % 9 == 0
column -= 9
row += 1
block -= 3
end
if cell_counter % 27 == 0
block += 3
end
end
@cells << Cell.new(ROW_ID[row], COLUMN_ID[column], block)
cell_counter += 1
end
end
``````

I concluded that it was easiest to calculate `row`, `column` and `block` from scratch for each `i = 0,..,80`.

``````def initialize_default_cells
(0..80).each do |i|
@cells << Cell.new(ROW_ID[i/9], COLUMN_ID[i%9], 1 + (i%9)/3 + 3*(i/27))
end
end
``````

The key for `COLUMN_ID` (`i%9`) is reduced from `i-9*(i/9)` and the last argument (`1 + (i%9)/3 + 3*(i/27)`) is reduced from `1 + i/3 - 3*(i/9) + 3*(i/27)`

Consider three examples.

`i=0`

``````@cells << Cell.new(ROW_ID[0/9], COLUMN_ID[0%9], 1 + (0%9)/3 + 3*(0/27))
#=> << Cell.new(ROW_ID[0], COLUMN_ID[0], 1)
``````

`i=6`

``````@cells << Cell.new(ROW_ID[6/9], COLUMN_ID[6%9], 1 + (6%9)/3 + 3*(6/27))
#=> << Cell.new(ROW_ID[0], COLUMN_ID[6], 3)
``````

`i=29`

``````@cells << Cell.new(ROW_ID[29/9], COLUMN_ID[29%9], 1 + (29%9)/3 + 3*(29/27))
# << Cell.new(ROW_ID[3], COLUMN_ID[2], 4)
``````

When `i=6`, `6/3 #=> 2` is the number of positive numbers that are divisible by `3`, `6/9 #=> 0` is the number of positive numbers that are divisible by `9` and `6/27 #=> 0` is the number of positive numbers that are divisible by `27`. The arguments of `Cell::new` are then computed with these values.