Skip to content

Instantly share code, notes, and snippets.

@wobh
Last active January 28, 2017 23:51
Show Gist options
  • Save wobh/06fd32bf46ae876bc656d0a1a165b025 to your computer and use it in GitHub Desktop.
Save wobh/06fd32bf46ae876bc656d0a1a165b025 to your computer and use it in GitHub Desktop.
Exercise implementing multidimensional arrays in Ruby
# Exercise for implementing multi-dimesional arrays in Ruby
# TODO:
# Level 0: Implement `row_major_index` and `to_a`.
# Level 1: How could tests be improved?
# Level 2: How could the interface of ArrayN be extended? Made more idiomatic?
# Multi-dimensional array
class ArrayN
def initialize (dimension, *dimensions)
@dimensions = dimension, *dimensions
@dimensions.freeze
@contents = Array.new total_size
end
attr_reader :dimensions
def total_size
@total_size ||= @dimensions.reduce(:*)
end
def rank
@rank ||= dimensions.size
end
def in_bounds? (subscript, *subscripts)
all = subscript, *subscripts
return false unless all.size == rank
rank.times do |idx|
one = all.fetch(idx)
return false if one < 0
return false unless one < dimensions.fetch(idx)
end
true
end
def fetch (subscript, *subscripts)
@contents.fetch row_major_index(subscript, *subscripts)
end
def store (item, subscript, *subscripts)
@contents[row_major_index(subscript, *subscripts)] = item
end
def row_major_index (subscript, *subscripts)
raise NotImplementedError, "Left as exercise to student."
end
def to_a
raise NotImplementedError, "Left as exercise to student."
end
end
require 'minitest/autorun'
class ArrayNTest < Minitest::Test
def setup
@subject = ArrayN.new 2, 3, 5
end
def test_total_size
assert_equal 30, @subject.total_size
end
def test_rank
assert_equal 3, @subject.rank
end
def test_in_bounds?
assert @subject.in_bounds?(1, 2, 4)
refute @subject.in_bounds?(2, 2, 4)
end
def test_store_fetch
@subject.store 0, 0, 0, 0
assert_equal 0, @subject.fetch(0, 0, 0)
end
def test_row_major_index
assert_equal 1, @subject.row_major_index(0, 0, 1)
assert_equal 5, @subject.row_major_index(0, 1, 0)
assert_equal 15, @subject.row_major_index(1, 0, 0)
end
def test_to_a
assert_equal [[[nil, nil, nil, nil, nil],
[nil, nil, nil, nil, nil],
[nil, nil, nil, nil, nil]],
[[nil, nil, nil, nil, nil],
[nil, nil, nil, nil, nil],
[nil, nil, nil, nil, nil]]], @subject.to_a
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment