I was waiting to clean up my solution, but it's Thursday, so here it is. It's too late for the summary, I'm just looking to get my first successful RubyQuiz up. I also used this as my first TDD "project," which explains why it's so verbose in places. I've also included the tests, can't hurt.
class String
def each_char
for i in 0...length
yield(self[i,1])
end
end
end
class Array
alias_method :old_eq, :==
def ==(arg)
return arg == self if arg.kind_of?(Grid)
old_eq(arg)
end
end
class Range
def middle
(first+last)/2
end
def flip(i)
last-1-(i-first)
end
def flip_doubled(i)
(last*2)-1-(i-first)
end
end
module DiscreteMethod
def make_disc_meth(sym)
define_method(sym) do |*args|
temp_var = clone
temp_var.send(sym.to_s + "!",*args)
temp_var
end
end
end
class Grid
extend DiscreteMethod
attr_accessor :size, :rows, :cols, :vert, :cells
def initialize(n = 0)
@size = n
@rows = 0...n
@cols = 0...n
@vert = 0...1
@cells = {}
init_cells if n > 0
end
def init_cells
num = 1
for r in 0...size
for c in 0...size
@cells[[r,c,0]] = num; num += 1;
end
end
end
def [](r,c,v)
@cells[[r,c,v]]
end
make_disc_meth "fold"
def fold!(str)
if str.length > 1
str.each_char { |c| fold!(c) }
return
end
raise "bad attempted fold" unless ["R","T","L","B"].include?(str)
raise "bad attempted fold" if (str == "R" or str == "L") and cols.first == cols.last-1
raise "bad attempted fold" if (str == "B" or str == "T") and rows.first == rows.last-1
@cells.keys.find_all { |k| k[1] >= cols.middle }.each { |k| self[k[0],cols.flip(k[1]),vert.flip_doubled(k[2])] = @cells[k]; @cells.delete(k) } if str == "R"
@cells.keys.find_all { |k| k[1] < cols.middle }.each { |k| self[k[0],cols.flip(k[1]),vert.flip_doubled(k[2])] = @cells[k]; @cells.delete(k) } if str == "L"
@cells.keys.find_all { |k| k[0] >= rows.middle }.each { |k| self[rows.flip(k[0]),k[1],vert.flip_doubled(k[2])] = @cells[k]; @cells.delete(k) } if str == "B"
@cells.keys.find_all { |k| k[0] < rows.middle }.each { |k| self[rows.flip(k[0]),k[1],vert.flip_doubled(k[2])] = @cells[k]; @cells.delete(k) } if str == "T"
update_boundaries!(str)
end
make_disc_meth "update_boundaries"
def update_boundaries!(d)
@vert = (0...vert.last*2)
@rows = (rows.first...rows.middle) if d == "B"
@rows = (rows.middle...rows.last) if d == "T"
@cols = (cols.first...cols.middle) if d == "R"
@cols = (cols.middle...cols.last) if d == "L"
end
def []=(r,c,v,n)
@cells[[r,c,v]] = n
end
def clone
g = Grid.new
g.rows,g.cols,g.vert = rows.clone,cols.clone,vert.clone
@cells.each_key do |k|
g[k[0],k[1],k[2]] = @cells[k]
end
g
end
def ==(g)
return to_a == g if g.kind_of? Array
return false if @cells.keys.size != g.cells.keys.size
return false if size != g.size or cols != g.cols or rows != g.rows or vert != g.vert
@cells.keys.each { |k| return false if @cells[k] != g.cells[k] }
true
end
def sorted_keys
@cells.keys.sort { |a,b| x = b[2] <=> a[2]; (x = a[0] <=> b[0]) if x==0; (x = a[1] <=> b[1]) if x==0; x }
end
def to_a
a = []
sorted_keys.each { |k| a << @cells[k] }
a
end
end
def fold(r,c,str)
raise "Bad Input Dimensions" if r != c or ![1,2,4,8,16,32,64,128].include?(r)
g = Grid.new(r)
g.fold!(str)
g.to_a
end
···
-----------
require 'test/unit'
require '../grid.rb'
class TestGridFold < Test::Unit::TestCase
def setup
@two = Grid.new(2)
@two_folded_rb = Grid.new
@two_folded_rb.rows = (0...1)
@two_folded_rb.cols = (0...1)
@two_folded_rb.vert = (0...4)
@two_folded_rb[0,0,3] = 3
@two_folded_rb[0,0,2] = 4
@two_folded_rb[0,0,1] = 2
@two_folded_rb[0,0,0] = 1
@st = Grid.new(16)
end
def test_size
assert @two.size == 2
end
def test_get
assert @two[0,0,0] == 1
assert @two[0,1,0] == 2
assert @two[1,0,0] == 3
assert @two[1,1,0] == 4
end
def test_out_bounds
assert @two[2,2,2].nil?
end
def test_full_fold
g = @two.fold("RB")
assert g == @two_folded_rb,g.to_a
#assert @two.fold("TL") == [3,1,2,4]
end
def test_one_fold
g = @two.fold("R")
assert g == [2,4,1,3],g.to_a
g = g.fold("B")
assert g == @two_folded_rb
end
def test_fold_not_modify
@two.fold("R")
test_get
end
def test_fold_exc
assert @two.fold("RB") == @two_folded_rb
end
def test_init_boundaries
assert @two.rows == (0...2)
assert @two.cols == (0...2)
assert @two.vert == (0...1)
end
def test_boundaries_after_fold
assert @two.fold("R").cols == (0...1)
assert @two.fold("L").cols == (1...2)
assert @two.fold("R").rows == (0...2)
assert @two.fold("L").rows == (0...2)
end
def test_update_boundaries_r
g = @two.update_boundaries("R")
assert g.rows == (0...2)
assert g.cols == (0...1),g.cols
assert g.vert == (0...2)
end
def test_update_boundaries_t
assert @two.update_boundaries("T").rows == (1...2)
assert @two.update_boundaries("T").cols == (0...2)
assert @two.update_boundaries("T").vert == (0...2)
end
def test_update_boundaries_l
g = @two.update_boundaries("L")
assert g.rows == (0...2)
assert g.cols == (1...2),g.cols
assert g.vert == (0...2)
end
def test_update_boundaries_ll
g = @st.update_boundaries("L").update_boundaries("L")
assert g.rows == (0...16)
assert g.cols == (12...16),g.cols
assert g.vert == (0...4)
end
def test_update_boundaries_llrbt
g = @st.update_boundaries("L").update_boundaries("L").update_boundaries("R").update_boundaries("B").update_boundaries("T")
assert g.rows == (4...8)
assert g.cols == (12...14),g.cols
assert g.vert == (0...32)
end
def test_update_boundaries_no_update
@two.update_boundaries("R")
assert @two.cols == (0...2)
end
def test_update_boundaries_exc_update
@two.update_boundaries!("R")
assert @two.cols == (0...1)
end
def test_clone
g = @two.clone
assert g[0,0,0] == 1
assert g[1,1,0] == 4
g[0,0,0] = 9
assert g[0,0,0] == 9
assert @two[0,0,0] == 1
end
def test_set
@two[0,0,0] = 9
assert @two[0,0,0] == 9
end
def test_equality_grid
assert @two == Grid.new(2)
assert Grid.new(2).fold("R") == Grid.new(2).fold("R")
assert Grid.new(2).fold("RB") == Grid.new(2).fold("RB")
end
def test_equality_array
assert @two_folded_rb == [3,4,2,1]
end
def test_to_a
a = @two_folded_rb.to_a
assert a == [3,4,2,1],a
end
end